diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-07-14 23:14:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-07-14 23:14:12 +0000 |
commit | 5f0e252f635ab98060f6eb8e51babf6767064a8d (patch) | |
tree | e1bb1852ebbd977f2ce1fda248b614880464f970 | |
parent | 25e72a892019026b06677aa6100065354b6fa451 (diff) | |
download | bcm5719-llvm-5f0e252f635ab98060f6eb8e51babf6767064a8d.tar.gz bcm5719-llvm-5f0e252f635ab98060f6eb8e51babf6767064a8d.zip |
When there are extra or missing template parameter lists in a template
definition, we're likely going to end up breaking the invariants of
the template system, e.g., that the depths of template parameter lists
match up with the nesting template of the template. So, make sure we
mark such ill-formed declarations as invalid or don't even build them
at all.
llvm-svn: 108372
-rw-r--r-- | clang/lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 19 | ||||
-rw-r--r-- | clang/test/SemaTemplate/deduction-crash.cpp | 59 |
4 files changed, 96 insertions, 9 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index d902dfea1f1..8336918c134 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2956,7 +2956,8 @@ public: TemplateParameterList **ParamLists, unsigned NumParamLists, bool IsFriend, - bool &IsExplicitSpecialization); + bool &IsExplicitSpecialization, + bool &Invalid); DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9c683f726af..c1c898fac5f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2572,6 +2572,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // determine whether we have a template or a template specialization. bool isExplicitSpecialization = false; unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); + bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), @@ -2579,7 +2580,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, (TemplateParameterList**)TemplateParamLists.get(), TemplateParamLists.size(), /*never a friend*/ false, - isExplicitSpecialization)) { + isExplicitSpecialization, + Invalid)) { // All but one template parameter lists have been matching. --NumMatchedTemplateParamLists; @@ -2606,7 +2608,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, VarDecl *NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), II, R, TInfo, SC, SCAsWritten); - if (D.isInvalidType()) + if (D.isInvalidType() || Invalid) NewVD->setInvalidDecl(); SetNestedNameSpecifier(NewVD, D); @@ -3156,6 +3158,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); + bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), @@ -3163,7 +3166,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (TemplateParameterList**)TemplateParamLists.get(), TemplateParamLists.size(), isFriend, - isExplicitSpecialization)) { + isExplicitSpecialization, + Invalid)) { // All but one template parameter lists have been matching. --NumMatchedTemplateParamLists; @@ -3214,6 +3218,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (TemplateParameterList**)TemplateParamLists.release()); } + if (Invalid) { + NewFD->setInvalidDecl(); + if (FunctionTemplate) + FunctionTemplate->setInvalidDecl(); + } + // C++ [dcl.fct.spec]p5: // The virtual specifier shall only be used in declarations of // nonstatic class member functions that appear within a @@ -5037,19 +5047,24 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); + bool Invalid = false; if (TUK != TUK_Reference) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, (TemplateParameterList**)TemplateParameterLists.get(), TemplateParameterLists.size(), TUK == TUK_Friend, - isExplicitSpecialization)) { + isExplicitSpecialization, + Invalid)) { // All but one template parameter lists have been matching. --NumMatchedTemplateParamLists; if (TemplateParams->size() > 0) { // This is a declaration or definition of a class template (which may // be a member of another template). + if (Invalid) + return DeclPtrTy(); + OwnedDecl = false; DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, @@ -5069,7 +5084,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; bool isStdBadAlloc = false; - bool Invalid = false; RedeclarationKind Redecl = ForRedeclaration; if (TUK == TUK_Friend || TUK == TUK_Reference) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 7cc43178450..f121954eed6 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1233,7 +1233,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, TemplateParameterList **ParamLists, unsigned NumParamLists, bool IsFriend, - bool &IsExplicitSpecialization) { + bool &IsExplicitSpecialization, + bool &Invalid) { IsExplicitSpecialization = false; // Find the template-ids that occur within the nested-name-specifier. These @@ -1311,6 +1312,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, diag::err_template_spec_needs_template_parameters) << TemplateId << SS.getRange(); + Invalid = true; } else { Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header) << SS.getRange() @@ -1373,7 +1375,13 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, << ExplicitSpecializationsInSpecifier.back(); ExplicitSpecializationsInSpecifier.pop_back(); } - + + // We have a template parameter list with no corresponding scope, which + // means that the resulting template declaration can't be instantiated + // properly (we'll end up with dependent nodes when we shouldn't). + if (!isExplicitSpecHeader) + Invalid = true; + ++Idx; } } @@ -3622,12 +3630,17 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // template. // FIXME: We probably shouldn't complain about these headers for // friend declarations. + bool Invalid = false; TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS, (TemplateParameterList**)TemplateParameterLists.get(), TemplateParameterLists.size(), TUK == TUK_Friend, - isExplicitSpecialization); + isExplicitSpecialization, + Invalid); + if (Invalid) + return true; + unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); if (TemplateParams) --NumMatchedTemplateParamLists; diff --git a/clang/test/SemaTemplate/deduction-crash.cpp b/clang/test/SemaTemplate/deduction-crash.cpp new file mode 100644 index 00000000000..1860c7577c7 --- /dev/null +++ b/clang/test/SemaTemplate/deduction-crash.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -fsyntax-only %s 2>&1| FileCheck %s + +// PR7511 + +// Note that the error count below doesn't matter. We just want to +// make sure that the parser doesn't crash. +// CHECK: 16 errors +template<a> +struct int_; + +template<a> +template<int,typename T1,typename> +struct ac +{ + typedef T1 ae +}; + +template<class>struct aaa +{ + typedef ac<1,int,int>::ae ae +}; + +template<class> +struct state_machine +{ + typedef aaa<int>::ae aaa; + int start() + { + ant(0); + } + + template<class> + struct region_processing_helper + { + template<class,int=0> + struct In; + + template<int my> + struct In<a::int_<aaa::a>,my>; + + template<class Event> + int process(Event) + { + In<a::int_<0> > a; + } + } + template<class Event> + int ant(Event) + { + region_processing_helper<int>* helper; + helper->process(0) + } +}; + +int a() +{ + state_machine<int> p; + p.ant(0); +} |