faisalv updated this revision to Diff 127828.
faisalv retitled this revision from "[Parser] Diagnose storage classes in 
template parameter declarations" to "Diagnose invalid decl-specifiers in 
non-type template parameter declarations (original author miyuki!)".
faisalv edited the summary of this revision.
faisalv set the repository for this revision to rC Clang.
faisalv added projects: clang, clang-c.
faisalv added a comment.

Miyuki - please take a look at the patch and let me know if you agree with the 
changes - or have any concerns...

Thank you!

P.S. While I can see the argument for having these syntactical checks be done 
by the Parser - since they could be described as context sensitive syntax 
analysis, moving the changes to Sema also seems quite appropriate.


Repository:
  rC Clang

https://reviews.llvm.org/D40705

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaTemplate.cpp
  test/CXX/temp/temp.param/p2.cpp

Index: test/CXX/temp/temp.param/p2.cpp
===================================================================
--- test/CXX/temp/temp.param/p2.cpp
+++ test/CXX/temp/temp.param/p2.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify %s 
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DCPP11
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s -DCPP17
 
 // There is no semantic difference between class and typename in a
 // template-parameter. typename followed by an unqualified-id names a
@@ -13,8 +14,32 @@
 template<typename T, typename X<T>::type Value> struct Y1;
 
 // A storage class shall not be specified in a template-parameter declaration.
-template<static int Value> struct Z; // FIXME: expect an error
+template<static int Value> struct Z; //expected-error{{invalid declaration specifier}}
+template<typedef int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<extern inline int Value> struct Z0; //expected-error2{{invalid declaration specifier}}
+template<virtual int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<inline int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<extern int> struct Z0; //expected-error{{invalid declaration specifier}}
+template<static int> struct Z0;  //expected-error{{invalid declaration specifier}}
+template<explicit int Value> struct Z0; //expected-error{{invalid declaration specifier}}
+template<mutable int> struct Z0; //expected-error{{invalid declaration specifier}}
 
+template<const int> struct Z0; // OK 
+template<volatile int> struct Z0; // OK
+
+
+
+#ifdef CPP11
+template<thread_local int> struct Z0; //expected-error{{invalid declaration specifier}}
+template<constexpr int> struct Z0; //expected-error{{invalid declaration specifier}}
+
+#endif
+
+#ifdef CPP17
+template<auto> struct Z1; // OK
+#endif
+
 // Make sure that we properly disambiguate non-type template parameters that
 // start with 'class'.
 class X1 { };
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -929,6 +929,60 @@
                                           Expr *Default) {
   TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
 
+  // Check that we have valid decl-specifiers specified.
+  auto CheckValidDeclSpecifiers = [this, &D] {
+    // C++ [temp.param]
+    // p1 
+    //   template-parameter:
+    //     ...
+    //     parameter-declaration
+    // p2 
+    //   ... A storage class shall not be specified in a template-parameter
+    //   declaration.
+    // [dcl.typedef]p1: 
+    //   The typedef specifier [...] shall not be used in the decl-specifier-seq
+    //   of a parameter-declaration
+    const DeclSpec &DS = D.getDeclSpec();
+    auto EmitDiag = [this](SourceLocation Loc) {
+      Diag(Loc, diag::err_invalid_decl_specifier_in_nontype_parm)
+          << FixItHint::CreateRemoval(Loc);
+    };
+    if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified)
+      EmitDiag(DS.getStorageClassSpecLoc());
+    
+    if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec())
+      EmitDiag(DS.getThreadStorageClassSpecLoc());
+    
+    // [dcl.inline]p1: 
+    //   The inline specifier can be applied only to the declaration or 
+    //   definition of a variable or function.
+    
+    if (DS.isInlineSpecified())
+      EmitDiag(DS.getInlineSpecLoc());
+    
+    // [dcl.constexpr]p1:
+    //   The constexpr specifier shall be applied only to the definition of a 
+    //   variable or variable template or the declaration of a function or 
+    //   function template.
+    
+    if (DS.isConstexprSpecified())
+      EmitDiag(DS.getConstexprSpecLoc());
+
+    // [dcl.fct.spec]p1:
+    //   Function-specifiers can be used only in function declarations.
+
+    if (DS.isVirtualSpecified())
+      EmitDiag(DS.getVirtualSpecLoc());
+
+    if (DS.isExplicitSpecified())
+      EmitDiag(DS.getExplicitSpecLoc());
+
+    if (DS.isNoreturnSpecified())
+      EmitDiag(DS.getNoreturnSpecLoc());
+  };
+
+  CheckValidDeclSpecifiers();
+  
   if (TInfo->getType()->isUndeducedType()) {
     Diag(D.getIdentifierLoc(),
          diag::warn_cxx14_compat_template_nontype_parm_auto_type)
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3911,6 +3911,9 @@
   "%select{|template parameter }0redeclaration">;
 def note_template_param_different_kind : Note<
   "template parameter has a different kind in template argument">;
+
+def err_invalid_decl_specifier_in_nontype_parm : Error<
+  "invalid declaration specifier in template non-type parameter">;
   
 def err_template_nontype_parm_different_type : Error<
   "template non-type parameter has a different type %0 in template "
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to