]> granicus.if.org Git - clang/commitdiff
Diagnose the presence of storage-class-specifiers on explicit
authorDouglas Gregor <dgregor@apple.com>
Sat, 21 May 2011 18:53:30 +0000 (18:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 21 May 2011 18:53:30 +0000 (18:53 +0000)
instantiations and specializations. Fixes <rdar://problem/9126453> and PR8700.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131802 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp [new file with mode: 0644]

index 92a8228f14198bf56d8e0d15f4ac99ef4199ce80..00cd81f7e350a6f114f4cdc4112254b5e4f9d8fd 100644 (file)
@@ -1827,6 +1827,8 @@ def err_not_class_template_specialization : Error<
   "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 @@ def err_explicit_instantiation_requires_name : Error<
   "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">;
index a5a494877f2d8f052a667f92fa0738228134ed14..3965a45171c4797dc3319285cebdd163a90ac230 100644 (file)
@@ -4595,6 +4595,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                   (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();
index 9d8d7f608e3c8844f53979c50e93259e653bc452..f3392e41830155ae781ebc3f5c82cc427ff62645 100644 (file)
@@ -5377,7 +5377,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
                                          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 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
                                         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 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
   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:
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp
new file mode 100644 (file)
index 0000000..40917b8
--- /dev/null
@@ -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}}