Просмотр исходного кода

meta: avoid risk of name clashing on meta types and meta data members

Michele Caini 4 лет назад
Родитель
Сommit
a9cefcb823
3 измененных файлов с 35 добавлено и 6 удалено
  1. 9 6
      src/entt/meta/factory.hpp
  2. 13 0
      test/entt/meta/meta_data.cpp
  3. 13 0
      test/entt/meta/meta_type.cpp

+ 9 - 6
src/entt/meta/factory.hpp

@@ -159,10 +159,11 @@ struct meta_factory<Type> {
     auto type(const id_type id = type_hash<Type>::value()) {
     auto type(const id_type id = type_hash<Type>::value()) {
         auto * const node = internal::meta_info<Type>::resolve();
         auto * const node = internal::meta_info<Type>::resolve();
 
 
+        meta_range<internal::meta_type_node *, internal::meta_type_node> range{*internal::meta_context::global()};
+        ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id, node](const auto *curr) { return curr != node && curr->id == id; }) == range.cend(), "Duplicate identifier");
         node->id = id;
         node->id = id;
 
 
-        if(meta_range<internal::meta_type_node *, internal::meta_type_node> range{*internal::meta_context::global()}; std::find(range.cbegin(), range.cend(), node) == range.cend()) {
-            ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr->id == id; }) == range.cend(), "Duplicate identifier");
+        if(std::find(range.cbegin(), range.cend(), node) == range.cend()) {
             node->next = *internal::meta_context::global();
             node->next = *internal::meta_context::global();
             *internal::meta_context::global() = node;
             *internal::meta_context::global() = node;
         }
         }
@@ -411,10 +412,11 @@ struct meta_factory<Type> {
                 &meta_getter<Type, Data, Policy>
                 &meta_getter<Type, Data, Policy>
             };
             };
 
 
+            meta_range<internal::meta_data_node *, internal::meta_data_node> range{type->data};
+            ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr != &node && curr->id == id; }) == range.cend(), "Duplicate identifier");
             node.id = id;
             node.id = id;
 
 
-            if(meta_range<internal::meta_data_node *, internal::meta_data_node> range{type->data}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
-                ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr->id == id; }) == range.cend(), "Duplicate identifier");
+            if(std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
                 node.next = type->data;
                 node.next = type->data;
                 type->data = &node;
                 type->data = &node;
             }
             }
@@ -460,10 +462,11 @@ struct meta_factory<Type> {
             &meta_getter<Type, Getter, Policy>
             &meta_getter<Type, Getter, Policy>
         };
         };
 
 
+        meta_range<internal::meta_data_node *, internal::meta_data_node> range{type->data};
+        ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr != &node && curr->id == id; }) == range.cend(), "Duplicate identifier");
         node.id = id;
         node.id = id;
 
 
-        if(meta_range<internal::meta_data_node *, internal::meta_data_node> range{type->data}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
-            ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr->id == id; }) == range.cend(), "Duplicate identifier");
+        if(std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
             node.next = type->data;
             node.next = type->data;
             type->data = &node;
             type->data = &node;
         }
         }

+ 13 - 0
test/entt/meta/meta_data.cpp

@@ -515,3 +515,16 @@ TEST_F(MetaData, ReRegistration) {
     ASSERT_FALSE(type.data("value"_hs));
     ASSERT_FALSE(type.data("value"_hs));
     ASSERT_TRUE(type.data("field"_hs));
     ASSERT_TRUE(type.data("field"_hs));
 }
 }
+
+TEST_F(MetaData, NameCollision) {
+    using namespace entt::literals;
+
+    ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::j>("j"_hs));
+    ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs));
+
+    ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::j>("cj"_hs));
+    ASSERT_FALSE(entt::resolve<clazz_t>().data("j"_hs));
+    ASSERT_TRUE(entt::resolve<clazz_t>().data("cj"_hs));
+
+    ASSERT_DEATH(entt::meta<clazz_t>().data<&clazz_t::j>("i"_hs), "");
+}

+ 13 - 0
test/entt/meta/meta_type.cpp

@@ -640,3 +640,16 @@ TEST_F(MetaType, ReRegistration) {
     ASSERT_TRUE(entt::resolve("real"_hs));
     ASSERT_TRUE(entt::resolve("real"_hs));
     ASSERT_TRUE(entt::resolve("real"_hs).data("var"_hs));
     ASSERT_TRUE(entt::resolve("real"_hs).data("var"_hs));
 }
 }
+
+TEST_F(MetaType, NameCollision) {
+    using namespace entt::literals;
+
+    ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().type("clazz"_hs));
+    ASSERT_TRUE(entt::resolve("clazz"_hs));
+
+    ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().type("quux"_hs));
+    ASSERT_FALSE(entt::resolve("clazz"_hs));
+    ASSERT_TRUE(entt::resolve("quux"_hs));
+
+    ASSERT_DEATH(entt::meta<clazz_t>().type("abstract"_hs), "");
+}