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

via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 5 04:53:08 PST 2024


Author: Qizhi Hu
Date: 2024-01-05T20:53:04+08:00
New Revision: 86127305d4602801ba7ffdc74377ed67b18819ac

URL: https://github.com/llvm/llvm-project/commit/86127305d4602801ba7ffdc74377ed67b18819ac
DIFF: https://github.com/llvm/llvm-project/commit/86127305d4602801ba7ffdc74377ed67b18819ac.diff

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

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.
fix [issue](https://github.com/llvm/llvm-project/issues/65913)

Co-authored-by: huqizhi <836744285 at qq.com>

Added: 
    

Modified: 
    clang/lib/AST/ASTStructuralEquivalence.cpp
    clang/unittests/AST/StructuralEquivalenceTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 1f492b051e0341..a9e0d1698a9178 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1463,8 +1463,9 @@ IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context,
 }
 
 /// Determine if context of a class is equivalent.
-static bool IsRecordContextStructurallyEquivalent(RecordDecl *D1,
-                                                  RecordDecl *D2) {
+static bool
+IsRecordContextStructurallyEquivalent(StructuralEquivalenceContext &Context,
+                                      RecordDecl *D1, RecordDecl *D2) {
   // The context should be completely equal, including anonymous and inline
   // namespaces.
   // We compare objects as part of full translation units, not subtrees of
@@ -1491,6 +1492,12 @@ static bool IsRecordContextStructurallyEquivalent(RecordDecl *D1,
         return false;
     }
 
+    if (auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1)) {
+      auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2);
+      if (!IsStructurallyEquivalent(Context, D1Spec, D2Spec))
+        return false;
+    }
+
     DC1 = DC1->getParent()->getNonTransparentContext();
     DC2 = DC2->getParent()->getNonTransparentContext();
   }
@@ -1544,7 +1551,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
   // If the records occur in 
diff erent context (namespace), these should be
   // 
diff erent. This is specially important if the definition of one or both
   // records is missing.
-  if (!IsRecordContextStructurallyEquivalent(D1, D2))
+  if (!IsRecordContextStructurallyEquivalent(Context, D1, D2))
     return false;
 
   // If both declarations are class template specializations, we know

diff  --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 44d950cfe758f1..22c7b82460f0a0 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -1024,6 +1024,29 @@ TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextInNamespace) {
   EXPECT_TRUE(testStructuralMatch(Decls));
 }
 
+TEST_F(StructuralEquivalenceRecordContextTest,
+       ClassTemplateSpecializationContext) {
+  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"(


        


More information about the cfe-commits mailing list