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

Qizhi Hu via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 13 23:22:40 PST 2023


=?utf-8?q?Balázs_Kéri?= <balazs.keri at ericsson.com>,
=?utf-8?q?Balázs_Kéri?= <balazs.keri at ericsson.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/72841 at github.com>


================
@@ -5050,6 +5050,59 @@ TEST_P(ImportFriendClasses, RecordVarTemplateDecl) {
   EXPECT_EQ(ToTUX, ToX);
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) {
+  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);
----------------
jcsxky wrote:

If import `X` should fail, What about this case in `ASTImporterGenericRedeclTest.cpp`
```cpp
struct VariableTemplate {
  using DeclTy = VarTemplateDecl;
  static constexpr auto *Prototype = "template <class T> extern T X;";
  static constexpr auto *Definition =
      R"(
      template <class T> T X;
      template <> int X<int>;
      )";
  // There is no matcher for varTemplateDecl so use a work-around.
  BindableMatcher<Decl> getPattern() {
    return namedDecl(hasName("X"), unless(isImplicit()),
                     has(templateTypeParmDecl()));
  }
};
```
Storage of `X` in `Prototype` and `Definition` is different, it should fail when imported.
I added structural equivalence of `VarTemplateDecl` and makes this import failed in `VarTemplateDeclConflict`. is it also need to fix the testcase in `ASTImporterGenericRedeclTest.cpp`?
```cpp
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
                                     VarTemplateDecl *D1,
                                     VarTemplateDecl *D2) {
  if (!IsStructurallyEquivalent(Context, D1->getDeclName(), D2->getDeclName()))
    return false;

  // Check the templated declaration.
  if (!IsStructurallyEquivalent(Context, D1->getTemplatedDecl(),
                                D2->getTemplatedDecl()))
    return false;

  // Check template parameters.
  return IsStructurallyEquivalent(Context, D1->getTemplateParameters(),
                                  D2->getTemplateParameters());
}
```

https://github.com/llvm/llvm-project/pull/72841


More information about the cfe-commits mailing list