diff --git a/distr/flecs.c b/distr/flecs.c index 907c15e1f..226a6a8bf 100644 --- a/distr/flecs.c +++ b/distr/flecs.c @@ -18955,19 +18955,8 @@ void flecs_default_move_w_dtor(void *dst_ptr, void *src_ptr, cl->dtor(src_ptr, count, ti); } -/* Define noreturn attribute only for GCC or Clang. - * Certain builds in Windows require this for functions that abort - * (-Wmissing-noreturn) -*/ -#if defined(__GNUC__) || defined(__clang__) - #define NORETURN __attribute__((noreturn)) -#else - #define NORETURN -#endif - -NORETURN -static -void ecs_ctor_illegal( +ECS_NORETURN static +void flecs_ctor_illegal( void * dst, int32_t count, const ecs_type_info_t *ti) { @@ -18976,9 +18965,8 @@ void ecs_ctor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid constructor for %s", ti->name); } -NORETURN -static -void ecs_dtor_illegal( +ECS_NORETURN static +void flecs_dtor_illegal( void *dst, int32_t count, const ecs_type_info_t *ti) { @@ -18987,9 +18975,8 @@ void ecs_dtor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid destructor for %s", ti->name); } -NORETURN -static -void ecs_copy_illegal( +ECS_NORETURN static +void flecs_copy_illegal( void *dst, const void *src, int32_t count, @@ -19001,9 +18988,8 @@ void ecs_copy_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name); } -NORETURN -static -void ecs_move_illegal( +ECS_NORETURN static +void flecs_move_illegal( void * dst, void * src, int32_t count, @@ -19014,9 +19000,8 @@ void ecs_move_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid move assignment for %s", ti->name); } -NORETURN -static -void ecs_copy_ctor_illegal( +ECS_NORETURN static +void flecs_copy_ctor_illegal( void *dst, const void *src, int32_t count, @@ -19028,9 +19013,8 @@ void ecs_copy_ctor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid copy construct for %s", ti->name); } -NORETURN -static -void ecs_move_ctor_illegal( +ECS_NORETURN static +void flecs_move_ctor_illegal( void *dst, void *src, int32_t count, @@ -19042,7 +19026,6 @@ void ecs_move_ctor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid move construct for %s", ti->name); } - void ecs_set_hooks_id( ecs_world_t *world, ecs_entity_t component, @@ -19050,12 +19033,37 @@ void ecs_set_hooks_id( { ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL); + ecs_check(!(h->flags & ECS_TYPE_HOOKS), ECS_INVALID_PARAMETER, + "hooks flags are derived"); + + /* TODO: enable asserts once RTT API is updated */ + /* + ecs_check(!(h->flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) || !h->ctor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_DTOR_ILLEGAL) || !h->dtor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_COPY_ILLEGAL) || !h->copy, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_MOVE_ILLEGAL) || !h->move, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL) || !h->copy_ctor, + ECS_INVALID_PARAMETER, + "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL) || !h->move_ctor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL) || + !h->ctor_move_dtor, ECS_INVALID_PARAMETER, + "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL) || !h->move_dtor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + */ + flecs_stage_from_world(&world); /* Ensure that no tables have yet been created for the component */ - ecs_assert( ecs_id_in_use(world, component) == false, + ecs_check( ecs_id_in_use(world, component) == false, ECS_ALREADY_IN_USE, ecs_get_name(world, component)); - ecs_assert( ecs_id_in_use(world, ecs_pair(component, EcsWildcard)) == false, + ecs_check( ecs_id_in_use(world, ecs_pair(component, EcsWildcard)) == false, ECS_ALREADY_IN_USE, ecs_get_name(world, component)); ecs_type_info_t *ti = flecs_type_info_ensure(world, component); @@ -19107,42 +19115,42 @@ void ecs_set_hooks_id( } /* Set default copy ctor, move ctor and merge */ - ecs_type_hooks_flags_t flags = h->flags; + ecs_flags32_t flags = h->flags; if (!h->copy_ctor) { - if(flags & ECS_COPY_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { - flags |= ECS_COPY_CTOR_ILLEGAL; + if(flags & ECS_TYPE_HOOK_COPY_ILLEGAL || flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) { + flags |= ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL; } else if(h->copy) { ti->hooks.copy_ctor = flecs_default_copy_ctor; } } if (!h->move_ctor) { - if(flags & ECS_MOVE_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { - flags |= ECS_MOVE_CTOR_ILLEGAL; + if(flags & ECS_TYPE_HOOK_MOVE_ILLEGAL || flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) { + flags |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; } else if (h->move) { ti->hooks.move_ctor = flecs_default_move_ctor; } } if (!h->ctor_move_dtor) { - ecs_type_hooks_flags_t illegal_check = 0; + ecs_flags32_t illegal_check = 0; if (h->move) { - illegal_check |= ECS_MOVE_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_ILLEGAL; if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; if (h->move_ctor) { - illegal_check |= ECS_MOVE_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; /* If an explicit move ctor has been set, use callback * that uses the move ctor vs. using a ctor+move */ ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { - illegal_check |= ECS_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_CTOR_ILLEGAL; /* If no explicit move_ctor has been set, use * combination of ctor + move + dtor */ ti->hooks.ctor_move_dtor = flecs_default_ctor_w_move_w_dtor; } } else { - illegal_check |= ECS_MOVE_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; /* If no dtor has been set, this is just a move ctor */ ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; } @@ -19150,9 +19158,9 @@ void ecs_set_hooks_id( /* If move is not set but move_ctor and dtor is, we can still set * ctor_move_dtor. */ if (h->move_ctor) { - illegal_check |= ECS_MOVE_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; @@ -19160,65 +19168,63 @@ void ecs_set_hooks_id( } } if(flags & illegal_check) { - flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; + flags |= ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL; } } if (!h->move_dtor) { - ecs_type_hooks_flags_t illegal_check = 0; + ecs_flags32_t illegal_check = 0; if (h->move) { - illegal_check |= ECS_MOVE_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_ILLEGAL; if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_move_w_dtor; } else { ti->hooks.move_dtor = flecs_default_move; } } else { if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_dtor; } } if(flags & illegal_check) { - flags |= ECS_MOVE_DTOR_ILLEGAL; + flags |= ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL; } } - if(flags & ECS_CTOR_ILLEGAL) { - ti->hooks.ctor = ecs_ctor_illegal; - } - - if(flags & ECS_DTOR_ILLEGAL) { - ti->hooks.dtor = ecs_dtor_illegal; - } + ti->hooks.flags = flags; - if(flags & ECS_COPY_ILLEGAL) { - ti->hooks.copy = ecs_copy_illegal; - } + if (ti->hooks.ctor) ti->hooks.flags |= ECS_TYPE_HOOK_CTOR; + if (ti->hooks.dtor) ti->hooks.flags |= ECS_TYPE_HOOK_DTOR; + if (ti->hooks.move) ti->hooks.flags |= ECS_TYPE_HOOK_MOVE; + if (ti->hooks.move_ctor) ti->hooks.flags |= ECS_TYPE_HOOK_MOVE_CTOR; + if (ti->hooks.ctor_move_dtor) ti->hooks.flags |= ECS_TYPE_HOOK_CTOR_MOVE_DTOR; + if (ti->hooks.move_dtor) ti->hooks.flags |= ECS_TYPE_HOOK_MOVE_DTOR; + if (ti->hooks.copy) ti->hooks.flags |= ECS_TYPE_HOOK_COPY; + if (ti->hooks.copy_ctor) ti->hooks.flags |= ECS_TYPE_HOOK_COPY_CTOR; - if(flags & ECS_MOVE_ILLEGAL) { - ti->hooks.move = ecs_move_illegal; - } + if(flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) ti->hooks.ctor = flecs_ctor_illegal; + if(flags & ECS_TYPE_HOOK_DTOR_ILLEGAL) ti->hooks.dtor = flecs_dtor_illegal; + if(flags & ECS_TYPE_HOOK_COPY_ILLEGAL) ti->hooks.copy = flecs_copy_illegal; + if(flags & ECS_TYPE_HOOK_MOVE_ILLEGAL) ti->hooks.move = flecs_move_illegal; - if(flags & ECS_COPY_CTOR_ILLEGAL) { - ti->hooks.copy_ctor = ecs_copy_ctor_illegal; + if(flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL) { + ti->hooks.copy_ctor = flecs_copy_ctor_illegal; } - if(ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL) { - ti->hooks.move_ctor = ecs_move_ctor_illegal; + if(ti->hooks.flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL) { + ti->hooks.move_ctor = flecs_move_ctor_illegal; } - if(ti->hooks.flags & ECS_CTOR_MOVE_DTOR_ILLEGAL) { - ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; + if(ti->hooks.flags & ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = flecs_move_ctor_illegal; } - if(ti->hooks.flags & ECS_MOVE_DTOR_ILLEGAL) { - ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; + if(ti->hooks.flags & ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = flecs_move_ctor_illegal; } - ti->hooks.flags = flags; - error: return; } @@ -51561,7 +51567,7 @@ static ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( ecs_world_t *world, const ecs_type_info_t *ti, - ecs_type_hooks_flags_t flags, + ecs_flags32_t flags, bool ctor, bool dtor, bool move, @@ -51599,6 +51605,7 @@ ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( hooks.lifecycle_ctx_free = NULL; } hooks.flags |= flags; + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, ti->component, &hooks); return rtt_ctx; } @@ -51627,7 +51634,7 @@ void flecs_rtt_init_default_hooks_struct( * the struct itself will need to have that hook: */ int i, member_count = ecs_vec_count(&struct_info->members); ecs_member_t *members = ecs_vec_first(&struct_info->members); - ecs_type_hooks_flags_t flags = 0; + ecs_flags32_t flags = 0; for (i = 0; i < member_count; i++) { ecs_member_t *m = &members[i]; const ecs_type_info_t *member_ti = ecs_get_type_info(world, m->type); @@ -51817,7 +51824,7 @@ void flecs_rtt_init_default_hooks_array( bool dtor_hook_required = array_ti->hooks.dtor != NULL; bool move_hook_required = array_ti->hooks.move != NULL; bool copy_hook_required = array_ti->hooks.copy != NULL; - ecs_type_hooks_flags_t flags = array_ti->hooks.flags; + ecs_flags32_t flags = array_ti->hooks.flags; ecs_type_hooks_t hooks = *ecs_get_hooks_id(world, component); @@ -51856,7 +51863,7 @@ void flecs_rtt_init_default_hooks_array( } hooks.flags |= flags; - + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, component, &hooks); } @@ -51994,6 +52001,7 @@ void flecs_rtt_init_default_hooks_vector( hooks.dtor = flecs_rtt_vector_dtor; hooks.move = flecs_rtt_vector_move; hooks.copy = flecs_rtt_vector_copy; + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, component, &hooks); } @@ -52040,10 +52048,9 @@ void flecs_rtt_init_default_hooks( * could cause serializers to crash when for example inspecting string * fields. */ if (!ti || !ti->hooks.ctor) { - ecs_set_hooks_id( - world, - component, - &(ecs_type_hooks_t){.ctor = flecs_default_ctor}); + ecs_set_hooks_id(world, component, &(ecs_type_hooks_t){ + .ctor = flecs_default_ctor + }); } } } diff --git a/distr/flecs.h b/distr/flecs.h index 0b420a18b..dc7e06521 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -628,6 +628,13 @@ extern "C" { #endif #endif +/* Define noreturn attribute only for GCC or Clang. */ +#if defined(ECS_TARGET_GNU) || defined(ECS_TARGET_CLANG) + #define ECS_NORETURN __attribute__((noreturn)) +#else + #define ECS_NORETURN +#endif + /* Ignored warnings */ #if defined(ECS_TARGET_CLANG) /* Ignore unknown options so we don't have to care about the compiler version */ @@ -3523,17 +3530,38 @@ struct ecs_observer_t { * @ingroup components */ -/* Hook flags */ -#define ECS_CTOR_ILLEGAL (1 << 0) -#define ECS_DTOR_ILLEGAL (1 << 1) -#define ECS_COPY_ILLEGAL (1 << 2) -#define ECS_MOVE_ILLEGAL (1 << 3) -#define ECS_COPY_CTOR_ILLEGAL (1 << 4) -#define ECS_MOVE_CTOR_ILLEGAL (1 << 5) -#define ECS_CTOR_MOVE_DTOR_ILLEGAL (1 << 6) -#define ECS_MOVE_DTOR_ILLEGAL (1 << 7) - -typedef uint8_t ecs_type_hooks_flags_t; +/* Flags that can be used to check which hooks a type has set */ +#define ECS_TYPE_HOOK_CTOR (1 << 0) +#define ECS_TYPE_HOOK_DTOR (1 << 1) +#define ECS_TYPE_HOOK_COPY (1 << 2) +#define ECS_TYPE_HOOK_MOVE (1 << 3) +#define ECS_TYPE_HOOK_COPY_CTOR (1 << 4) +#define ECS_TYPE_HOOK_MOVE_CTOR (1 << 5) +#define ECS_TYPE_HOOK_CTOR_MOVE_DTOR (1 << 6) +#define ECS_TYPE_HOOK_MOVE_DTOR (1 << 7) + +/* Flags that can be used to set/check which hooks of a type are invalid */ +#define ECS_TYPE_HOOK_CTOR_ILLEGAL (1 << 8) +#define ECS_TYPE_HOOK_DTOR_ILLEGAL (1 << 9) +#define ECS_TYPE_HOOK_COPY_ILLEGAL (1 << 10) +#define ECS_TYPE_HOOK_MOVE_ILLEGAL (1 << 11) +#define ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL (1 << 12) +#define ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL (1 << 13) +#define ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL (1 << 14) +#define ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL (1 << 15) + +/* All valid hook flags */ +#define ECS_TYPE_HOOKS (ECS_TYPE_HOOK_CTOR|ECS_TYPE_HOOK_DTOR|\ + ECS_TYPE_HOOK_COPY|ECS_TYPE_HOOK_MOVE|ECS_TYPE_HOOK_COPY_CTOR|\ + ECS_TYPE_HOOK_MOVE_CTOR|ECS_TYPE_HOOK_CTOR_MOVE_DTOR|\ + ECS_TYPE_HOOK_MOVE_DTOR) + +/* All invalid hook flags */ +#define ECS_TYPE_HOOKS_ILLEGAL (ECS_TYPE_HOOK_CTOR_ILLEGAL|\ + ECS_TYPE_HOOK_DTOR_ILLEGAL|ECS_TYPE_HOOK_COPY_ILLEGAL|\ + ECS_TYPE_HOOK_MOVE_ILLEGAL|ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL|\ + ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL|ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL|\ + ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL) struct ecs_type_hooks_t { ecs_xtor_t ctor; /**< ctor */ @@ -3559,11 +3587,11 @@ struct ecs_type_hooks_t { * not set explicitly it will be derived from other callbacks. */ ecs_move_t move_dtor; - /** Hook flags - * Indicates if any hook is illegal. - * Setting any flag will configure an aborting hook - */ - ecs_type_hooks_flags_t flags; + /** Hook flags. + * Indicates which hooks are set for the type, and which hooks are illegal. + * When an ILLEGAL flag is set when calling ecs_set_hooks() a hook callback + * will be set that panics when called. */ + ecs_flags32_t flags; /** Callback that is invoked when an instance of a component is added. This * callback is invoked before triggers are invoked. */ @@ -3586,7 +3614,6 @@ struct ecs_type_hooks_t { ecs_ctx_free_t ctx_free; /**< Callback to free ctx */ ecs_ctx_free_t binding_ctx_free; /**< Callback to free binding_ctx */ ecs_ctx_free_t lifecycle_ctx_free; /**< Callback to free lifecycle_ctx */ - }; /** Type that contains component information (passed to ctors/dtors/...) @@ -20286,15 +20313,15 @@ namespace _ // Trivially constructible template ::value > = 0> -ecs_xtor_t ctor(ecs_type_hooks_flags_t &) { +ecs_xtor_t ctor(ecs_flags32_t &) { return nullptr; } // Not constructible by flecs template ::value > = 0> -ecs_xtor_t ctor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_CTOR_ILLEGAL; +ecs_xtor_t ctor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_CTOR_ILLEGAL; return nullptr; } @@ -20302,13 +20329,13 @@ ecs_xtor_t ctor(ecs_type_hooks_flags_t &flags) { template ::value && std::is_default_constructible::value > = 0> -ecs_xtor_t ctor(ecs_type_hooks_flags_t &) { +ecs_xtor_t ctor(ecs_flags32_t &) { return ctor_impl; } // No dtor template ::value > = 0> -ecs_xtor_t dtor(ecs_type_hooks_flags_t &) { +ecs_xtor_t dtor(ecs_flags32_t &) { return nullptr; } @@ -20316,22 +20343,22 @@ ecs_xtor_t dtor(ecs_type_hooks_flags_t &) { template ::value && ! std::is_trivially_destructible::value > = 0> -ecs_xtor_t dtor(ecs_type_hooks_flags_t &) { +ecs_xtor_t dtor(ecs_flags32_t &) { return dtor_impl; } // Assert when the type cannot be destructed template ::value > = 0> -ecs_xtor_t dtor(ecs_type_hooks_flags_t &flags) { +ecs_xtor_t dtor(ecs_flags32_t &flags) { flecs_static_assert(always_false::value, "component type must be destructible"); - flags |= ECS_DTOR_ILLEGAL; + flags |= ECS_TYPE_HOOK_DTOR_ILLEGAL; return nullptr; } // Trivially copyable template ::value > = 0> -ecs_copy_t copy(ecs_type_hooks_flags_t &) { +ecs_copy_t copy(ecs_flags32_t &) { return nullptr; } @@ -20339,8 +20366,8 @@ ecs_copy_t copy(ecs_type_hooks_flags_t &) { template ::value && ! std::is_copy_assignable::value > = 0> -ecs_copy_t copy(ecs_type_hooks_flags_t &flags) { - flags |= ECS_COPY_ILLEGAL; +ecs_copy_t copy(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_COPY_ILLEGAL; return nullptr; } @@ -20348,20 +20375,20 @@ ecs_copy_t copy(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_copyable::value > = 0> -ecs_copy_t copy(ecs_type_hooks_flags_t &) { +ecs_copy_t copy(ecs_flags32_t &) { return copy_impl; } // Trivially move assignable template ::value > = 0> -ecs_move_t move(ecs_type_hooks_flags_t &) { +ecs_move_t move(ecs_flags32_t &) { return nullptr; } // Component types must be move assignable template ::value > = 0> -ecs_move_t move(ecs_type_hooks_flags_t &flags) { - flags |= ECS_MOVE_ILLEGAL; +ecs_move_t move(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_MOVE_ILLEGAL; return nullptr; } @@ -20369,21 +20396,21 @@ ecs_move_t move(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_move_assignable::value > = 0> -ecs_move_t move(ecs_type_hooks_flags_t &) { +ecs_move_t move(ecs_flags32_t &) { return move_impl; } // Trivially copy constructible template ::value > = 0> -ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &) { +ecs_copy_t copy_ctor(ecs_flags32_t &) { return nullptr; } // No copy ctor template ::value > = 0> -ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_COPY_CTOR_ILLEGAL; +ecs_copy_t copy_ctor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL; return nullptr; } @@ -20392,21 +20419,21 @@ ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_copy_constructible::value > = 0> -ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &) { +ecs_copy_t copy_ctor(ecs_flags32_t &) { return copy_ctor_impl; } // Trivially move constructible template ::value > = 0> -ecs_move_t move_ctor(ecs_type_hooks_flags_t &) { +ecs_move_t move_ctor(ecs_flags32_t &) { return nullptr; } // Component types must be move constructible template ::value > = 0> -ecs_move_t move_ctor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t move_ctor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; return nullptr; } @@ -20414,7 +20441,7 @@ ecs_move_t move_ctor(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_move_constructible::value > = 0> -ecs_move_t move_ctor(ecs_type_hooks_flags_t &) { +ecs_move_t move_ctor(ecs_flags32_t &) { return move_ctor_impl; } @@ -20422,7 +20449,7 @@ ecs_move_t move_ctor(ecs_type_hooks_flags_t &) { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t ctor_move_dtor(ecs_flags32_t &) { return nullptr; } @@ -20430,8 +20457,8 @@ ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; +ecs_move_t ctor_move_dtor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL; return nullptr; } @@ -20441,7 +20468,7 @@ template ::value) && std::is_move_constructible::value && std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t ctor_move_dtor(ecs_flags32_t &) { return ctor_move_dtor_impl; } @@ -20449,7 +20476,7 @@ ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t move_dtor(ecs_flags32_t &) { return nullptr; } @@ -20457,8 +20484,8 @@ ecs_move_t move_dtor(ecs_type_hooks_flags_t &) { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t move_dtor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_MOVE_DTOR_ILLEGAL; +ecs_move_t move_dtor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL; return nullptr; } @@ -20468,7 +20495,7 @@ template ::value) && std::is_move_assignable::value && std::is_destructible::value > = 0> -ecs_move_t move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t move_dtor(ecs_flags32_t &) { return move_dtor_impl; } @@ -26825,7 +26852,8 @@ void register_lifecycle_actions( ecs_set_hooks_id(world, component, &cl); - if (cl.flags & ECS_MOVE_ILLEGAL || cl.flags & ECS_MOVE_CTOR_ILLEGAL) { + if (cl.flags & (ECS_TYPE_HOOK_MOVE_ILLEGAL|ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL)) + { ecs_add_id(world, component, flecs::Sparse); } } diff --git a/include/flecs.h b/include/flecs.h index ef9deca78..d1e7d8148 100644 --- a/include/flecs.h +++ b/include/flecs.h @@ -862,17 +862,38 @@ struct ecs_observer_t { * @ingroup components */ -/* Hook flags */ -#define ECS_CTOR_ILLEGAL (1 << 0) -#define ECS_DTOR_ILLEGAL (1 << 1) -#define ECS_COPY_ILLEGAL (1 << 2) -#define ECS_MOVE_ILLEGAL (1 << 3) -#define ECS_COPY_CTOR_ILLEGAL (1 << 4) -#define ECS_MOVE_CTOR_ILLEGAL (1 << 5) -#define ECS_CTOR_MOVE_DTOR_ILLEGAL (1 << 6) -#define ECS_MOVE_DTOR_ILLEGAL (1 << 7) - -typedef uint8_t ecs_type_hooks_flags_t; +/* Flags that can be used to check which hooks a type has set */ +#define ECS_TYPE_HOOK_CTOR (1 << 0) +#define ECS_TYPE_HOOK_DTOR (1 << 1) +#define ECS_TYPE_HOOK_COPY (1 << 2) +#define ECS_TYPE_HOOK_MOVE (1 << 3) +#define ECS_TYPE_HOOK_COPY_CTOR (1 << 4) +#define ECS_TYPE_HOOK_MOVE_CTOR (1 << 5) +#define ECS_TYPE_HOOK_CTOR_MOVE_DTOR (1 << 6) +#define ECS_TYPE_HOOK_MOVE_DTOR (1 << 7) + +/* Flags that can be used to set/check which hooks of a type are invalid */ +#define ECS_TYPE_HOOK_CTOR_ILLEGAL (1 << 8) +#define ECS_TYPE_HOOK_DTOR_ILLEGAL (1 << 9) +#define ECS_TYPE_HOOK_COPY_ILLEGAL (1 << 10) +#define ECS_TYPE_HOOK_MOVE_ILLEGAL (1 << 11) +#define ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL (1 << 12) +#define ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL (1 << 13) +#define ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL (1 << 14) +#define ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL (1 << 15) + +/* All valid hook flags */ +#define ECS_TYPE_HOOKS (ECS_TYPE_HOOK_CTOR|ECS_TYPE_HOOK_DTOR|\ + ECS_TYPE_HOOK_COPY|ECS_TYPE_HOOK_MOVE|ECS_TYPE_HOOK_COPY_CTOR|\ + ECS_TYPE_HOOK_MOVE_CTOR|ECS_TYPE_HOOK_CTOR_MOVE_DTOR|\ + ECS_TYPE_HOOK_MOVE_DTOR) + +/* All invalid hook flags */ +#define ECS_TYPE_HOOKS_ILLEGAL (ECS_TYPE_HOOK_CTOR_ILLEGAL|\ + ECS_TYPE_HOOK_DTOR_ILLEGAL|ECS_TYPE_HOOK_COPY_ILLEGAL|\ + ECS_TYPE_HOOK_MOVE_ILLEGAL|ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL|\ + ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL|ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL|\ + ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL) struct ecs_type_hooks_t { ecs_xtor_t ctor; /**< ctor */ @@ -898,11 +919,11 @@ struct ecs_type_hooks_t { * not set explicitly it will be derived from other callbacks. */ ecs_move_t move_dtor; - /** Hook flags - * Indicates if any hook is illegal. - * Setting any flag will configure an aborting hook - */ - ecs_type_hooks_flags_t flags; + /** Hook flags. + * Indicates which hooks are set for the type, and which hooks are illegal. + * When an ILLEGAL flag is set when calling ecs_set_hooks() a hook callback + * will be set that panics when called. */ + ecs_flags32_t flags; /** Callback that is invoked when an instance of a component is added. This * callback is invoked before triggers are invoked. */ @@ -925,7 +946,6 @@ struct ecs_type_hooks_t { ecs_ctx_free_t ctx_free; /**< Callback to free ctx */ ecs_ctx_free_t binding_ctx_free; /**< Callback to free binding_ctx */ ecs_ctx_free_t lifecycle_ctx_free; /**< Callback to free lifecycle_ctx */ - }; /** Type that contains component information (passed to ctors/dtors/...) diff --git a/include/flecs/addons/cpp/component.hpp b/include/flecs/addons/cpp/component.hpp index dd1003edd..f4702128f 100644 --- a/include/flecs/addons/cpp/component.hpp +++ b/include/flecs/addons/cpp/component.hpp @@ -114,7 +114,8 @@ void register_lifecycle_actions( ecs_set_hooks_id(world, component, &cl); - if (cl.flags & ECS_MOVE_ILLEGAL || cl.flags & ECS_MOVE_CTOR_ILLEGAL) { + if (cl.flags & (ECS_TYPE_HOOK_MOVE_ILLEGAL|ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL)) + { ecs_add_id(world, component, flecs::Sparse); } } diff --git a/include/flecs/addons/cpp/lifecycle_traits.hpp b/include/flecs/addons/cpp/lifecycle_traits.hpp index 0557b6e8d..425d28290 100644 --- a/include/flecs/addons/cpp/lifecycle_traits.hpp +++ b/include/flecs/addons/cpp/lifecycle_traits.hpp @@ -162,15 +162,15 @@ namespace _ // Trivially constructible template ::value > = 0> -ecs_xtor_t ctor(ecs_type_hooks_flags_t &) { +ecs_xtor_t ctor(ecs_flags32_t &) { return nullptr; } // Not constructible by flecs template ::value > = 0> -ecs_xtor_t ctor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_CTOR_ILLEGAL; +ecs_xtor_t ctor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_CTOR_ILLEGAL; return nullptr; } @@ -178,13 +178,13 @@ ecs_xtor_t ctor(ecs_type_hooks_flags_t &flags) { template ::value && std::is_default_constructible::value > = 0> -ecs_xtor_t ctor(ecs_type_hooks_flags_t &) { +ecs_xtor_t ctor(ecs_flags32_t &) { return ctor_impl; } // No dtor template ::value > = 0> -ecs_xtor_t dtor(ecs_type_hooks_flags_t &) { +ecs_xtor_t dtor(ecs_flags32_t &) { return nullptr; } @@ -192,22 +192,22 @@ ecs_xtor_t dtor(ecs_type_hooks_flags_t &) { template ::value && ! std::is_trivially_destructible::value > = 0> -ecs_xtor_t dtor(ecs_type_hooks_flags_t &) { +ecs_xtor_t dtor(ecs_flags32_t &) { return dtor_impl; } // Assert when the type cannot be destructed template ::value > = 0> -ecs_xtor_t dtor(ecs_type_hooks_flags_t &flags) { +ecs_xtor_t dtor(ecs_flags32_t &flags) { flecs_static_assert(always_false::value, "component type must be destructible"); - flags |= ECS_DTOR_ILLEGAL; + flags |= ECS_TYPE_HOOK_DTOR_ILLEGAL; return nullptr; } // Trivially copyable template ::value > = 0> -ecs_copy_t copy(ecs_type_hooks_flags_t &) { +ecs_copy_t copy(ecs_flags32_t &) { return nullptr; } @@ -215,8 +215,8 @@ ecs_copy_t copy(ecs_type_hooks_flags_t &) { template ::value && ! std::is_copy_assignable::value > = 0> -ecs_copy_t copy(ecs_type_hooks_flags_t &flags) { - flags |= ECS_COPY_ILLEGAL; +ecs_copy_t copy(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_COPY_ILLEGAL; return nullptr; } @@ -224,20 +224,20 @@ ecs_copy_t copy(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_copyable::value > = 0> -ecs_copy_t copy(ecs_type_hooks_flags_t &) { +ecs_copy_t copy(ecs_flags32_t &) { return copy_impl; } // Trivially move assignable template ::value > = 0> -ecs_move_t move(ecs_type_hooks_flags_t &) { +ecs_move_t move(ecs_flags32_t &) { return nullptr; } // Component types must be move assignable template ::value > = 0> -ecs_move_t move(ecs_type_hooks_flags_t &flags) { - flags |= ECS_MOVE_ILLEGAL; +ecs_move_t move(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_MOVE_ILLEGAL; return nullptr; } @@ -245,21 +245,21 @@ ecs_move_t move(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_move_assignable::value > = 0> -ecs_move_t move(ecs_type_hooks_flags_t &) { +ecs_move_t move(ecs_flags32_t &) { return move_impl; } // Trivially copy constructible template ::value > = 0> -ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &) { +ecs_copy_t copy_ctor(ecs_flags32_t &) { return nullptr; } // No copy ctor template ::value > = 0> -ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_COPY_CTOR_ILLEGAL; +ecs_copy_t copy_ctor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL; return nullptr; } @@ -268,21 +268,21 @@ ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_copy_constructible::value > = 0> -ecs_copy_t copy_ctor(ecs_type_hooks_flags_t &) { +ecs_copy_t copy_ctor(ecs_flags32_t &) { return copy_ctor_impl; } // Trivially move constructible template ::value > = 0> -ecs_move_t move_ctor(ecs_type_hooks_flags_t &) { +ecs_move_t move_ctor(ecs_flags32_t &) { return nullptr; } // Component types must be move constructible template ::value > = 0> -ecs_move_t move_ctor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_MOVE_CTOR_ILLEGAL; +ecs_move_t move_ctor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; return nullptr; } @@ -290,7 +290,7 @@ ecs_move_t move_ctor(ecs_type_hooks_flags_t &flags) { template ::value && ! std::is_trivially_move_constructible::value > = 0> -ecs_move_t move_ctor(ecs_type_hooks_flags_t &) { +ecs_move_t move_ctor(ecs_flags32_t &) { return move_ctor_impl; } @@ -298,7 +298,7 @@ ecs_move_t move_ctor(ecs_type_hooks_flags_t &) { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t ctor_move_dtor(ecs_flags32_t &) { return nullptr; } @@ -306,8 +306,8 @@ ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; +ecs_move_t ctor_move_dtor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL; return nullptr; } @@ -317,7 +317,7 @@ template ::value) && std::is_move_constructible::value && std::is_destructible::value > = 0> -ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t ctor_move_dtor(ecs_flags32_t &) { return ctor_move_dtor_impl; } @@ -325,7 +325,7 @@ ecs_move_t ctor_move_dtor(ecs_type_hooks_flags_t &) { template ::value && std::is_trivially_destructible::value > = 0> -ecs_move_t move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t move_dtor(ecs_flags32_t &) { return nullptr; } @@ -333,8 +333,8 @@ ecs_move_t move_dtor(ecs_type_hooks_flags_t &) { template ::value || ! std::is_destructible::value > = 0> -ecs_move_t move_dtor(ecs_type_hooks_flags_t &flags) { - flags |= ECS_MOVE_DTOR_ILLEGAL; +ecs_move_t move_dtor(ecs_flags32_t &flags) { + flags |= ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL; return nullptr; } @@ -344,7 +344,7 @@ template ::value) && std::is_move_assignable::value && std::is_destructible::value > = 0> -ecs_move_t move_dtor(ecs_type_hooks_flags_t &) { +ecs_move_t move_dtor(ecs_flags32_t &) { return move_dtor_impl; } diff --git a/include/flecs/private/api_defines.h b/include/flecs/private/api_defines.h index e1a431471..b88a700d4 100644 --- a/include/flecs/private/api_defines.h +++ b/include/flecs/private/api_defines.h @@ -67,6 +67,13 @@ #endif #endif +/* Define noreturn attribute only for GCC or Clang. */ +#if defined(ECS_TARGET_GNU) || defined(ECS_TARGET_CLANG) + #define ECS_NORETURN __attribute__((noreturn)) +#else + #define ECS_NORETURN +#endif + /* Ignored warnings */ #if defined(ECS_TARGET_CLANG) /* Ignore unknown options so we don't have to care about the compiler version */ diff --git a/src/addons/meta/rtt_lifecycle.c b/src/addons/meta/rtt_lifecycle.c index 461fc2d3f..172079128 100644 --- a/src/addons/meta/rtt_lifecycle.c +++ b/src/addons/meta/rtt_lifecycle.c @@ -204,7 +204,7 @@ static ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( ecs_world_t *world, const ecs_type_info_t *ti, - ecs_type_hooks_flags_t flags, + ecs_flags32_t flags, bool ctor, bool dtor, bool move, @@ -242,6 +242,7 @@ ecs_rtt_struct_ctx_t * flecs_rtt_configure_struct_hooks( hooks.lifecycle_ctx_free = NULL; } hooks.flags |= flags; + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, ti->component, &hooks); return rtt_ctx; } @@ -270,7 +271,7 @@ void flecs_rtt_init_default_hooks_struct( * the struct itself will need to have that hook: */ int i, member_count = ecs_vec_count(&struct_info->members); ecs_member_t *members = ecs_vec_first(&struct_info->members); - ecs_type_hooks_flags_t flags = 0; + ecs_flags32_t flags = 0; for (i = 0; i < member_count; i++) { ecs_member_t *m = &members[i]; const ecs_type_info_t *member_ti = ecs_get_type_info(world, m->type); @@ -460,7 +461,7 @@ void flecs_rtt_init_default_hooks_array( bool dtor_hook_required = array_ti->hooks.dtor != NULL; bool move_hook_required = array_ti->hooks.move != NULL; bool copy_hook_required = array_ti->hooks.copy != NULL; - ecs_type_hooks_flags_t flags = array_ti->hooks.flags; + ecs_flags32_t flags = array_ti->hooks.flags; ecs_type_hooks_t hooks = *ecs_get_hooks_id(world, component); @@ -499,7 +500,7 @@ void flecs_rtt_init_default_hooks_array( } hooks.flags |= flags; - + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, component, &hooks); } @@ -637,6 +638,7 @@ void flecs_rtt_init_default_hooks_vector( hooks.dtor = flecs_rtt_vector_dtor; hooks.move = flecs_rtt_vector_move; hooks.copy = flecs_rtt_vector_copy; + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, component, &hooks); } @@ -683,10 +685,9 @@ void flecs_rtt_init_default_hooks( * could cause serializers to crash when for example inspecting string * fields. */ if (!ti || !ti->hooks.ctor) { - ecs_set_hooks_id( - world, - component, - &(ecs_type_hooks_t){.ctor = flecs_default_ctor}); + ecs_set_hooks_id(world, component, &(ecs_type_hooks_t){ + .ctor = flecs_default_ctor + }); } } } diff --git a/src/world.c b/src/world.c index ffb2a2707..170c5fbfa 100644 --- a/src/world.c +++ b/src/world.c @@ -1191,19 +1191,8 @@ void flecs_default_move_w_dtor(void *dst_ptr, void *src_ptr, cl->dtor(src_ptr, count, ti); } -/* Define noreturn attribute only for GCC or Clang. - * Certain builds in Windows require this for functions that abort - * (-Wmissing-noreturn) -*/ -#if defined(__GNUC__) || defined(__clang__) - #define NORETURN __attribute__((noreturn)) -#else - #define NORETURN -#endif - -NORETURN -static -void ecs_ctor_illegal( +ECS_NORETURN static +void flecs_ctor_illegal( void * dst, int32_t count, const ecs_type_info_t *ti) { @@ -1212,9 +1201,8 @@ void ecs_ctor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid constructor for %s", ti->name); } -NORETURN -static -void ecs_dtor_illegal( +ECS_NORETURN static +void flecs_dtor_illegal( void *dst, int32_t count, const ecs_type_info_t *ti) { @@ -1223,9 +1211,8 @@ void ecs_dtor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid destructor for %s", ti->name); } -NORETURN -static -void ecs_copy_illegal( +ECS_NORETURN static +void flecs_copy_illegal( void *dst, const void *src, int32_t count, @@ -1237,9 +1224,8 @@ void ecs_copy_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name); } -NORETURN -static -void ecs_move_illegal( +ECS_NORETURN static +void flecs_move_illegal( void * dst, void * src, int32_t count, @@ -1250,9 +1236,8 @@ void ecs_move_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid move assignment for %s", ti->name); } -NORETURN -static -void ecs_copy_ctor_illegal( +ECS_NORETURN static +void flecs_copy_ctor_illegal( void *dst, const void *src, int32_t count, @@ -1264,9 +1249,8 @@ void ecs_copy_ctor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid copy construct for %s", ti->name); } -NORETURN -static -void ecs_move_ctor_illegal( +ECS_NORETURN static +void flecs_move_ctor_illegal( void *dst, void *src, int32_t count, @@ -1278,7 +1262,6 @@ void ecs_move_ctor_illegal( ecs_abort(ECS_INVALID_OPERATION, "invalid move construct for %s", ti->name); } - void ecs_set_hooks_id( ecs_world_t *world, ecs_entity_t component, @@ -1286,12 +1269,37 @@ void ecs_set_hooks_id( { ecs_check(world != NULL, ECS_INVALID_PARAMETER, NULL); + ecs_check(!(h->flags & ECS_TYPE_HOOKS), ECS_INVALID_PARAMETER, + "hooks flags are derived"); + + /* TODO: enable asserts once RTT API is updated */ + /* + ecs_check(!(h->flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) || !h->ctor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_DTOR_ILLEGAL) || !h->dtor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_COPY_ILLEGAL) || !h->copy, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_MOVE_ILLEGAL) || !h->move, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL) || !h->copy_ctor, + ECS_INVALID_PARAMETER, + "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL) || !h->move_ctor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL) || + !h->ctor_move_dtor, ECS_INVALID_PARAMETER, + "cannot specify both hook and illegal flag"); + ecs_check(!(h->flags & ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL) || !h->move_dtor, + ECS_INVALID_PARAMETER, "cannot specify both hook and illegal flag"); + */ + flecs_stage_from_world(&world); /* Ensure that no tables have yet been created for the component */ - ecs_assert( ecs_id_in_use(world, component) == false, + ecs_check( ecs_id_in_use(world, component) == false, ECS_ALREADY_IN_USE, ecs_get_name(world, component)); - ecs_assert( ecs_id_in_use(world, ecs_pair(component, EcsWildcard)) == false, + ecs_check( ecs_id_in_use(world, ecs_pair(component, EcsWildcard)) == false, ECS_ALREADY_IN_USE, ecs_get_name(world, component)); ecs_type_info_t *ti = flecs_type_info_ensure(world, component); @@ -1343,42 +1351,42 @@ void ecs_set_hooks_id( } /* Set default copy ctor, move ctor and merge */ - ecs_type_hooks_flags_t flags = h->flags; + ecs_flags32_t flags = h->flags; if (!h->copy_ctor) { - if(flags & ECS_COPY_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { - flags |= ECS_COPY_CTOR_ILLEGAL; + if(flags & ECS_TYPE_HOOK_COPY_ILLEGAL || flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) { + flags |= ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL; } else if(h->copy) { ti->hooks.copy_ctor = flecs_default_copy_ctor; } } if (!h->move_ctor) { - if(flags & ECS_MOVE_ILLEGAL || flags & ECS_CTOR_ILLEGAL) { - flags |= ECS_MOVE_CTOR_ILLEGAL; + if(flags & ECS_TYPE_HOOK_MOVE_ILLEGAL || flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) { + flags |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; } else if (h->move) { ti->hooks.move_ctor = flecs_default_move_ctor; } } if (!h->ctor_move_dtor) { - ecs_type_hooks_flags_t illegal_check = 0; + ecs_flags32_t illegal_check = 0; if (h->move) { - illegal_check |= ECS_MOVE_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_ILLEGAL; if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; if (h->move_ctor) { - illegal_check |= ECS_MOVE_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; /* If an explicit move ctor has been set, use callback * that uses the move ctor vs. using a ctor+move */ ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { - illegal_check |= ECS_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_CTOR_ILLEGAL; /* If no explicit move_ctor has been set, use * combination of ctor + move + dtor */ ti->hooks.ctor_move_dtor = flecs_default_ctor_w_move_w_dtor; } } else { - illegal_check |= ECS_MOVE_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; /* If no dtor has been set, this is just a move ctor */ ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; } @@ -1386,9 +1394,9 @@ void ecs_set_hooks_id( /* If move is not set but move_ctor and dtor is, we can still set * ctor_move_dtor. */ if (h->move_ctor) { - illegal_check |= ECS_MOVE_CTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL; if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; ti->hooks.ctor_move_dtor = flecs_default_move_ctor_w_dtor; } else { ti->hooks.ctor_move_dtor = ti->hooks.move_ctor; @@ -1396,65 +1404,63 @@ void ecs_set_hooks_id( } } if(flags & illegal_check) { - flags |= ECS_CTOR_MOVE_DTOR_ILLEGAL; + flags |= ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL; } } if (!h->move_dtor) { - ecs_type_hooks_flags_t illegal_check = 0; + ecs_flags32_t illegal_check = 0; if (h->move) { - illegal_check |= ECS_MOVE_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_MOVE_ILLEGAL; if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_move_w_dtor; } else { ti->hooks.move_dtor = flecs_default_move; } } else { if (h->dtor) { - illegal_check |= ECS_DTOR_ILLEGAL; + illegal_check |= ECS_TYPE_HOOK_DTOR_ILLEGAL; ti->hooks.move_dtor = flecs_default_dtor; } } if(flags & illegal_check) { - flags |= ECS_MOVE_DTOR_ILLEGAL; + flags |= ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL; } } - if(flags & ECS_CTOR_ILLEGAL) { - ti->hooks.ctor = ecs_ctor_illegal; - } + ti->hooks.flags = flags; - if(flags & ECS_DTOR_ILLEGAL) { - ti->hooks.dtor = ecs_dtor_illegal; - } + if (ti->hooks.ctor) ti->hooks.flags |= ECS_TYPE_HOOK_CTOR; + if (ti->hooks.dtor) ti->hooks.flags |= ECS_TYPE_HOOK_DTOR; + if (ti->hooks.move) ti->hooks.flags |= ECS_TYPE_HOOK_MOVE; + if (ti->hooks.move_ctor) ti->hooks.flags |= ECS_TYPE_HOOK_MOVE_CTOR; + if (ti->hooks.ctor_move_dtor) ti->hooks.flags |= ECS_TYPE_HOOK_CTOR_MOVE_DTOR; + if (ti->hooks.move_dtor) ti->hooks.flags |= ECS_TYPE_HOOK_MOVE_DTOR; + if (ti->hooks.copy) ti->hooks.flags |= ECS_TYPE_HOOK_COPY; + if (ti->hooks.copy_ctor) ti->hooks.flags |= ECS_TYPE_HOOK_COPY_CTOR; - if(flags & ECS_COPY_ILLEGAL) { - ti->hooks.copy = ecs_copy_illegal; - } + if(flags & ECS_TYPE_HOOK_CTOR_ILLEGAL) ti->hooks.ctor = flecs_ctor_illegal; + if(flags & ECS_TYPE_HOOK_DTOR_ILLEGAL) ti->hooks.dtor = flecs_dtor_illegal; + if(flags & ECS_TYPE_HOOK_COPY_ILLEGAL) ti->hooks.copy = flecs_copy_illegal; + if(flags & ECS_TYPE_HOOK_MOVE_ILLEGAL) ti->hooks.move = flecs_move_illegal; - if(flags & ECS_MOVE_ILLEGAL) { - ti->hooks.move = ecs_move_illegal; + if(flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL) { + ti->hooks.copy_ctor = flecs_copy_ctor_illegal; } - if(flags & ECS_COPY_CTOR_ILLEGAL) { - ti->hooks.copy_ctor = ecs_copy_ctor_illegal; + if(ti->hooks.flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL) { + ti->hooks.move_ctor = flecs_move_ctor_illegal; } - if(ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL) { - ti->hooks.move_ctor = ecs_move_ctor_illegal; + if(ti->hooks.flags & ECS_TYPE_HOOK_CTOR_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = flecs_move_ctor_illegal; } - if(ti->hooks.flags & ECS_CTOR_MOVE_DTOR_ILLEGAL) { - ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; + if(ti->hooks.flags & ECS_TYPE_HOOK_MOVE_DTOR_ILLEGAL) { + ti->hooks.ctor_move_dtor = flecs_move_ctor_illegal; } - if(ti->hooks.flags & ECS_MOVE_DTOR_ILLEGAL) { - ti->hooks.ctor_move_dtor = ecs_move_ctor_illegal; - } - - ti->hooks.flags = flags; - error: return; } diff --git a/test/core/project.json b/test/core/project.json index 5f91ab42a..972e44919 100644 --- a/test/core/project.json +++ b/test/core/project.json @@ -1197,7 +1197,29 @@ "new_w_table_ctor", "new_w_table_on_add_hook", "count_in_on_add", - "count_in_on_remove" + "count_in_on_remove", + "illegal_ctor", + "illegal_dtor", + "illegal_move", + "illegal_copy", + "illegal_move_ctor", + "illegal_move_and_ctor", + "illegal_copy_ctor", + "illegal_copy_and_ctor", + "illegal_ctor_w_ctor", + "illegal_dtor_w_dtor", + "illegal_move_w_move", + "illegal_copy_w_copy", + "illegal_move_ctor_w_move_ctor", + "illegal_copy_ctor_w_copy_ctor", + "illegal_move_ctor_w_ctor_and_move", + "illegal_copy_ctor_w_ctor_and_copy", + "ctor_flags", + "dtor_flags", + "move_flags", + "copy_flags", + "ctor_move_dtor_flags", + "move_dtor_flags" ] }, { "id": "Pairs", diff --git a/test/core/src/ComponentLifecycle.c b/test/core/src/ComponentLifecycle.c index 21e7f6279..d6de7d44f 100644 --- a/test/core/src/ComponentLifecycle.c +++ b/test/core/src/ComponentLifecycle.c @@ -3513,3 +3513,463 @@ void ComponentLifecycle_count_in_on_remove(void) { ecs_fini(world); } + +void ComponentLifecycle_illegal_ctor(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_CTOR_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.ctor(&(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_dtor(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_DTOR_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.dtor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.dtor(&(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_move(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_MOVE_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.move != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.move(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_copy(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_COPY_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.copy != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.copy(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_move_ctor(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.move_ctor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.move_ctor(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_move_and_ctor(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_CTOR_ILLEGAL|ECS_TYPE_HOOK_MOVE_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + test_assert(ti->hooks.move != NULL); + test_assert(ti->hooks.move_ctor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.move_ctor(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_copy_ctor(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.copy_ctor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.copy_ctor(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_copy_and_ctor(void) { + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .flags = ECS_TYPE_HOOK_CTOR_ILLEGAL|ECS_TYPE_HOOK_COPY_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + test_assert(ti->hooks.copy != NULL); + test_assert(ti->hooks.copy_ctor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.copy_ctor(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_ctor_w_ctor(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + test_expect_abort(); + + ecs_set_hooks(world, Position, { + .ctor = ecs_ctor(Position), + .flags = ECS_TYPE_HOOK_CTOR_ILLEGAL + }); +} + +void ComponentLifecycle_illegal_dtor_w_dtor(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + test_expect_abort(); + + ecs_set_hooks(world, Position, { + .dtor = ecs_dtor(Position), + .flags = ECS_TYPE_HOOK_DTOR_ILLEGAL + }); +} + +void ComponentLifecycle_illegal_move_w_move(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + test_expect_abort(); + + ecs_set_hooks(world, Position, { + .move = ecs_move(Position), + .flags = ECS_TYPE_HOOK_MOVE_ILLEGAL + }); +} + +void ComponentLifecycle_illegal_copy_w_copy(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + test_expect_abort(); + + ecs_set_hooks(world, Position, { + .copy = ecs_copy(Position), + .flags = ECS_TYPE_HOOK_COPY_ILLEGAL + }); +} + +void ComponentLifecycle_illegal_move_ctor_w_move_ctor(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + test_expect_abort(); + + ecs_set_hooks(world, Position, { + .move_ctor = ecs_move(Position), + .flags = ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL + }); +} + +void ComponentLifecycle_illegal_copy_ctor_w_copy_ctor(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + test_expect_abort(); + + ecs_set_hooks(world, Position, { + .copy_ctor = ecs_copy(Position), + .flags = ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL + }); +} + +void ComponentLifecycle_illegal_move_ctor_w_ctor_and_move(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .ctor = ecs_ctor(Position), + .move = ecs_move(Position), + .flags = ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + test_assert(ti->hooks.move != NULL); + test_assert(ti->hooks.move_ctor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.move_ctor(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_illegal_copy_ctor_w_ctor_and_copy(void) { + test_quarantine("27 Nov 2024"); + + install_test_abort(); + + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .ctor = ecs_ctor(Position), + .copy = ecs_copy(Position), + .flags = ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + test_assert(ti->hooks.copy != NULL); + test_assert(ti->hooks.copy_ctor != NULL); + + /* Make sure hook panics */ + test_expect_abort(); + ti->hooks.copy_ctor(&(Position){10, 20}, &(Position){10, 20}, 1, ti); + + ecs_fini(world); +} + +void ComponentLifecycle_ctor_flags(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .ctor = ecs_ctor(Position), + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + test_assert(ti->hooks.flags == ECS_TYPE_HOOK_CTOR); + + ecs_fini(world); +} + +void ComponentLifecycle_dtor_flags(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .dtor = ecs_ctor(Position), + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + test_assert(ti->hooks.dtor != NULL); + test_assert(ti->hooks.move_dtor != NULL); + test_assert(ti->hooks.flags == + (ECS_TYPE_HOOK_CTOR|ECS_TYPE_HOOK_DTOR|ECS_TYPE_HOOK_MOVE_DTOR)); + + ecs_fini(world); +} + +void ComponentLifecycle_move_flags(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .move = ecs_move(Position), + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.move != NULL); + test_assert(ti->hooks.flags == + (ECS_TYPE_HOOK_CTOR|ECS_TYPE_HOOK_MOVE|ECS_TYPE_HOOK_MOVE_CTOR| + ECS_TYPE_HOOK_CTOR_MOVE_DTOR|ECS_TYPE_HOOK_MOVE_DTOR)); + + ecs_fini(world); +} + +void ComponentLifecycle_copy_flags(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .copy = ecs_copy(Position), + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.copy != NULL); + test_assert(ti->hooks.flags == + (ECS_TYPE_HOOK_CTOR|ECS_TYPE_HOOK_COPY|ECS_TYPE_HOOK_COPY_CTOR)); + + ecs_fini(world); +} + +void ComponentLifecycle_ctor_move_dtor_flags(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .ctor = ecs_ctor(Position), + .dtor = ecs_dtor(Position), + .move = ecs_move(Position) + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.ctor != NULL); + test_assert(ti->hooks.dtor != NULL); + test_assert(ti->hooks.move != NULL); + test_assert(ti->hooks.move_ctor != NULL); + test_assert(ti->hooks.ctor_move_dtor != NULL); + test_assert(ti->hooks.move_dtor != NULL); + test_assert(ti->hooks.flags == + (ECS_TYPE_HOOK_CTOR|ECS_TYPE_HOOK_DTOR|ECS_TYPE_HOOK_MOVE| + ECS_TYPE_HOOK_MOVE_CTOR|ECS_TYPE_HOOK_CTOR_MOVE_DTOR|ECS_TYPE_HOOK_MOVE_DTOR)); + + ecs_fini(world); +} + +void ComponentLifecycle_move_dtor_flags(void) { + ecs_world_t *world = ecs_mini(); + + ECS_COMPONENT(world, Position); + + ecs_set_hooks(world, Position, { + .dtor = ecs_dtor(Position), + .move = ecs_move(Position) + }); + + const ecs_type_info_t *ti = ecs_get_type_info(world, ecs_id(Position)); + test_assert(ti != NULL); + test_assert(ti->hooks.dtor != NULL); + test_assert(ti->hooks.move != NULL); + test_assert(ti->hooks.move_dtor != NULL); + test_assert(ti->hooks.flags == + (ECS_TYPE_HOOK_CTOR|ECS_TYPE_HOOK_MOVE_CTOR|ECS_TYPE_HOOK_CTOR_MOVE_DTOR| + ECS_TYPE_HOOK_DTOR|ECS_TYPE_HOOK_MOVE|ECS_TYPE_HOOK_MOVE_DTOR)); + + ecs_fini(world); +} diff --git a/test/core/src/main.c b/test/core/src/main.c index 235e01600..b843d41a4 100644 --- a/test/core/src/main.c +++ b/test/core/src/main.c @@ -1143,6 +1143,28 @@ void ComponentLifecycle_new_w_table_ctor(void); void ComponentLifecycle_new_w_table_on_add_hook(void); void ComponentLifecycle_count_in_on_add(void); void ComponentLifecycle_count_in_on_remove(void); +void ComponentLifecycle_illegal_ctor(void); +void ComponentLifecycle_illegal_dtor(void); +void ComponentLifecycle_illegal_move(void); +void ComponentLifecycle_illegal_copy(void); +void ComponentLifecycle_illegal_move_ctor(void); +void ComponentLifecycle_illegal_move_and_ctor(void); +void ComponentLifecycle_illegal_copy_ctor(void); +void ComponentLifecycle_illegal_copy_and_ctor(void); +void ComponentLifecycle_illegal_ctor_w_ctor(void); +void ComponentLifecycle_illegal_dtor_w_dtor(void); +void ComponentLifecycle_illegal_move_w_move(void); +void ComponentLifecycle_illegal_copy_w_copy(void); +void ComponentLifecycle_illegal_move_ctor_w_move_ctor(void); +void ComponentLifecycle_illegal_copy_ctor_w_copy_ctor(void); +void ComponentLifecycle_illegal_move_ctor_w_ctor_and_move(void); +void ComponentLifecycle_illegal_copy_ctor_w_ctor_and_copy(void); +void ComponentLifecycle_ctor_flags(void); +void ComponentLifecycle_dtor_flags(void); +void ComponentLifecycle_move_flags(void); +void ComponentLifecycle_copy_flags(void); +void ComponentLifecycle_ctor_move_dtor_flags(void); +void ComponentLifecycle_move_dtor_flags(void); // Testsuite 'Pairs' void Pairs_type_w_one_pair(void); @@ -6689,6 +6711,94 @@ bake_test_case ComponentLifecycle_testcases[] = { { "count_in_on_remove", ComponentLifecycle_count_in_on_remove + }, + { + "illegal_ctor", + ComponentLifecycle_illegal_ctor + }, + { + "illegal_dtor", + ComponentLifecycle_illegal_dtor + }, + { + "illegal_move", + ComponentLifecycle_illegal_move + }, + { + "illegal_copy", + ComponentLifecycle_illegal_copy + }, + { + "illegal_move_ctor", + ComponentLifecycle_illegal_move_ctor + }, + { + "illegal_move_and_ctor", + ComponentLifecycle_illegal_move_and_ctor + }, + { + "illegal_copy_ctor", + ComponentLifecycle_illegal_copy_ctor + }, + { + "illegal_copy_and_ctor", + ComponentLifecycle_illegal_copy_and_ctor + }, + { + "illegal_ctor_w_ctor", + ComponentLifecycle_illegal_ctor_w_ctor + }, + { + "illegal_dtor_w_dtor", + ComponentLifecycle_illegal_dtor_w_dtor + }, + { + "illegal_move_w_move", + ComponentLifecycle_illegal_move_w_move + }, + { + "illegal_copy_w_copy", + ComponentLifecycle_illegal_copy_w_copy + }, + { + "illegal_move_ctor_w_move_ctor", + ComponentLifecycle_illegal_move_ctor_w_move_ctor + }, + { + "illegal_copy_ctor_w_copy_ctor", + ComponentLifecycle_illegal_copy_ctor_w_copy_ctor + }, + { + "illegal_move_ctor_w_ctor_and_move", + ComponentLifecycle_illegal_move_ctor_w_ctor_and_move + }, + { + "illegal_copy_ctor_w_ctor_and_copy", + ComponentLifecycle_illegal_copy_ctor_w_ctor_and_copy + }, + { + "ctor_flags", + ComponentLifecycle_ctor_flags + }, + { + "dtor_flags", + ComponentLifecycle_dtor_flags + }, + { + "move_flags", + ComponentLifecycle_move_flags + }, + { + "copy_flags", + ComponentLifecycle_copy_flags + }, + { + "ctor_move_dtor_flags", + ComponentLifecycle_ctor_move_dtor_flags + }, + { + "move_dtor_flags", + ComponentLifecycle_move_dtor_flags } }; @@ -11389,7 +11499,7 @@ static bake_test_suite suites[] = { "ComponentLifecycle", ComponentLifecycle_setup, NULL, - 98, + 120, ComponentLifecycle_testcases }, { diff --git a/test/meta/src/RuntimeTypes.c b/test/meta/src/RuntimeTypes.c index 0cea4f412..6a789450c 100644 --- a/test/meta/src/RuntimeTypes.c +++ b/test/meta/src/RuntimeTypes.c @@ -225,6 +225,7 @@ void RuntimeTypes_ctor(void) { ecs_type_hooks_t hooks = nested_struct_ti->hooks; hooks.ctor = test_ctor; /* only define a constructor for "NestedStruct" */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -271,7 +272,8 @@ void RuntimeTypes_ctor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -279,9 +281,9 @@ void RuntimeTypes_ctor_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal constructor too: */ - test_assert(test_struct_ti->hooks.flags & ECS_CTOR_ILLEGAL); - test_assert(test_struct_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); - test_assert(test_struct_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.dtor == NULL); @@ -301,7 +303,7 @@ void RuntimeTypes_dtor(void) { ecs_type_hooks_t hooks = nested_struct_ti->hooks; hooks.dtor = test_dtor; /* only set a destructor */ - + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -346,7 +348,8 @@ void RuntimeTypes_dtor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -354,7 +357,7 @@ void RuntimeTypes_dtor_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal constructor too: */ - test_assert(test_struct_ti->hooks.flags & ECS_DTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_DTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.ctor != NULL); @@ -373,8 +376,8 @@ void RuntimeTypes_move(void) { /* Define NestedStruct: */ const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.move = test_move; /* Only define a move hook. */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -437,7 +440,8 @@ void RuntimeTypes_move_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -445,8 +449,8 @@ void RuntimeTypes_move_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal move hook too: */ - test_assert(test_struct_ti->hooks.flags & ECS_MOVE_ILLEGAL); - test_assert(test_struct_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_MOVE_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.ctor != NULL); @@ -465,8 +469,8 @@ void RuntimeTypes_copy(void) { define_nested_struct(world); const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.copy = test_copy; /* only set a copy hook */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -525,7 +529,8 @@ void RuntimeTypes_copy_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define TestStruct, which has two "NestedStruct" members. @@ -533,8 +538,8 @@ void RuntimeTypes_copy_illegal(void) { const ecs_type_info_t *test_struct_ti = define_test_struct(world); /* TestStruct should have an illegal move hook too: */ - test_assert(test_struct_ti->hooks.flags & ECS_COPY_ILLEGAL); - test_assert(test_struct_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_COPY_ILLEGAL); + test_assert(test_struct_ti->hooks.flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_struct_ti->hooks.ctor != NULL); @@ -722,6 +727,7 @@ void define_resource_handle( if (copy) hooks.copy = ResourceHandle_copy; + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, resource_handle, &hooks); } @@ -817,7 +823,8 @@ void RuntimeTypes_array_ctor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_CTOR_ILLEGAL; /* mark constructor for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -828,9 +835,9 @@ void RuntimeTypes_array_ctor_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal constructor too: */ - test_assert(test_arr_ti->hooks.flags & ECS_CTOR_ILLEGAL); - test_assert(test_arr_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); - test_assert(test_arr_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.dtor == NULL); @@ -909,7 +916,8 @@ void RuntimeTypes_array_dtor_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_DTOR_ILLEGAL; /* mark destructor for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -920,7 +928,7 @@ void RuntimeTypes_array_dtor_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal destructor too: */ - test_assert(test_arr_ti->hooks.flags & ECS_DTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_DTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.ctor != NULL); @@ -1039,7 +1047,8 @@ void RuntimeTypes_array_move_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_MOVE_ILLEGAL; /* mark move hook for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -1050,8 +1059,8 @@ void RuntimeTypes_array_move_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal move hook too: */ - test_assert(test_arr_ti->hooks.flags & ECS_MOVE_ILLEGAL); - test_assert(test_arr_ti->hooks.flags & ECS_MOVE_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_MOVE_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_MOVE_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.ctor != NULL); @@ -1143,7 +1152,8 @@ void RuntimeTypes_array_copy_illegal(void) { const ecs_type_info_t *nested_struct_ti = define_nested_struct(world); ecs_type_hooks_t hooks = nested_struct_ti->hooks; - hooks.flags |= ECS_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ + hooks.flags |= ECS_TYPE_HOOK_COPY_ILLEGAL; /* mark copy hook for "NestedStruct" as illegal */ + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, nested_struct, &hooks); /* Define test_arr, as an array of "NestedStruct". @@ -1154,8 +1164,8 @@ void RuntimeTypes_array_copy_illegal(void) { const ecs_type_info_t* test_arr_ti = ecs_get_type_info(world, test_arr); /* test_arr should have an illegal copy hook too: */ - test_assert(test_arr_ti->hooks.flags & ECS_COPY_ILLEGAL); - test_assert(test_arr_ti->hooks.flags & ECS_COPY_CTOR_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_COPY_ILLEGAL); + test_assert(test_arr_ti->hooks.flags & ECS_TYPE_HOOK_COPY_CTOR_ILLEGAL); /* No other hooks should've been set: */ test_assert(test_arr_ti->hooks.ctor != NULL); @@ -1306,6 +1316,7 @@ ecs_entity_t define_ResourceHandle_opaque( hooks.dtor = ResourceHandle_dtor; hooks.move = ResourceHandle_move; hooks.copy = ResourceHandle_copy; + hooks.flags &= ECS_TYPE_HOOKS_ILLEGAL; ecs_set_hooks_id(world, ecs_id(ResourceHandle), &hooks); /* Create struct type that describes the structure of ResourceHandle */