diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 794ef23f07619a..91112860a2d029 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -793,6 +793,7 @@ def ext_main_used : Extension< /// parser diagnostics def ext_no_declarators : ExtWarn<"declaration does not declare anything">, InGroup; +def err_no_declarators : Error<"declaration does not declare anything">; def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">, InGroup; def err_typedef_not_identifier : Error<"typedef name must be an identifier">; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ddbf086ea63851..9b9d164dcbc1b8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4766,7 +4766,10 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, if (!DeclaresAnything) { // In C, we allow this as a (popular) extension / bug. Don't bother // producing further diagnostics for redundant qualifiers after this. - Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange(); + Diag(DS.getBeginLoc(), (IsExplicitInstantiation || !TemplateParams.empty()) + ? diag::err_no_declarators + : diag::ext_no_declarators) + << DS.getSourceRange(); return TagD; } diff --git a/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp index 64e7ca921f575b..7455b1d0ffe72c 100644 --- a/clang/test/Parser/cxx-template-decl.cpp +++ b/clang/test/Parser/cxx-template-decl.cpp @@ -12,7 +12,7 @@ export template x; // expected-error {{expected '<' after 'template'}} export template class x0; // expected-warning {{exported templates are unsupported}} template < ; // expected-error {{expected template parameter}} \ // expected-error{{expected ',' or '>' in template-parameter-list}} \ -// expected-warning {{declaration does not declare anything}} +// expected-error {{declaration does not declare anything}} template struct x1; // expected-error {{expected ',' or '>' in template-parameter-list}} // verifies that we only walk to the ',' & still produce errors on the rest of the template parameters @@ -286,3 +286,12 @@ namespace PR45239 { template int b; template auto f() -> b<0>; // expected-error +{{}} } + +namespace PR46231 { + template; // expected-error {{declaration does not declare anything}} + template<>; // expected-error {{declaration does not declare anything}} + template; // expected-error {{declaration does not declare anything}} + template int; // expected-error {{declaration does not declare anything}} + template<> int; // expected-error {{declaration does not declare anything}} + template int; // expected-error {{declaration does not declare anything}} +} diff --git a/clang/test/SemaCXX/PR16677.cpp b/clang/test/SemaCXX/PR16677.cpp index efa4faaacd6932..3ad76c6d861d7d 100644 --- a/clang/test/SemaCXX/PR16677.cpp +++ b/clang/test/SemaCXX/PR16677.cpp @@ -11,5 +11,5 @@ template { // expected-error{{'Derived' cannot be defined in a type specifier}} Class_With_Destructor member; }; // expected-error{{expected ',' or '>' in template-parameter-list}} - // expected-warning@-1{{declaration does not declare anything}} + // expected-error@-1{{declaration does not declare anything}} diff --git a/clang/test/SemaCXX/invalid-template-params.cpp b/clang/test/SemaCXX/invalid-template-params.cpp index 0c463fe13d5b0c..21220f3fea3451 100644 --- a/clang/test/SemaCXX/invalid-template-params.cpp +++ b/clang/test/SemaCXX/invalid-template-params.cpp @@ -5,7 +5,7 @@ template class Foo { // expected-note@-1 {{'UBar' declared here}} void foo1(); // expected-error {{a non-type template parameter cannot have type 'class UBar'}} // expected-error@-1 {{expected ',' or '>' in template-parameter-list}} - // expected-warning@-2 {{declaration does not declare anything}} + // expected-error@-2 {{declaration does not declare anything}} }; Foo::UBar g1; // expected-error {{no type named 'UBar' in 'Foo'}} @@ -16,7 +16,7 @@ class C0 { struct S0 {}; // expected-error {{'S0' cannot be defined in a type specifier}} // expected-error@-1 {{cannot combine with previous 'type-name' declaration specifier}} // expected-error@-2 {{expected ',' or '>' in template-parameter-list}} - // expected-warning@-3 {{declaration does not declare anything}} + // expected-error@-3 {{declaration does not declare anything}} C0() : m(new S0) {} // expected-error {{expected '(' for function-style cast or type construction}} // expected-error@-1 {{expected expression}} S0 *m; // expected-error {{expected member name or ';' after declaration specifiers}} diff --git a/clang/test/SemaTemplate/template-decl-fail.cpp b/clang/test/SemaTemplate/template-decl-fail.cpp index ad134cdf225c2a..7019caa2c2f318 100644 --- a/clang/test/SemaTemplate/template-decl-fail.cpp +++ b/clang/test/SemaTemplate/template-decl-fail.cpp @@ -4,7 +4,7 @@ template typedef T X; // expected-error{{typedef cannot be a templat template enum t0 { A = T::x }; // expected-error{{enumeration cannot be a template}} \ - // expected-warning{{declaration does not declare anything}} + // expected-error{{declaration does not declare anything}} enum e0 {}; template enum e0 f0(int a=x) {}