[clang] [clang][ASTImporter] Fix import of variable template redeclarations. (PR #72841)
Balázs Kéri via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 22 08:13:33 PST 2023
https://github.com/balazske updated https://github.com/llvm/llvm-project/pull/72841
>From 99d6169f62862b7b1147da7fd26a85df20a0aba5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Mon, 20 Nov 2023 10:14:52 +0100
Subject: [PATCH 1/2] [clang][ASTImporter] Fix import of variable template
redeclarations.
In some cases variable templates (specially if static member of record)
were not correctly imported and an assertion "Missing call to MapImported?"
could happen.
---
clang/lib/AST/ASTImporter.cpp | 27 +++---
clang/unittests/AST/ASTImporterTest.cpp | 105 ++++++++++++++++++++++++
2 files changed, 122 insertions(+), 10 deletions(-)
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index c4e931e220f69b5..7a5e3d665328532 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6245,17 +6245,21 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
D->getTemplatedDecl()))
continue;
if (IsStructuralMatch(D, FoundTemplate)) {
- // The Decl in the "From" context has a definition, but in the
- // "To" context we already have a definition.
+ // FIXME Check for ODR error if the two definitions have
+ // different initializers?
VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate);
- if (D->isThisDeclarationADefinition() && FoundDef)
- // FIXME Check for ODR error if the two definitions have
- // different initializers?
- return Importer.MapImported(D, FoundDef);
- if (FoundTemplate->getDeclContext()->isRecord() &&
- D->getDeclContext()->isRecord())
- return Importer.MapImported(D, FoundTemplate);
-
+ if (D->getDeclContext()->isRecord()) {
+ assert(FoundTemplate->getDeclContext()->isRecord() &&
+ "Member variable template imported as non-member, "
+ "inconsistent imported AST?");
+ if (FoundDef)
+ return Importer.MapImported(D, FoundDef);
+ if (!D->isThisDeclarationADefinition())
+ return Importer.MapImported(D, FoundTemplate);
+ } else {
+ if (FoundDef && D->isThisDeclarationADefinition())
+ return Importer.MapImported(D, FoundDef);
+ }
FoundByLookup = FoundTemplate;
break;
}
@@ -6374,7 +6378,10 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
// variable.
return Importer.MapImported(D, FoundDef);
}
+ // FIXME HandleNameConflict
+ return make_error<ASTImportError>(ASTImportError::NameConflict);
}
+ return Importer.MapImported(D, D2);
} else {
TemplateArgumentListInfo ToTAInfo;
if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) {
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 5f4d8d040772cb1..d439a14b7b9985f 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5050,6 +5050,111 @@ TEST_P(ImportFriendClasses, RecordVarTemplateDecl) {
EXPECT_EQ(ToTUX, ToX);
}
+TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ template <class U>
+ constexpr int X = 1;
+ )",
+ Lang_CXX14);
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <class U>
+ constexpr int X = 2;
+ )",
+ Lang_CXX14, "input1.cc");
+ auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
+ FromTU, varTemplateDecl(hasName("X")));
+ auto *ToX = Import(FromX, Lang_CXX11);
+ // FIXME: This import should fail.
+ EXPECT_TRUE(ToX);
+}
+
+TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ struct A {
+ template <class U, class V>
+ static int X;
+ };
+ )",
+ Lang_CXX14);
+ auto *ToX = FirstDeclMatcher<VarTemplateDecl>().match(
+ ToTU, varTemplateDecl(hasName("X")));
+ ASSERT_FALSE(ToX->isThisDeclarationADefinition());
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct A {
+ template <class U>
+ static int X;
+ };
+ template <class U>
+ int A::X = 2;
+ )",
+ Lang_CXX14, "input1.cc");
+ auto *FromXDef = LastDeclMatcher<VarTemplateDecl>().match(
+ FromTU, varTemplateDecl(hasName("X")));
+ ASSERT_TRUE(FromXDef->isThisDeclarationADefinition());
+ auto *ToXDef = Import(FromXDef, Lang_CXX14);
+ EXPECT_TRUE(ToXDef);
+ EXPECT_TRUE(ToXDef->isThisDeclarationADefinition());
+ EXPECT_EQ(ToXDef->getPreviousDecl(), ToX);
+}
+
+TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateSpecializationDeclValue) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ template <class U>
+ constexpr int X = U::Value;
+ struct A { static constexpr int Value = 1; };
+ constexpr int Y = X<A>;
+ )",
+ Lang_CXX14);
+
+ auto *ToTUX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
+ ToTU, varTemplateSpecializationDecl(hasName("X")));
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <class U>
+ constexpr int X = U::Value;
+ struct A { static constexpr int Value = 1; };
+ constexpr int Y = X<A>;
+ )",
+ Lang_CXX14, "input1.cc");
+ auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
+ FromTU, varTemplateSpecializationDecl(hasName("X")));
+ auto *ToX = Import(FromX, Lang_CXX14);
+ EXPECT_TRUE(ToX);
+ EXPECT_EQ(ToTUX, ToX);
+}
+
+TEST_P(ASTImporterOptionSpecificTestBase,
+ VarTemplateSpecializationDeclValueConflict) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ template <class U>
+ constexpr int X = U::Value;
+ struct A { static constexpr int Value = 1; };
+ constexpr int Y = X<A>;
+ )",
+ Lang_CXX14);
+
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <class U>
+ constexpr int X = U::Value;
+ struct A { static constexpr int Value = 2; };
+ constexpr int Y = X<A>;
+ )",
+ Lang_CXX14, "input1.cc");
+ auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
+ FromTU, varTemplateSpecializationDecl(hasName("X")));
+ auto *ToX = Import(FromX, Lang_CXX14);
+ EXPECT_FALSE(ToX);
+}
+
TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) {
constexpr auto Code =
R"(
>From 87b62c7dde30c0a9c652edba81f4234a9999f00a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Wed, 22 Nov 2023 17:12:25 +0100
Subject: [PATCH 2/2] removed changes related to VarTemplateSpecializationDecl
---
clang/lib/AST/ASTImporter.cpp | 3 --
clang/unittests/AST/ASTImporterTest.cpp | 54 +------------------------
2 files changed, 1 insertion(+), 56 deletions(-)
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 7a5e3d665328532..e9698915d194045 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6378,10 +6378,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
// variable.
return Importer.MapImported(D, FoundDef);
}
- // FIXME HandleNameConflict
- return make_error<ASTImportError>(ASTImportError::NameConflict);
}
- return Importer.MapImported(D, D2);
} else {
TemplateArgumentListInfo ToTAInfo;
if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) {
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index d439a14b7b9985f..7d1c770108331eb 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5051,7 +5051,7 @@ TEST_P(ImportFriendClasses, RecordVarTemplateDecl) {
}
TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) {
- Decl *ToTU = getToTuDecl(
+ getToTuDecl(
R"(
template <class U>
constexpr int X = 1;
@@ -5103,58 +5103,6 @@ TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) {
EXPECT_EQ(ToXDef->getPreviousDecl(), ToX);
}
-TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateSpecializationDeclValue) {
- Decl *ToTU = getToTuDecl(
- R"(
- template <class U>
- constexpr int X = U::Value;
- struct A { static constexpr int Value = 1; };
- constexpr int Y = X<A>;
- )",
- Lang_CXX14);
-
- auto *ToTUX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
- ToTU, varTemplateSpecializationDecl(hasName("X")));
- Decl *FromTU = getTuDecl(
- R"(
- template <class U>
- constexpr int X = U::Value;
- struct A { static constexpr int Value = 1; };
- constexpr int Y = X<A>;
- )",
- Lang_CXX14, "input1.cc");
- auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
- FromTU, varTemplateSpecializationDecl(hasName("X")));
- auto *ToX = Import(FromX, Lang_CXX14);
- EXPECT_TRUE(ToX);
- EXPECT_EQ(ToTUX, ToX);
-}
-
-TEST_P(ASTImporterOptionSpecificTestBase,
- VarTemplateSpecializationDeclValueConflict) {
- Decl *ToTU = getToTuDecl(
- R"(
- template <class U>
- constexpr int X = U::Value;
- struct A { static constexpr int Value = 1; };
- constexpr int Y = X<A>;
- )",
- Lang_CXX14);
-
- Decl *FromTU = getTuDecl(
- R"(
- template <class U>
- constexpr int X = U::Value;
- struct A { static constexpr int Value = 2; };
- constexpr int Y = X<A>;
- )",
- Lang_CXX14, "input1.cc");
- auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
- FromTU, varTemplateSpecializationDecl(hasName("X")));
- auto *ToX = Import(FromX, Lang_CXX14);
- EXPECT_FALSE(ToX);
-}
-
TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) {
constexpr auto Code =
R"(
More information about the cfe-commits
mailing list