diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 62470582870cadd9ca0554c95a3b11d3bd1f6549..32e9a08370143ea8daae0fc2fa91e87217a39de5 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -469,6 +469,11 @@ def err_missing_dependent_template_keyword : Error< def warn_missing_dependent_template_keyword : ExtWarn< "use 'template' keyword to treat '%0' as a dependent template name">; +def ext_extern_template : Extension< + "extern templates are a C++11 extension">, InGroup; +def warn_cxx98_compat_extern_template : Warning< + "extern templates are incompatible with C++98">, + InGroup, DefaultIgnore; def warn_static_inline_explicit_inst_ignored : Warning< "ignoring '%select{static|inline}0' keyword on explicit template " "instantiation">; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 2a1e2a2de899f27021f9c3e456768820124a4075..2e0c46dbdbfea63e9109756d5a0b102012f59f34 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -642,6 +642,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // Extern templates SourceLocation ExternLoc = ConsumeToken(); SourceLocation TemplateLoc = ConsumeToken(); + Diag(ExternLoc, getLang().CPlusPlus0x ? + diag::warn_cxx98_compat_extern_template : + diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc); SourceLocation DeclEnd; return Actions.ConvertDeclToDeclGroup( ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd)); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp index d3043741151382e3fa99dab5f47e75cc49463448..09c428e01df3b7d81af0abc5eefb4dcc0dd7dc23 100644 --- a/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -43,6 +43,6 @@ namespace test0 { // inappropriately instantiating this template. void *ptr = x; } - extern template class foo; + extern template class foo; // expected-warning {{extern templates are a C++11 extension}} template class foo; } diff --git a/clang/test/SemaCXX/cxx98-compat-pedantic.cpp b/clang/test/SemaCXX/cxx98-compat-pedantic.cpp index 28fc23a0a763ae01d1867feee96d008bfff7c23c..00532d5ac0731b56e377cdd78bcd8f2ff7c4135e 100644 --- a/clang/test/SemaCXX/cxx98-compat-pedantic.cpp +++ b/clang/test/SemaCXX/cxx98-compat-pedantic.cpp @@ -29,3 +29,6 @@ struct ConvertToInt { operator int(); }; int *ArraySizeConversion = new int[ConvertToInt()]; // expected-warning {{implicit conversion from array size expression of type 'ConvertToInt' to integral type 'int' is incompatible with C++98}} + +template class ExternTemplate {}; +extern template class ExternTemplate; // expected-warning {{extern templates are incompatible with C++98}}