diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 4749962d045..50663f9f4ba 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -226,6 +226,10 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( Inst.NumTemplateArgs = TemplateArgs.size(); Inst.DeductionInfo = DeductionInfo; Inst.InstantiationRange = InstantiationRange; + AlreadyInstantiating = + !SemaRef.InstantiatingSpecializations + .insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind)) + .second; SemaRef.InNonInstantiationSFINAEContext = false; SemaRef.ActiveTemplateInstantiations.push_back(Inst); if (!Inst.isInstantiationRecord()) @@ -248,13 +252,14 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( PointOfInstantiation, InstantiationRange, Entity) {} Sema::InstantiatingTemplate::InstantiatingTemplate( - Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template, - ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange) + Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateParameter Param, + TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, + SourceRange InstantiationRange) : InstantiatingTemplate( SemaRef, ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation, - PointOfInstantiation, InstantiationRange, Template, nullptr, - TemplateArgs) {} + PointOfInstantiation, InstantiationRange, getAsNamedDecl(Param), + Template, TemplateArgs) {} Sema::InstantiatingTemplate::InstantiatingTemplate( Sema &SemaRef, SourceLocation PointOfInstantiation, @@ -264,7 +269,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange) : InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation, InstantiationRange, FunctionTemplate, nullptr, - TemplateArgs, &DeductionInfo) {} + TemplateArgs, &DeductionInfo) { + assert( + Kind == ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution || + Kind == ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution); +} Sema::InstantiatingTemplate::InstantiatingTemplate( Sema &SemaRef, SourceLocation PointOfInstantiation, @@ -328,7 +337,8 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( void Sema::InstantiatingTemplate::Clear() { if (!Invalid) { - if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) { + auto &Active = SemaRef.ActiveTemplateInstantiations.back(); + if (!Active.isInstantiationRecord()) { assert(SemaRef.NonInstantiationEntries > 0); --SemaRef.NonInstantiationEntries; } @@ -346,6 +356,10 @@ void Sema::InstantiatingTemplate::Clear() { SemaRef.ActiveTemplateInstantiationLookupModules.pop_back(); } + if (!AlreadyInstantiating) + SemaRef.InstantiatingSpecializations.erase( + std::make_pair(Active.Entity, Active.Kind)); + SemaRef.ActiveTemplateInstantiations.pop_back(); Invalid = true; } @@ -444,7 +458,7 @@ void Sema::PrintInstantiationStack() { } case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: { - TemplateDecl *Template = cast<TemplateDecl>(Active->Entity); + TemplateDecl *Template = cast<TemplateDecl>(Active->Template); SmallVector<char, 128> TemplateArgsStr; llvm::raw_svector_ostream OS(TemplateArgsStr); Template->printName(OS); @@ -1895,6 +1909,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); if (Inst.isInvalid()) return true; + assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller"); PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(), "instantiating class definition"); @@ -2120,6 +2135,8 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation, InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); if (Inst.isInvalid()) return true; + if (Inst.isAlreadyInstantiating()) + return false; PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(), "instantiating enum definition"); @@ -2194,6 +2211,12 @@ bool Sema::InstantiateInClassInitializer( InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); if (Inst.isInvalid()) return true; + if (Inst.isAlreadyInstantiating()) { + // Error out if we hit an instantiation cycle for this initializer. + Diag(PointOfInstantiation, diag::err_in_class_initializer_cycle) + << Instantiation; + return true; + } PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(), "instantiating default member init"); |