diff options
-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); +} |