From: Douglas Gregor Date: Thu, 27 Jan 2011 01:40:17 +0000 (+0000) Subject: When we run into a template parameter that should have a default X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fd1a8fd240c8067e286e3881aac2bd8b700517d3;p=clang When we run into a template parameter that should have a default 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124345 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index eed41cc396..1d2de0fb52 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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(*NewParam)) + TTP->removeDefaultArgument(); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast(*NewParam)) + NTTP->removeDefaultArgument(); + else + cast(*NewParam)->removeDefaultArgument(); + } + } + return Invalid; } diff --git a/test/CXX/temp/temp.param/p1.cpp b/test/CXX/temp/temp.param/p1.cpp index edc99733f0..e9a9789617 100644 --- a/test/CXX/temp/temp.param/p1.cpp +++ b/test/CXX/temp/temp.param/p1.cpp @@ -4,3 +4,9 @@ template class C> class D; // expected-error{{template template parameter must have its own template parameters}} +struct A {}; +template // expected-error{{template parameter missing a default argument}} +class X0 {}; // expected-note{{template is declared here}} +X0 x0; // expected-error{{too few template arguments for class template 'X0'}}