]> granicus.if.org Git - clang/commitdiff
When we run into a template parameter that should have a default
authorDouglas Gregor <dgregor@apple.com>
Thu, 27 Jan 2011 01:40:17 +0000 (01:40 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 27 Jan 2011 01:40:17 +0000 (01:40 +0000)
argument but doesn't (because previous template parameters had default
arguments), clear out all of the default arguments so that we maintain
the invariant that a template parameter has a default argument only if
subsequence template parameters also have default arguments.
Fixes a crash-on-invalid <rdar://problem/8913649>.

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

lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.param/p1.cpp

index eed41cc396c4630bbdc1ac627b26d37b80c148af..1d2de0fb523a343ff26b2b726e79514669168c26 100644 (file)
@@ -1149,6 +1149,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
   if (OldParams)
     OldParam = OldParams->begin();
 
+  bool RemoveDefaultArguments = false;
   for (TemplateParameterList::iterator NewParam = NewParams->begin(),
                                     NewParamEnd = NewParams->end();
        NewParam != NewParamEnd; ++NewParam) {
@@ -1317,13 +1318,14 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
     } else if (MissingDefaultArg) {
       // C++ [temp.param]p11:
       //   If a template-parameter of a class template has a default 
-      //   template-argument, each subsequent template- parameter shall either 
+      //   template-argument, each subsequent template-parameter shall either 
       //   have a default template-argument supplied or be a template parameter
       //   pack.
       Diag((*NewParam)->getLocation(),
            diag::err_template_param_default_arg_missing);
       Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
       Invalid = true;
+      RemoveDefaultArguments = true;
     }
 
     // If we have an old template parameter list that we're merging
@@ -1332,6 +1334,22 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
       ++OldParam;
   }
 
+  // We were missing some default arguments at the end of the list, so remove
+  // all of the default arguments.
+  if (RemoveDefaultArguments) {
+    for (TemplateParameterList::iterator NewParam = NewParams->begin(),
+                                      NewParamEnd = NewParams->end();
+         NewParam != NewParamEnd; ++NewParam) {
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*NewParam))
+        TTP->removeDefaultArgument();
+      else if (NonTypeTemplateParmDecl *NTTP 
+                                = dyn_cast<NonTypeTemplateParmDecl>(*NewParam))
+        NTTP->removeDefaultArgument();
+      else
+        cast<TemplateTemplateParmDecl>(*NewParam)->removeDefaultArgument();
+    }
+  }
+  
   return Invalid;
 }
 
index edc99733f089520e6030bbf05d1fa84a087b0126..e9a978961769c39aa2e3e48c6f3708478f57f91d 100644 (file)
@@ -4,3 +4,9 @@
 template<template<> class C> class D; // expected-error{{template template parameter must have its own template parameters}}
 
 
+struct A {};
+template<class M, 
+         class T = A,  // expected-note{{previous default template argument defined here}}
+         class C> // expected-error{{template parameter missing a default argument}}
+class X0 {}; // expected-note{{template is declared here}}
+X0<int> x0; // expected-error{{too few template arguments for class template 'X0'}}