Browse Source

meta: self assignment for meta any

skypjack 1 year ago
parent
commit
2de5b6dd87
2 changed files with 71 additions and 5 deletions
  1. 10 5
      src/entt/meta/meta.hpp
  2. 61 0
      test/entt/meta/meta_any.cpp

+ 10 - 5
src/entt/meta/meta.hpp

@@ -328,11 +328,14 @@ public:
      * @return This meta any object.
      */
     meta_any &operator=(const meta_any &other) {
-        release();
-        storage = other.storage;
-        ctx = other.ctx;
-        node = other.node;
-        vtable = other.vtable;
+        if(this != &other) {
+            release();
+            storage = other.storage;
+            ctx = other.ctx;
+            node = other.node;
+            vtable = other.vtable;
+        }
+
         return *this;
     }
 
@@ -342,6 +345,8 @@ public:
      * @return This meta any object.
      */
     meta_any &operator=(meta_any &&other) noexcept {
+        ENTT_ASSERT(this != &other, "Self move assignment");
+
         release();
         storage = std::move(other.storage);
         ctx = other.ctx;

+ 61 - 0
test/entt/meta/meta_any.cpp

@@ -277,6 +277,19 @@ TEST_F(MetaAny, SBOCopyAssignment) {
     ASSERT_NE(other, entt::meta_any{0});
 }
 
+TEST_F(MetaAny, SBOSelfCopyAssignment) {
+    entt::meta_any any{3};
+
+    // avoid warnings due to self-assignment
+    any = *&any;
+
+    ASSERT_TRUE(any);
+    ASSERT_FALSE(any.try_cast<std::size_t>());
+    ASSERT_EQ(any.cast<int>(), 3);
+    ASSERT_EQ(any, entt::meta_any{3});
+    ASSERT_NE(any, entt::meta_any{0});
+}
+
 TEST_F(MetaAny, SBOMoveConstruction) {
     entt::meta_any any{3};
     entt::meta_any other{std::move(any)};
@@ -306,6 +319,13 @@ TEST_F(MetaAny, SBOMoveAssignment) {
     ASSERT_NE(other, entt::meta_any{0});
 }
 
+ENTT_DEBUG_TEST_F(MetaAnyDeathTest, SBOSelfMoveAssignment) {
+    entt::meta_any any{3};
+
+    // avoid warnings due to self-assignment
+    ASSERT_DEATH(any = std::move(*&any), "");
+}
+
 TEST_F(MetaAny, SBODirectAssignment) {
     entt::meta_any any{};
     any = 3;
@@ -547,6 +567,20 @@ TEST_F(MetaAny, NoSBOCopyAssignment) {
     ASSERT_NE(other, fat{});
 }
 
+TEST_F(MetaAny, NoSBOSelfCopyAssignment) {
+    const fat instance{.1, .2, .3, .4};
+    entt::meta_any any{instance};
+
+    // avoid warnings due to self-assignment
+    any = *&any;
+
+    ASSERT_TRUE(any);
+    ASSERT_FALSE(any.try_cast<std::size_t>());
+    ASSERT_EQ(any.cast<fat>(), instance);
+    ASSERT_EQ(any, entt::meta_any{instance});
+    ASSERT_NE(any, fat{});
+}
+
 TEST_F(MetaAny, NoSBOMoveConstruction) {
     const fat instance{.1, .2, .3, .4};
     entt::meta_any any{instance};
@@ -578,6 +612,14 @@ TEST_F(MetaAny, NoSBOMoveAssignment) {
     ASSERT_NE(other, fat{});
 }
 
+ENTT_DEBUG_TEST_F(MetaAnyDeathTest, NoSBOSelfMoveAssignment) {
+    const fat instance{.1, .2, .3, .4};
+    entt::meta_any any{instance};
+
+    // avoid warnings due to self-assignment
+    ASSERT_DEATH(any = std::move(*&any), "");
+}
+
 TEST_F(MetaAny, NoSBODirectAssignment) {
     const fat instance{.1, .2, .3, .4};
     entt::meta_any any{};
@@ -755,6 +797,18 @@ TEST_F(MetaAny, VoidCopyAssignment) {
     ASSERT_EQ(other, entt::meta_any{std::in_place_type<void>});
 }
 
+TEST_F(MetaAny, VoidSelfCopyAssignment) {
+    entt::meta_any any{std::in_place_type<void>};
+
+    // avoid warnings due to self-assignment
+    any = *&any;
+
+    ASSERT_TRUE(any);
+    ASSERT_FALSE(any.try_cast<std::size_t>());
+    ASSERT_EQ(any.type(), entt::resolve<void>());
+    ASSERT_EQ(any, entt::meta_any{std::in_place_type<void>});
+}
+
 TEST_F(MetaAny, VoidMoveConstruction) {
     entt::meta_any any{std::in_place_type<void>};
     const entt::meta_any other{std::move(any)};
@@ -780,6 +834,13 @@ TEST_F(MetaAny, VoidMoveAssignment) {
     ASSERT_EQ(other, entt::meta_any{std::in_place_type<void>});
 }
 
+ENTT_DEBUG_TEST_F(MetaAnyDeathTest, VoidSelfMoveAssignment) {
+    entt::meta_any any{std::in_place_type<void>};
+
+    // avoid warnings due to self-assignment
+    ASSERT_DEATH(any = std::move(*&any), "");
+}
+
 TEST_F(MetaAny, SBOMoveInvalidate) {
     entt::meta_any any{3};
     entt::meta_any other{std::move(any)};