[cfe-commits] r131802 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp

Douglas Gregor dgregor at apple.com
Sat May 21 11:53:30 PDT 2011


Author: dgregor
Date: Sat May 21 13:53:30 2011
New Revision: 131802

URL: http://llvm.org/viewvc/llvm-project?rev=131802&view=rev
Log:
Diagnose the presence of storage-class-specifiers on explicit
instantiations and specializations. Fixes <rdar://problem/9126453> and PR8700.

Added:
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=131802&r1=131801&r2=131802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat May 21 13:53:30 2011
@@ -1827,6 +1827,8 @@
   "parameter}0">;
 def err_function_specialization_in_class : Error<
   "cannot specialize a function %0 within class scope">;
+def err_explicit_specialization_storage_class : Error<
+  "explicit specialization cannot have a storage class">;
 
 // C++ class template specializations and out-of-line definitions
 def err_template_spec_needs_header : Error<
@@ -1983,6 +1985,8 @@
   "explicit instantiation declaration requires a name">;
 def err_explicit_instantiation_of_typedef : Error<
   "explicit instantiation of typedef %0">;
+def err_explicit_instantiation_storage_class : Error<
+  "explicit instantiation cannot have a storage class">;
 def err_explicit_instantiation_not_known : Error<
   "explicit instantiation of %0 does not refer to a function template, member "
   "function, member class, or static data member">;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=131802&r1=131801&r2=131802&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat May 21 13:53:30 2011
@@ -4595,6 +4595,16 @@
                                   (HasExplicitTemplateArgs ? &TemplateArgs : 0),
                                                      Previous))
         NewFD->setInvalidDecl();
+      
+      // C++ [dcl.stc]p1:
+      //   A storage-class-specifier shall not be specified in an explicit
+      //   specialization (14.7.3)
+      if (SC != SC_None) {
+        Diag(NewFD->getLocation(), 
+             diag::err_explicit_specialization_storage_class)
+          << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+      }
+      
     } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) {
       if (CheckMemberSpecialization(NewFD, Previous))
           NewFD->setInvalidDecl();

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=131802&r1=131801&r2=131802&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat May 21 13:53:30 2011
@@ -5377,7 +5377,7 @@
                                          SpecInfo->getPointOfInstantiation(),
                                              HasNoEffect))
     return true;
-
+  
   // Mark the prior declaration as an explicit specialization, so that later
   // clients know that this is an explicit specialization.
   if (!isFriend) {
@@ -5397,7 +5397,8 @@
                                         TemplArgs, /*InsertPos=*/0,
                                     SpecInfo->getTemplateSpecializationKind(),
                                         TemplArgsAsWritten);
-
+  FD->setStorageClass(Specialization->getStorageClass());
+  
   // The "previous declaration" for this function template specialization is
   // the prior function template specialization.
   Previous.clear();
@@ -5998,11 +5999,20 @@
   if (R.isNull())
     return true;
 
+  // C++ [dcl.stc]p1:
+  //   A storage-class-specifier shall not be specified in [...] an explicit 
+  //   instantiation (14.7.2) directive.
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
-    // Cannot explicitly instantiate a typedef.
     Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
       << Name;
     return true;
+  } else if (D.getDeclSpec().getStorageClassSpec() 
+                                                != DeclSpec::SCS_unspecified) {
+    // Complain about then remove the storage class specifier.
+    Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class)
+      << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+    
+    D.getMutableDeclSpec().ClearStorageClassSpecs();
   }
 
   // C++0x [temp.explicit]p1:

Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp?rev=131802&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp Sat May 21 13:53:30 2011
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// A storage-class-specifier shall not be specified in an explicit
+// specialization (14.7.3) or an explicit instantiation (14.7.2)
+// directive.
+template<typename T> void f(T) {}
+template<typename T> static void g(T) {}
+
+
+template<> static void f<int>(int); // expected-error{{explicit specialization cannot have a storage class}}
+template static void f<float>(float); // expected-error{{explicit instantiation cannot have a storage class}}
+
+template<> void f<double>(double);
+template void f<long>(long);
+
+template<> static void g<int>(int); // expected-error{{explicit specialization cannot have a storage class}}
+template static void g<float>(float); // expected-error{{explicit instantiation cannot have a storage class}}
+
+template<> void g<double>(double);
+template void g<long>(long);
+
+template<typename T>
+struct X {
+  static int value;
+};
+
+template<typename T>
+int X<T>::value = 17;
+
+template static int X<int>::value; // expected-error{{explicit instantiation cannot have a storage class}}
+
+template<> static int X<float>::value; // expected-error{{'static' can only be specified inside the class definition}}

Propchange: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list