Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -6953,6 +6953,21 @@ return true; } +/// \brief Check whether a template is declared with "C" language linkage. +/// +/// If a template or a template specialization is declared with "C" language +/// linkage, issues a diagnostic and returns true. Otherwise, returns false. +static bool +CheckTemplateLanguageLinkage(Sema &S, DeclContext *Ctx, SourceRange Rng) { + if (Ctx && Ctx->isExternCContext()) { + S.Diag(Rng.getBegin(), diag::err_template_linkage) << Rng; + if (const LinkageSpecDecl *LSD = Ctx->getExternCContext()) + S.Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); + return true; + } + return false; +} + /// \brief Check whether a template can be declared within this scope. /// /// If the template declaration is valid in this scope, returns @@ -6970,13 +6985,10 @@ // C++ [temp]p4: // A template [...] shall not have C linkage. DeclContext *Ctx = S->getEntity(); - if (Ctx && Ctx->isExternCContext()) { - Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) - << TemplateParams->getSourceRange(); - if (const LinkageSpecDecl *LSD = Ctx->getExternCContext()) - Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); + if (CheckTemplateLanguageLinkage(*this, Ctx, + TemplateParams->getSourceRange())) return true; - } + Ctx = Ctx->getRedeclContext(); // C++ [temp]p2: @@ -7071,6 +7083,12 @@ return true; } + // C++ [temp]p6: + // A template, a template explicit specialization, and a class template + // partial specialization shall not have C linkage. + if (CheckTemplateLanguageLinkage(S, S.CurContext, Loc)) + return true; + // C++ [temp.expl.spec]p2: // An explicit specialization shall be declared in the namespace // of which the template is a member, or, for member templates, in Index: test/SemaTemplate/class-template-spec.cpp =================================================================== --- test/SemaTemplate/class-template-spec.cpp +++ test/SemaTemplate/class-template-spec.cpp @@ -235,3 +235,9 @@ > struct S; template struct S {}; // expected-error {{non-type template argument specializes a template parameter with dependent type 'T'}} } + +template struct C {}; +extern "C" { // expected-note 2{{extern "C" language linkage specification begins here}} + template struct C {}; // expected-error{{templates must have C++ linkage}} + template<> struct C {}; // expected-error{{templates must have C++ linkage}} +} Index: test/SemaTemplate/function-template-specialization.cpp =================================================================== --- test/SemaTemplate/function-template-specialization.cpp +++ test/SemaTemplate/function-template-specialization.cpp @@ -56,3 +56,8 @@ template<> static void Bar(const long& input) {} // expected-error{{explicit specialization of 'Bar' in class scope}} }; + +template void f3(T) {} +extern "C" { // expected-note {{extern "C" language linkage specification begins here}} + template<> void f3(int) {} // expected-error{{templates must have C++ linkage}} +}