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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits