bool considerVisibility =
shouldConsiderTemplateVisibility(fn, specInfo);
- // Merge information from the template parameters.
FunctionTemplateDecl *temp = specInfo->getTemplate();
- LinkageInfo tempLV =
- getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
- LV.mergeMaybeWithVisibility(tempLV, considerVisibility);
+
+ // Merge information from the template declaration.
+ LinkageInfo tempLV = getLVForDecl(temp, computation);
+ // The linkage of the specialization should be consistent with the
+ // template declaration.
+ LV.setLinkage(tempLV.getLinkage());
+
+ // Merge information from the template parameters.
+ LinkageInfo paramsLV =
+ getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
+ LV.mergeMaybeWithVisibility(paramsLV, considerVisibility);
// Merge information from the template arguments.
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
selectFirst<FunctionDecl>("f", match(functionDecl().bind("f"), Ctx));
EXPECT_TRUE(f->isInExportDeclContext());
}
+
+TEST(Decl, InConsistLinkageForTemplates) {
+ llvm::Annotations Code(R"(
+ export module m;
+ export template <class T>
+ void f() {}
+
+ template <>
+ void f<int>() {})");
+
+ auto AST =
+ tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"});
+ ASTContext &Ctx = AST->getASTContext();
+
+ llvm::SmallVector<ast_matchers::BoundNodes, 2> Funcs =
+ match(functionDecl().bind("f"), Ctx);
+
+ EXPECT_EQ(Funcs.size(), 2);
+ const FunctionDecl *TemplateF = Funcs[0].getNodeAs<FunctionDecl>("f");
+ const FunctionDecl *SpecializedF = Funcs[1].getNodeAs<FunctionDecl>("f");
+ EXPECT_EQ(TemplateF->getLinkageInternal(),
+ SpecializedF->getLinkageInternal());
+}