Index: cfe/trunk/lib/AST/ASTImporter.cpp =================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp +++ cfe/trunk/lib/AST/ASTImporter.cpp @@ -5638,17 +5638,16 @@ continue; if (auto *FoundTemplate = dyn_cast(FoundDecl)) { - if (FoundTemplate->hasExternalFormalLinkage() && - D->hasExternalFormalLinkage()) { - if (IsStructuralMatch(D, FoundTemplate)) { - FunctionTemplateDecl *TemplateWithDef = - getTemplateDefinition(FoundTemplate); - if (D->isThisDeclarationADefinition() && TemplateWithDef) { - return Importer.MapImported(D, TemplateWithDef); - } - FoundByLookup = FoundTemplate; - break; - } + if (!hasSameVisibilityContext(FoundTemplate, D)) + continue; + if (IsStructuralMatch(D, FoundTemplate)) { + FunctionTemplateDecl *TemplateWithDef = + getTemplateDefinition(FoundTemplate); + if (D->isThisDeclarationADefinition() && TemplateWithDef) + return Importer.MapImported(D, TemplateWithDef); + + FoundByLookup = FoundTemplate; + break; // TODO: handle conflicting names } } Index: cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp =================================================================== --- cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp +++ cfe/trunk/unittests/AST/ASTImporterVisibilityTest.cpp @@ -43,6 +43,12 @@ using DeclTy = TypedefNameDecl; BindableMatcher operator()() { return typedefNameDecl(hasName("T")); } }; +struct GetFunTemplPattern { + using DeclTy = FunctionTemplateDecl; + BindableMatcher operator()() { + return functionTemplateDecl(hasName("f")); + } +}; // Values for the value-parameterized test fixtures. // FunctionDecl: @@ -64,6 +70,10 @@ const auto *AnonTypedef = "namespace { typedef int T; }"; const auto *ExternUsing = "using T = int;"; const auto *AnonUsing = "namespace { using T = int; }"; +// FunctionTemplateDecl: +const auto *ExternFT = "template void f();"; +const auto *StaticFT = "template static void f();"; +const auto *AnonFT = "namespace { template void f(); }"; // First value in tuple: Compile options. // Second value in tuple: Source code to be used in the test. @@ -108,6 +118,9 @@ using ImportFunctionsVisibilityChain = ImportVisibilityChain; using ImportVariablesVisibilityChain = ImportVisibilityChain; using ImportClassesVisibilityChain = ImportVisibilityChain; +using ImportFunctionTemplatesVisibilityChain = + ImportVisibilityChain; + // Value-parameterized test for functions. TEST_P(ImportFunctionsVisibilityChain, ImportChain) { TypedTest_ImportChain(); @@ -120,6 +133,10 @@ TEST_P(ImportClassesVisibilityChain, ImportChain) { TypedTest_ImportChain(); } +// Value-parameterized test for function templates. +TEST_P(ImportFunctionTemplatesVisibilityChain, ImportChain) { + TypedTest_ImportChain(); +} // Automatic instantiation of the value-parameterized tests. INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain, @@ -143,6 +160,11 @@ ::testing::Combine( DefaultTestValuesForRunOptions, ::testing::Values(ExternC, AnonC)), ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, + ImportFunctionTemplatesVisibilityChain, + ::testing::Combine(DefaultTestValuesForRunOptions, + ::testing::Values(ExternFT, StaticFT, + AnonFT)), ); // First value in tuple: Compile options. // Second value in tuple: Tuple with informations for the test. @@ -253,6 +275,7 @@ using ImportClassesVisibility = ImportVisibility; using ImportEnumsVisibility = ImportVisibility; using ImportTypedefNameVisibility = ImportVisibility; +using ImportFunctionTemplatesVisibility = ImportVisibility; // FunctionDecl. TEST_P(ImportFunctionsVisibility, ImportAfter) { @@ -289,6 +312,13 @@ TEST_P(ImportTypedefNameVisibility, ImportAfterImport) { TypedTest_ImportAfterImportWithMerge(); } +// FunctionTemplateDecl. +TEST_P(ImportFunctionTemplatesVisibility, ImportAfter) { + TypedTest_ImportAfter(); +} +TEST_P(ImportFunctionTemplatesVisibility, ImportAfterImport) { + TypedTest_ImportAfterImport(); +} const bool ExpectLinkedDeclChain = true; const bool ExpectUnlinkedDeclChain = false; @@ -367,6 +397,20 @@ std::make_tuple(AnonTypedef, ExternUsing, ExpectUnlinkedDeclChain), std::make_tuple(AnonTypedef, AnonUsing, ExpectUnlinkedDeclChain))), ); +INSTANTIATE_TEST_CASE_P( + ParameterizedTests, ImportFunctionTemplatesVisibility, + ::testing::Combine( + DefaultTestValuesForRunOptions, + ::testing::Values( + std::make_tuple(ExternFT, ExternFT, ExpectLinkedDeclChain), + std::make_tuple(ExternFT, StaticFT, ExpectUnlinkedDeclChain), + std::make_tuple(ExternFT, AnonFT, ExpectUnlinkedDeclChain), + std::make_tuple(StaticFT, ExternFT, ExpectUnlinkedDeclChain), + std::make_tuple(StaticFT, StaticFT, ExpectUnlinkedDeclChain), + std::make_tuple(StaticFT, AnonFT, ExpectUnlinkedDeclChain), + std::make_tuple(AnonFT, ExternFT, ExpectUnlinkedDeclChain), + std::make_tuple(AnonFT, StaticFT, ExpectUnlinkedDeclChain), + std::make_tuple(AnonFT, AnonFT, ExpectUnlinkedDeclChain))), ); } // end namespace ast_matchers } // end namespace clang