Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -7017,6 +7017,16 @@ return true; } + // C++ [temp]p6: + // A template, a template explicit specialization, and a class template + // partial specialization shall not have C linkage. + if (S.CurContext->isExternCContext()) { + S.Diag(Loc, diag::err_template_linkage); + if (const LinkageSpecDecl *LSD = S.CurContext->getExternCContext()) + S.Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); + 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}} +}