[clang] Template Diagnostic Improvements (PR #99933)

Braden Helmer via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 22 15:32:47 PDT 2024


https://github.com/bradenhelmer updated https://github.com/llvm/llvm-project/pull/99933

>From 1aaa6ff0f1843f10606064f6b285c7070aaa5b44 Mon Sep 17 00:00:00 2001
From: Braden Helmer <bradenhelmeraus at gmail.com>
Date: Mon, 22 Jul 2024 16:46:04 -0400
Subject: [PATCH 1/4] Fix template error message

---
 clang/lib/Parse/ParseStmt.cpp           | 9 +++++++++
 clang/test/Parser/cxx-template-decl.cpp | 4 ++++
 2 files changed, 13 insertions(+)

diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 22d38adc28ebe..bdb3fc051d0b3 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/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp
index 734438069b9ae..5a2d1cec9ad31 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> int; // expected-error {{declaration does not declare anything}}
 }
+
+namespace NoTemplateInBlockScope {
+  void foo() { template <typename> int i; } // expected-error {{templates can only be declared in namespace or class scope}}
+}

>From 26853b9c5d65f6bcc74d52cdaeec333e8bd0422c Mon Sep 17 00:00:00 2001
From: Braden Helmer <bradenhelmeraus at gmail.com>
Date: Mon, 22 Jul 2024 17:46:27 -0400
Subject: [PATCH 2/4] Update another template error message, add and fixed
 tests accordingly

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td    | 2 +-
 clang/test/Parser/cxx-template-decl.cpp             | 2 +-
 clang/test/SemaCXX/invalid-template-declaration.cpp | 6 ++++++
 clang/test/SemaTemplate/class-template-decl.cpp     | 2 +-
 clang/test/SemaTemplate/nested-template.cpp         | 2 +-
 5 files changed, 10 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/SemaCXX/invalid-template-declaration.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c4a4e8064fac2..7790982301177 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp
index 5a2d1cec9ad31..476341686a64b 100644
--- a/clang/test/Parser/cxx-template-decl.cpp
+++ b/clang/test/Parser/cxx-template-decl.cpp
@@ -298,6 +298,6 @@ namespace PR46231 {
   template<int> int; // expected-error {{declaration does not declare anything}}
 }
 
-namespace NoTemplateInBlockScope {
+namespace PR99933 {
   void foo() { template <typename> int i; } // expected-error {{templates can only be declared in namespace or class scope}}
 }
diff --git a/clang/test/SemaCXX/invalid-template-declaration.cpp b/clang/test/SemaCXX/invalid-template-declaration.cpp
new file mode 100644
index 0000000000000..fda147520cca8
--- /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 <typename> 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 c054a6a8d82f7..0374c4eba982a 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<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'}} \
diff --git a/clang/test/SemaTemplate/nested-template.cpp b/clang/test/SemaTemplate/nested-template.cpp
index a6ede8e99037e..a54992a397187 100644
--- a/clang/test/SemaTemplate/nested-template.cpp
+++ b/clang/test/SemaTemplate/nested-template.cpp
@@ -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'}}
   };
 

>From 5b14649ce8c9dd7bdec00f8cf30c6f20139e4a8f Mon Sep 17 00:00:00 2001
From: Braden Helmer <bradenhelmeraus at gmail.com>
Date: Mon, 22 Jul 2024 17:51:43 -0400
Subject: [PATCH 3/4] Update ReleaseNotes.rst

---
 clang/docs/ReleaseNotes.rst | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8e24087b3dcdb..0ab928b6331d8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
 ----------------------------------
 

>From 9fd1f0baf9f2240abddd3e4f7a4da920dfdc2434 Mon Sep 17 00:00:00 2001
From: Braden Helmer <bradenhelmeraus at gmail.com>
Date: Mon, 22 Jul 2024 18:32:35 -0400
Subject: [PATCH 4/4] Fix more tests

---
 clang/test/CXX/drs/cwg6xx.cpp                    |  2 +-
 .../CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp  |  8 ++++----
 .../cxx1y-variable-templates_in_class.cpp        | 16 ++++++++--------
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp
index 069102d9c5975..1c56dd3907152 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<int>(a);
-    // expected-error at -1 {{expected expression}}
+    // expected-error at -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 7a261fef27361..935dd360847bc 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<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*>;
@@ -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>;
@@ -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*>;
@@ -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>;
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index 5e189b758c61e..eafadb07b29e1 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<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 at -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<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 at -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 at -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'}}



More information about the cfe-commits mailing list