diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 83fd5dc31547eb..ac1de0db9ce486 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -110,6 +110,16 @@ Attribute Changes in Clang Improvements to Clang's diagnostics ----------------------------------- +- Some template related diagnostics have been improved. + + .. code-block:: c++ + + void foo() { template int i; } // error: templates can only be declared in namespace or class scope + + struct S { + template int i; // error: non-static data member 'i' cannot be declared as a template + }; + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b8d97a6b14fe6b..00affee1ea67f7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5168,7 +5168,7 @@ def warn_cxx11_compat_variable_template : Warning< InGroup, DefaultIgnore; def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; -def err_template_member : Error<"member %0 declared as a template">; +def err_template_member : Error<"non-static data member %0 cannot be declared as a template">; def err_member_with_template_arguments : Error<"member %0 cannot have template arguments">; def err_template_member_noparams : Error< "extraneous 'template<>' in declaration of member %0">; diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 22d38adc28ebe9..bdb3fc051d0b35 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -299,6 +299,15 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( goto Retry; } + case tok::kw_template: { + SourceLocation DeclEnd; + ParsedAttributes Attrs(AttrFactory); + ParseTemplateDeclarationOrSpecialization(DeclaratorContext::Block, DeclEnd, + Attrs, + getAccessSpecifierIfPresent()); + return StmtError(); + } + case tok::kw_case: // C99 6.8.1: labeled-statement return ParseCaseStatement(StmtCtx); case tok::kw_default: // C99 6.8.1: labeled-statement diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp index 069102d9c59750..1c56dd3907152e 100644 --- a/clang/test/CXX/drs/cwg6xx.cpp +++ b/clang/test/CXX/drs/cwg6xx.cpp @@ -1265,7 +1265,7 @@ namespace cwg687 { // cwg687 (9 c++20, but the issue is still considered open) // This is not. template g(a); - // expected-error@-1 {{expected expression}} + // expected-error@-1 {{expected '<' after 'template'}} } } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp index 7a261fef27361a..935dd360847bc4 100644 --- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp @@ -56,7 +56,7 @@ struct B { static int y; template - int z; // expected-error {{member 'z' declared as a template}} + int z; // expected-error {{non-static data member 'z' cannot be declared as a template}} template static int x; @@ -65,7 +65,7 @@ struct B { static int y; template - int x; // expected-error {{member 'x' declared as a template}} + int x; // expected-error {{non-static data member 'x' cannot be declared as a template}} template<> int x; @@ -169,7 +169,7 @@ struct D { static int y; template - int z; // expected-error {{member 'z' declared as a template}} + int z; // expected-error {{non-static data member 'z' cannot be declared as a template}} template static int x; @@ -178,7 +178,7 @@ struct D { static int y; template - int x; // expected-error {{member 'x' declared as a template}} + int x; // expected-error {{non-static data member 'x' cannot be declared as a template}} template<> int x; diff --git a/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp index 734438069b9ae6..476341686a64b7 100644 --- a/clang/test/Parser/cxx-template-decl.cpp +++ b/clang/test/Parser/cxx-template-decl.cpp @@ -297,3 +297,7 @@ namespace PR46231 { template<> int; // expected-error {{declaration does not declare anything}} template int; // expected-error {{declaration does not declare anything}} } + +namespace PR99933 { + void foo() { template int i; } // expected-error {{templates can only be declared in namespace or class scope}} +} diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index 5e189b758c61e9..eafadb07b29e1e 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -9,12 +9,12 @@ #endif class A { - template CONST T wrong; // expected-error {{member 'wrong' declared as a template}} - template CONST T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}} + template CONST T wrong; // expected-error {{non-static data member 'wrong' cannot be declared as a template}} + template CONST T wrong_init = 5; // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}} template static CONST T right = T(100); template static CONST T right = 5; - template CONST int right; // expected-error {{member 'right' declared as a template}} - template CONST float right = 5; // expected-error {{member 'right' declared as a template}} + template CONST int right; // expected-error {{non-static data member 'right' cannot be declared as a template}} + template CONST float right = 5; // expected-error {{non-static data member 'right' cannot be declared as a template}} #ifdef PRECXX11 // expected-warning@-2 {{in-class initializer for static data member of type 'const float' is a GNU extension}} #else @@ -161,14 +161,14 @@ namespace non_const_init { #ifndef PRECXX11 namespace constexpred { class A { - template constexpr T wrong; // expected-error {{member 'wrong' declared as a template}} + template constexpr T wrong; // expected-error {{non-static data member 'wrong' cannot be declared as a template}} // expected-error@-1 {{declaration of constexpr static data member 'wrong' requires an initializer}} - template constexpr T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}} + template constexpr T wrong_init = 5; // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}} template static constexpr T right = T(100); template static constexpr T right = 5; - template constexpr int right; // expected-error {{member 'right' declared as a template}} + template constexpr int right; // expected-error {{non-static data member 'right' cannot be declared as a template}} // expected-error@-1 {{declaration of constexpr static data member 'right' requires an initializer}} - template constexpr float right = 5; // expected-error {{member 'right' declared as a template}} + template constexpr float right = 5; // expected-error {{non-static data member 'right' cannot be declared as a template}} template<> constexpr int right = 7; template<> constexpr float right; // expected-error {{declaration of constexpr static data member 'right' requires an initializer}} template static constexpr int right; // expected-error {{expected '<' after 'template'}} diff --git a/clang/test/SemaCXX/invalid-template-declaration.cpp b/clang/test/SemaCXX/invalid-template-declaration.cpp new file mode 100644 index 00000000000000..fda147520cca82 --- /dev/null +++ b/clang/test/SemaCXX/invalid-template-declaration.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only +// PR99933 + +struct S { + template int i; // expected-error {{non-static data member 'i' cannot be declared as a template}} +}; diff --git a/clang/test/SemaTemplate/class-template-decl.cpp b/clang/test/SemaTemplate/class-template-decl.cpp index c054a6a8d82f7a..0374c4eba982a0 100644 --- a/clang/test/SemaTemplate/class-template-decl.cpp +++ b/clang/test/SemaTemplate/class-template-decl.cpp @@ -63,7 +63,7 @@ class X { }; void f() { - template class X; // expected-error{{expression}} + template class X; // expected-error{{templates can only be declared in namespace or class scope}} } template class X1 var; // expected-error {{variable has incomplete type 'class X1'}} \ diff --git a/clang/test/SemaTemplate/nested-template.cpp b/clang/test/SemaTemplate/nested-template.cpp index a6ede8e99037e0..a54992a3971878 100644 --- a/clang/test/SemaTemplate/nested-template.cpp +++ b/clang/test/SemaTemplate/nested-template.cpp @@ -132,7 +132,7 @@ namespace PR10896 { private: template - T SomeField; // expected-error {{member 'SomeField' declared as a template}} + T SomeField; // expected-error {{non-static data member 'SomeField' cannot be declared as a template}} template<> int SomeField2; // expected-error {{extraneous 'template<>' in declaration of variable 'SomeField2'}} };