[clang] [clang][ASTImporter][StructuralEquivalence] improve StructuralEquivalence on recordType (PR #76226)

via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 22 02:02:55 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Qizhi Hu (jcsxky)

<details>
<summary>Changes</summary>

Types comparison in `StructuralEquivalence` ignores its `DeclContext` when they are generated by template specialization implicitly and this will produce incorrect result. Add comparison of `DeclContext` of ClassTemplateSpecializationDecl to improve result.

---
Full diff: https://github.com/llvm/llvm-project/pull/76226.diff


2 Files Affected:

- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+12-3) 
- (modified) clang/unittests/AST/StructuralEquivalenceTest.cpp (+22) 


``````````diff
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 6bb4bf14b873d7..7c04c09bb80874 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1107,11 +1107,20 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
   }
 
   case Type::Record:
-  case Type::Enum:
-    if (!IsStructurallyEquivalent(Context, cast<TagType>(T1)->getDecl(),
-                                  cast<TagType>(T2)->getDecl()))
+  case Type::Enum: {
+    auto *D1 = cast<TagType>(T1)->getDecl();
+    auto *D2 = cast<TagType>(T2)->getDecl();
+    if (!IsStructurallyEquivalent(Context, D1, D2))
+      return false;
+    auto *D1Spec =
+        dyn_cast_or_null<ClassTemplateSpecializationDecl>(D1->getDeclContext());
+    auto *D2Spec =
+        dyn_cast_or_null<ClassTemplateSpecializationDecl>(D2->getDeclContext());
+    if (nullptr != D1Spec && nullptr != D2Spec &&
+        !IsStructurallyEquivalent(Context, D1Spec, D2Spec))
       return false;
     break;
+  }
 
   case Type::TemplateTypeParm: {
     const auto *Parm1 = cast<TemplateTypeParmType>(T1);
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 44d950cfe758f1..b54d149152e105 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -1024,6 +1024,28 @@ TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextInNamespace) {
   EXPECT_TRUE(testStructuralMatch(Decls));
 }
 
+TEST_F(StructuralEquivalenceRecordContextTest, RecordWithinTemplateClass) {
+  std::string Code =
+      R"(
+      template <typename T> struct O {
+        struct M {};
+      };
+      )";
+  auto t = makeDecls<VarDecl>(Code + R"(
+      typedef O<int>::M MT1;
+      MT1 A;
+      )",
+                              Code + R"(
+      namespace {
+        struct I {};
+      } // namespace
+      typedef O<I>::M MT2;
+      MT2 A;
+      )",
+                              Lang_CXX11, varDecl(hasName("A")));
+  EXPECT_FALSE(testStructuralMatch(t));
+}
+
 TEST_F(StructuralEquivalenceTest, NamespaceOfRecordMember) {
   auto Decls = makeNamedDecls(
       R"(

``````````

</details>


https://github.com/llvm/llvm-project/pull/76226


More information about the cfe-commits mailing list