[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