[cfe-commits] r73245 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplate.cpp test/SemaTemplate/temp_class_spec_neg.cpp

Douglas Gregor dgregor at apple.com
Fri Jun 12 12:43:02 PDT 2009


Author: dgregor
Date: Fri Jun 12 14:43:02 2009
New Revision: 73245

URL: http://llvm.org/viewvc/llvm-project?rev=73245&view=rev
Log:
Verify that the template parameters of a class template partial
specialization do not have default arguments 
(C++ [temp.class.spec]p10). 

Added:
    cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    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=73245&r1=73244&r2=73245&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 12 14:43:02 2009
@@ -742,9 +742,6 @@
   "template specialization requires 'template<>'">;
 def err_template_spec_extra_headers : Error<
   "template specialization must have a single 'template<>' header">;
-def unsup_template_partial_spec_ordering : Error<
-  "partial ordering of class template partial specializations is not yet "
-  "supported">;
 def err_template_spec_decl_out_of_scope_global : Error<
   "class template specialization of %0 must occur in the global scope">;
 def err_template_spec_decl_out_of_scope : Error<
@@ -759,6 +756,13 @@
   "%select{class template specialization|explicit instantiation}0 of %1 must "
   "occur at global scope">;
 
+// C++ Class Template Partial Specialization
+def err_default_arg_in_partial_spec : Error<
+    "default template argument in a class template partial specialization">;
+def unsup_template_partial_spec_ordering : Error<
+  "partial ordering of class template partial specializations is not yet "
+  "supported">;
+
 // C++ Template Instantiation
 def err_template_recursion_depth_exceeded : Error<
   "recursive template instantiation exceeded maximum depth of %0">,DefaultFatal;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=73245&r1=73244&r2=73245&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Jun 12 14:43:02 2009
@@ -1731,7 +1731,12 @@
   //   template template argument with the corresponding parameter;
   //   partial specializations are not considered even if their
   //   parameter lists match that of the template template parameter.
-  if (!isa<ClassTemplateDecl>(Template)) {
+  //
+  // Note that we also allow template template parameters here, which
+  // will happen when we are dealing with, e.g., class template
+  // partial specializations.
+  if (!isa<ClassTemplateDecl>(Template) && 
+      !isa<TemplateTemplateParmDecl>(Template)) {
     assert(isa<FunctionTemplateDecl>(Template) && 
            "Only function templates are possible here");
     Diag(Arg->getSourceRange().getBegin(), 
@@ -2033,9 +2038,41 @@
       return true;
     }
 
-    // FIXME: We'll need more checks, here!
-    if (TemplateParams->size() > 0)
+    if (TemplateParams->size() > 0) {
       isPartialSpecialization = true;
+
+      // C++ [temp.class.spec]p10:
+      //   The template parameter list of a specialization shall not
+      //   contain default template argument values.
+      for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+        Decl *Param = TemplateParams->getParam(I);
+        if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+          if (TTP->hasDefaultArgument()) {
+            Diag(TTP->getDefaultArgumentLoc(), 
+                 diag::err_default_arg_in_partial_spec);
+            TTP->setDefaultArgument(QualType(), SourceLocation(), false);
+          }
+        } else if (NonTypeTemplateParmDecl *NTTP
+                     = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+          if (Expr *DefArg = NTTP->getDefaultArgument()) {
+            Diag(NTTP->getDefaultArgumentLoc(), 
+                 diag::err_default_arg_in_partial_spec)
+              << DefArg->getSourceRange();
+            NTTP->setDefaultArgument(0);
+            DefArg->Destroy(Context);
+          }
+        } else {
+          TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
+          if (Expr *DefArg = TTP->getDefaultArgument()) {
+            Diag(TTP->getDefaultArgumentLoc(), 
+                 diag::err_default_arg_in_partial_spec)
+              << DefArg->getSourceRange();
+            TTP->setDefaultArgument(0);
+            DefArg->Destroy(Context);
+          }
+        }
+      }
+    }
   }
 
   // Check that the specialization uses the same tag kind as the
@@ -2078,11 +2115,12 @@
   // Find the class template (partial) specialization declaration that
   // corresponds to these arguments.
   llvm::FoldingSetNodeID ID;
-  if (isPartialSpecialization)
+  if (isPartialSpecialization) {
     // FIXME: Template parameter list matters, too
     ClassTemplatePartialSpecializationDecl::Profile(ID, 
                                     ConvertedTemplateArgs.getFlatArgumentList(),
                                               ConvertedTemplateArgs.flatSize());
+  }
   else
     ClassTemplateSpecializationDecl::Profile(ID,
                                     ConvertedTemplateArgs.getFlatArgumentList(),

Added: cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp?rev=73245&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp (added)
+++ cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp Fri Jun 12 14:43:02 2009
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> struct vector;
+
+template<typename T, int N, template<typename X> class TT>
+struct Test0;
+
+template<typename T = int, // expected-error{{default template argument}}
+         int N = 17, // expected-error{{default template argument}}
+         template<typename X> class TT = ::vector> // expected-error{{default template argument}}
+  struct Test0<T*, N, TT> { };

Propchange: cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list