diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 37 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 35 |
5 files changed, 71 insertions, 22 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c756d1f6ab6..9df9c63cfdf 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9645,7 +9645,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } VarDecl *Def; - if ((Def = VDecl->getDefinition()) && Def != VDecl) { + if ((Def = VDecl->getDefinition()) && Def != VDecl && + (!VDecl->isStaticDataMember() || VDecl->isOutOfLine())) { NamedDecl *Hidden = nullptr; if (!hasVisibleDefinition(Def, &Hidden) && (VDecl->getFormalLinkage() == InternalLinkage || diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4bf17a6d88c..ce371e023c9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4545,6 +4545,11 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, MutiLevelArgList.getInnermost()); if (Inst.isInvalid()) return ExprError(); + if (Inst.isAlreadyInstantiating()) { + Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD; + Param->setInvalidDecl(); + return ExprError(); + } ExprResult Result; { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ea0357a3359..ab5f545181b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3329,7 +3329,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, // on the previously-computed template arguments. if (ArgType->getType()->isDependentType()) { Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, - Template, Converted, + Param, Template, Converted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return nullptr; @@ -3381,7 +3381,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, NonTypeTemplateParmDecl *Param, SmallVectorImpl<TemplateArgument> &Converted) { Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, - Template, Converted, + Param, Template, Converted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return ExprError(); @@ -3432,8 +3432,9 @@ SubstDefaultTemplateArgument(Sema &SemaRef, TemplateTemplateParmDecl *Param, SmallVectorImpl<TemplateArgument> &Converted, NestedNameSpecifierLoc &QualifierLoc) { - Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Template, Converted, - SourceRange(TemplateLoc, RAngleLoc)); + Sema::InstantiatingTemplate Inst( + SemaRef, TemplateLoc, TemplateParameter(Param), Template, Converted, + SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return TemplateName(); @@ -4054,7 +4055,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, } // Introduce an instantiation record that describes where we are using - // the default template argument. + // the default template argument. We're not actually instantiating a + // template here, we just create this object to put a note into the + // context stack. InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, Converted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) 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"); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f7d9787fbea..d686798be13 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3396,6 +3396,13 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, UpdateExceptionSpec(Decl, EST_None); return; } + if (Inst.isAlreadyInstantiating()) { + // This exception specification indirectly depends on itself. Reject. + // FIXME: Corresponding rule in the standard? + Diag(PointOfInstantiation, diag::err_exception_spec_cycle) << Decl; + UpdateExceptionSpec(Decl, EST_None); + return; + } // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. @@ -3647,7 +3654,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, } InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); - if (Inst.isInvalid()) + if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(), "instantiating function definition"); @@ -3914,10 +3921,6 @@ void Sema::InstantiateVariableInitializer( else if (OldVar->isInline()) Var->setImplicitlyInline(); - if (Var->getAnyInitializer()) - // We already have an initializer in the class. - return; - if (OldVar->getInit()) { if (Var->isStaticDataMember() && !OldVar->isOutOfLine()) PushExpressionEvaluationContext(Sema::ConstantEvaluated, OldVar); @@ -3953,9 +3956,23 @@ void Sema::InstantiateVariableInitializer( } PopExpressionEvaluationContext(); - } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) && - !Var->isCXXForRangeDecl()) + } else { + if (Var->isStaticDataMember()) { + if (!Var->isOutOfLine()) + return; + + // If the declaration inside the class had an initializer, don't add + // another one to the out-of-line definition. + if (OldVar->getFirstDecl()->hasInit()) + return; + } + + // We'll add an initializer to a for-range declaration later. + if (Var->isCXXForRangeDecl()) + return; + ActOnUninitializedDecl(Var, false); + } } /// \brief Instantiate the definition of the given variable from its @@ -4045,7 +4062,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, // FIXME: Factor out the duplicated instantiation context setup/tear down // code here. InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); - if (Inst.isInvalid()) + if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), "instantiating variable initializer"); @@ -4174,7 +4191,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, } InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); - if (Inst.isInvalid()) + if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), "instantiating variable definition"); |