[clang] [clang][ASTImporter] Fix import of variable template redeclarations. (PR #72841)

Balázs Kéri via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 5 07:07:48 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/3] [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 c4e931e220f69..7a5e3d6653285 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 5f4d8d040772c..d439a14b7b998 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/3] 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 7a5e3d6653285..e9698915d1940 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 d439a14b7b998..7d1c770108331 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"(

>From 1edb738afb2e3c9d348e825ec4d999d12d074ceb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Tue, 5 Dec 2023 16:06:48 +0100
Subject: [PATCH 3/3] fixed wrong test code

---
 clang/unittests/AST/ASTImporterTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 7d1c770108331..10a8b3be11485 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5075,7 +5075,7 @@ TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) {
   Decl *ToTU = getToTuDecl(
       R"(
       struct A {
-        template <class U, class V>
+        template <class U>
         static int X;
       };
       )",



More information about the cfe-commits mailing list