Skip to content

Template Diagnostic Improvements #99933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,16 @@ Improvements to Clang's diagnostics

UsingWithAttr<int> objUsingWA; // warning: 'UsingWithAttr' is deprecated

- Some template related diagnostics have been improved.

.. code-block:: c++

void foo() { template <typename> int i; } // error: templates can only be declared in namespace or class scope

struct S {
template <typename> int i; // error: non-static data member 'i' cannot be declared as a template
};

Improvements to Clang's time-trace
----------------------------------

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -5165,7 +5165,7 @@ def warn_cxx11_compat_variable_template : Warning<
InGroup<CXXPre14Compat>, 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">;
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Parse/ParseStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/drs/cwg6xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1265,7 +1265,7 @@ namespace cwg687 { // cwg687 (9 c++20, but the issue is still considered open)

// This is not.
template g<int>(a);
// expected-error@-1 {{expected expression}}
// expected-error@-1 {{expected '<' after 'template'}}
}
}

Expand Down
8 changes: 4 additions & 4 deletions clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct B {
static int y;

template<typename T>
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<typename T>
static int x<T*>;
Expand All @@ -65,7 +65,7 @@ struct B {
static int y<T*>;

template<typename T>
int x<T**>; // expected-error {{member 'x' declared as a template}}
int x<T**>; // expected-error {{non-static data member 'x' cannot be declared as a template}}

template<>
int x<short>;
Expand Down Expand Up @@ -169,7 +169,7 @@ struct D {
static int y;

template<typename U>
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<typename U>
static int x<U*>;
Expand All @@ -178,7 +178,7 @@ struct D {
static int y<U*>;

template<typename U>
int x<U**>; // expected-error {{member 'x' declared as a template}}
int x<U**>; // expected-error {{non-static data member 'x' cannot be declared as a template}}

template<>
int x<short>;
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Parser/cxx-template-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,7 @@ namespace PR46231 {
template<> int; // expected-error {{declaration does not declare anything}}
template<int> int; // expected-error {{declaration does not declare anything}}
}

namespace PR99933 {
void foo() { template <typename> int i; } // expected-error {{templates can only be declared in namespace or class scope}}
}
16 changes: 8 additions & 8 deletions clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
#endif

class A {
template<typename T> CONST T wrong; // expected-error {{member 'wrong' declared as a template}}
template<typename T> CONST T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}}
template<typename T> CONST T wrong; // expected-error {{non-static data member 'wrong' cannot be declared as a template}}
template<typename T> CONST T wrong_init = 5; // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}}
template<typename T, typename T0> static CONST T right = T(100);
template<typename T> static CONST T right<T,int> = 5;
template<typename T> CONST int right<int,T>; // expected-error {{member 'right' declared as a template}}
template<typename T> CONST float right<float,T> = 5; // expected-error {{member 'right' declared as a template}}
template<typename T> CONST int right<int,T>; // expected-error {{non-static data member 'right' cannot be declared as a template}}
template<typename T> CONST float right<float,T> = 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
Expand Down Expand Up @@ -161,14 +161,14 @@ namespace non_const_init {
#ifndef PRECXX11
namespace constexpred {
class A {
template<typename T> constexpr T wrong; // expected-error {{member 'wrong' declared as a template}}
template<typename T> 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<typename T> constexpr T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}}
template<typename T> constexpr T wrong_init = 5; // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}}
template<typename T, typename T0> static constexpr T right = T(100);
template<typename T> static constexpr T right<T,int> = 5;
template<typename T> constexpr int right<int,T>; // expected-error {{member 'right' declared as a template}}
template<typename T> constexpr int right<int,T>; // expected-error {{non-static data member 'right' cannot be declared as a template}}
// expected-error@-1 {{declaration of constexpr static data member 'right<int, T>' requires an initializer}}
template<typename T> constexpr float right<float,T> = 5; // expected-error {{member 'right' declared as a template}}
template<typename T> constexpr float right<float,T> = 5; // expected-error {{non-static data member 'right' cannot be declared as a template}}
template<> constexpr int right<int,int> = 7;
template<> constexpr float right<float, int>; // expected-error {{declaration of constexpr static data member 'right<float, int>' requires an initializer}}
template static constexpr int right<int,int>; // expected-error {{expected '<' after 'template'}}
Expand Down
6 changes: 6 additions & 0 deletions clang/test/SemaCXX/invalid-template-declaration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: %clang_cc1 %s -verify -fsyntax-only
// PR99933

struct S {
template <typename> int i; // expected-error {{non-static data member 'i' cannot be declared as a template}}
};
2 changes: 1 addition & 1 deletion clang/test/SemaTemplate/class-template-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class X {
};

void f() {
template<typename T> class X; // expected-error{{expression}}
template<typename T> class X; // expected-error{{templates can only be declared in namespace or class scope}}
}

template<typename T> class X1 var; // expected-error {{variable has incomplete type 'class X1'}} \
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaTemplate/nested-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ namespace PR10896 {
private:

template<typename T>
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'}}
};

Expand Down
Loading