https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/76226
>From ab1ace9573588153f1e8caf992a6abda3322c6a7 Mon Sep 17 00:00:00 2001 From: huqizhi <huqi...@feysh.com> Date: Fri, 22 Dec 2023 17:56:32 +0800 Subject: [PATCH] [clang][ASTImporter][StructuralEquivalence] improve StructuralEquivalence on recordType --- clang/lib/AST/ASTStructuralEquivalence.cpp | 13 ++++++++--- .../AST/StructuralEquivalenceTest.cpp | 23 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 6bb4bf14b873d7..73b3b2a9524a7b 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; } + auto *D1Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC1); + auto *D2Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC2); + if (nullptr != D1Spec && nullptr != D2Spec && + !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 different context (namespace), these should be // different. 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"( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits