[clang] [clang][ASTImporter][StructuralEquivalence] improve StructuralEquivalence on recordType (PR #76226)
Qizhi Hu via cfe-commits
cfe-commits at lists.llvm.org
Sat Dec 23 00:08:38 PST 2023
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/76226
>From 77976022454865df8bee1e4a09682a16658ed035 Mon Sep 17 00:00:00 2001
From: huqizhi <huqizhi at 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..277532696305e3 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 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"(
More information about the cfe-commits
mailing list