diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5489,6 +5489,10 @@ continue; if (VarTemplateDecl *FoundTemplate = dyn_cast(FoundDecl)) { + // Use the templated decl, some linkage flags are set only there. + if (!hasSameVisibilityContextAndLinkage(FoundTemplate->getTemplatedDecl(), + 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. diff --git a/clang/unittests/AST/ASTImporterVisibilityTest.cpp b/clang/unittests/AST/ASTImporterVisibilityTest.cpp --- a/clang/unittests/AST/ASTImporterVisibilityTest.cpp +++ b/clang/unittests/AST/ASTImporterVisibilityTest.cpp @@ -49,6 +49,12 @@ return functionTemplateDecl(hasName("f")); } }; +struct GetVarTemplPattern { + using DeclTy = VarTemplateDecl; + BindableMatcher operator()() { + return namedDecl(hasName("v"), has(templateTypeParmDecl())); + } +}; struct GetClassTemplPattern { using DeclTy = ClassTemplateDecl; BindableMatcher operator()() { return classTemplateDecl(hasName("X")); } @@ -80,6 +86,10 @@ const auto *ExternFT = "template void f();"; const auto *StaticFT = "template static void f();"; const auto *AnonFT = "namespace { template void f(); }"; +// VarTemplateDecl: +const auto *ExternVT = "template extern int v;"; +const auto *StaticVT = "template static int v;"; +const auto *AnonVT = "namespace { template extern int v; }"; // ClassTemplateDecl: const auto *ExternCT = "template class X;"; const auto *AnonCT = "namespace { template class X; }"; @@ -130,6 +140,8 @@ using ImportScopedEnumsVisibilityChain = ImportVisibilityChain; using ImportFunctionTemplatesVisibilityChain = ImportVisibilityChain; +using ImportVariableTemplatesVisibilityChain = + ImportVisibilityChain; using ImportClassTemplatesVisibilityChain = ImportVisibilityChain; @@ -153,6 +165,10 @@ TEST_P(ImportFunctionTemplatesVisibilityChain, ImportChain) { TypedTest_ImportChain(); } +// Value-parameterized test for variable templates. +TEST_P(ImportVariableTemplatesVisibilityChain, ImportChain) { + TypedTest_ImportChain(); +} // Value-parameterized test for class templates. TEST_P(ImportClassTemplatesVisibilityChain, ImportChain) { TypedTest_ImportChain(); @@ -190,6 +206,11 @@ ::testing::Combine(DefaultTestValuesForRunOptions, ::testing::Values(ExternFT, StaticFT, AnonFT)), ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, + ImportVariableTemplatesVisibilityChain, + ::testing::Combine(DefaultTestValuesForRunOptions, + ::testing::Values(ExternVT, + AnonVT)), ); INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplatesVisibilityChain, ::testing::Combine(DefaultTestValuesForRunOptions, ::testing::Values(ExternCT, @@ -306,6 +327,7 @@ using ImportScopedEnumsVisibility = ImportVisibility; using ImportTypedefNameVisibility = ImportVisibility; using ImportFunctionTemplatesVisibility = ImportVisibility; +using ImportVariableTemplatesVisibility = ImportVisibility; using ImportClassTemplatesVisibility = ImportVisibility; // FunctionDecl. @@ -356,6 +378,13 @@ TEST_P(ImportFunctionTemplatesVisibility, ImportAfterImport) { TypedTest_ImportAfterImport(); } +// VarTemplateDecl. +TEST_P(ImportVariableTemplatesVisibility, ImportAfter) { + TypedTest_ImportAfter(); +} +TEST_P(ImportVariableTemplatesVisibility, ImportAfterImport) { + TypedTest_ImportAfterImport(); +} // ClassTemplateDecl. TEST_P(ImportClassTemplatesVisibility, ImportAfter) { TypedTest_ImportAfter(); } TEST_P(ImportClassTemplatesVisibility, ImportAfterImport) { @@ -463,6 +492,20 @@ std::make_tuple(AnonFT, StaticFT, ExpectUnlinkedDeclChain), std::make_tuple(AnonFT, AnonFT, ExpectUnlinkedDeclChain))), ); INSTANTIATE_TEST_CASE_P( + ParameterizedTests, ImportVariableTemplatesVisibility, + ::testing::Combine( + DefaultTestValuesForRunOptions, + ::testing::Values( + std::make_tuple(ExternVT, ExternVT, ExpectLinkedDeclChain), + std::make_tuple(ExternVT, StaticVT, ExpectUnlinkedDeclChain), + std::make_tuple(ExternVT, AnonVT, ExpectUnlinkedDeclChain), + std::make_tuple(StaticVT, ExternVT, ExpectUnlinkedDeclChain), + std::make_tuple(StaticVT, StaticVT, ExpectUnlinkedDeclChain), + std::make_tuple(StaticVT, AnonVT, ExpectUnlinkedDeclChain), + std::make_tuple(AnonVT, ExternVT, ExpectUnlinkedDeclChain), + std::make_tuple(AnonVT, StaticVT, ExpectUnlinkedDeclChain), + std::make_tuple(AnonVT, AnonVT, ExpectUnlinkedDeclChain))), ); +INSTANTIATE_TEST_CASE_P( ParameterizedTests, ImportClassTemplatesVisibility, ::testing::Combine( DefaultTestValuesForRunOptions,