[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