diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 64 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 91 |
3 files changed, 147 insertions, 20 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index d68924c7c0..c4964bf69b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -245,7 +245,7 @@ public: DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID); if (!Diags.isBuiltinNote(DiagID) && !ActiveTemplateInstantiations.empty() && - ActiveTemplateInstantiations.back().Entity + ActiveTemplateInstantiations.back() != LastTemplateInstantiationErrorContext) DB << PostDiagnosticHook(PrintInstantiationStackHook, this); return DB; @@ -1673,16 +1673,61 @@ public: /// \brief A template instantiation that is currently in progress. struct ActiveTemplateInstantiation { + /// \brief The kind of template instantiation we are performing + enum { + /// We are instantiating a template declaration. The entity is + /// the declaration we're instantiation (e.g., a + /// ClassTemplateSpecializationDecl). + TemplateInstantiation, + + /// We are instantiating a default argument for a template + /// parameter. The Entity is the template, and + /// TemplateArgs/NumTemplateArguments provides the template + /// arguments as specified. + DefaultTemplateArgumentInstantiation + } Kind; + /// \brief The point of instantiation within the source code. SourceLocation PointOfInstantiation; /// \brief The entity that is being instantiated. - ClassTemplateSpecializationDecl *Entity; + uintptr_t Entity; + + // \brief If this the instantiation of a default template + // argument, the list of tempalte arguments. + const TemplateArgument *TemplateArgs; + + /// \brief The number of template arguments in TemplateArgs. + unsigned NumTemplateArgs; /// \brief The source range that covers the construct that cause /// the instantiation, e.g., the template-id that causes a class /// template instantiation. SourceRange InstantiationRange; + + friend bool operator==(const ActiveTemplateInstantiation &X, + const ActiveTemplateInstantiation &Y) { + if (X.Kind != Y.Kind) + return false; + + if (X.Entity != Y.Entity) + return false; + + switch (X.Kind) { + case TemplateInstantiation: + return true; + + case DefaultTemplateArgumentInstantiation: + return X.TemplateArgs == Y.TemplateArgs; + } + + return true; + } + + friend bool operator!=(const ActiveTemplateInstantiation &X, + const ActiveTemplateInstantiation &Y) { + return !(X == Y); + } }; /// \brief List of active template instantiations. @@ -1701,7 +1746,7 @@ public: /// instantiation backtraces when there are multiple errors in the /// same instantiation. FIXME: Does this belong in Sema? It's tough /// to implement it anywhere else. - ClassTemplateSpecializationDecl *LastTemplateInstantiationErrorContext; + ActiveTemplateInstantiation LastTemplateInstantiationErrorContext; /// \brief A stack object to be created when performing template /// instantiation. @@ -1715,9 +1760,19 @@ public: /// Destruction of this object will pop the named instantiation off /// the stack. struct InstantiatingTemplate { + /// \brief Note that we are instantiating a class template. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *Entity, SourceRange InstantiationRange = SourceRange()); + + /// \brief Note that we are instantiating a default argument in a + /// template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange = SourceRange()); + ~InstantiatingTemplate(); /// \brief Determines whether we have exceeded the maximum @@ -1728,6 +1783,9 @@ public: Sema &SemaRef; bool Invalid; + bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, + SourceRange InstantiationRange); + InstantiatingTemplate(const InstantiatingTemplate&); // not implemented InstantiatingTemplate& diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index fc1173d9d1..ea91a3836a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -825,10 +825,15 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. - if (ArgType->isDependentType()) + if (ArgType->isDependentType()) { + InstantiatingTemplate Inst(*this, TemplateLoc, + Template, &Converted[0], + Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); ArgType = InstantiateType(ArgType, &Converted[0], Converted.size(), TTP->getDefaultArgumentLoc(), TTP->getDeclName()); + } if (ArgType.isNull()) return true; @@ -888,6 +893,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, QualType NTTPType = NTTP->getType(); if (NTTPType->isDependentType()) { // Instantiate the type of the non-type template parameter. + InstantiatingTemplate Inst(*this, TemplateLoc, + Template, &Converted[0], + Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); + NTTPType = InstantiateType(NTTPType, &Converted[0], Converted.size(), NTTP->getLocation(), diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 057b256ddd..21694b2e73 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -30,19 +30,38 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *Entity, SourceRange InstantiationRange) : SemaRef(SemaRef) { - if (SemaRef.ActiveTemplateInstantiations.size() - > SemaRef.getLangOptions().InstantiationDepth) { - SemaRef.Diag(PointOfInstantiation, - diag::err_template_recursion_depth_exceeded) - << SemaRef.getLangOptions().InstantiationDepth - << InstantiationRange; - SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth) - << SemaRef.getLangOptions().InstantiationDepth; - Invalid = true; - } else { + + Invalid = CheckInstantiationDepth(PointOfInstantiation, + InstantiationRange); + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(Entity); + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + Invalid = false; + } +} + +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + SourceLocation PointOfInstantiation, + TemplateDecl *Template, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) + : SemaRef(SemaRef) { + + Invalid = CheckInstantiationDepth(PointOfInstantiation, + InstantiationRange); + if (!Invalid) { ActiveTemplateInstantiation Inst; + Inst.Kind + = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation; Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = Entity; + Inst.Entity = reinterpret_cast<uintptr_t>(Template); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); Invalid = false; @@ -54,12 +73,28 @@ Sema::InstantiatingTemplate::~InstantiatingTemplate() { SemaRef.ActiveTemplateInstantiations.pop_back(); } +bool Sema::InstantiatingTemplate::CheckInstantiationDepth( + SourceLocation PointOfInstantiation, + SourceRange InstantiationRange) { + if (SemaRef.ActiveTemplateInstantiations.size() + <= SemaRef.getLangOptions().InstantiationDepth) + return false; + + SemaRef.Diag(PointOfInstantiation, + diag::err_template_recursion_depth_exceeded) + << SemaRef.getLangOptions().InstantiationDepth + << InstantiationRange; + SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth) + << SemaRef.getLangOptions().InstantiationDepth; + return true; +} + /// \brief Post-diagnostic hook for printing the instantiation stack. void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) { Sema &SemaRef = *static_cast<Sema*>(Cookie); SemaRef.PrintInstantiationStack(); SemaRef.LastTemplateInstantiationErrorContext - = SemaRef.ActiveTemplateInstantiations.back().Entity; + = SemaRef.ActiveTemplateInstantiations.back(); } /// \brief Prints the current instantiation stack through a series of @@ -70,10 +105,30 @@ void Sema::PrintInstantiationStack() { ActiveEnd = ActiveTemplateInstantiations.rend(); Active != ActiveEnd; ++Active) { - Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), - diag::note_template_class_instantiation_here) - << Context.getTypeDeclType(Active->Entity) - << Active->InstantiationRange; + switch (Active->Kind) { + case ActiveTemplateInstantiation::TemplateInstantiation: { + ClassTemplateSpecializationDecl *Spec + = cast<ClassTemplateSpecializationDecl>((Decl*)Active->Entity); + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_template_class_instantiation_here) + << Context.getTypeDeclType(Spec) + << Active->InstantiationRange; + break; + } + + case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: { + TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity); + std::string TemplateArgsStr + = ClassTemplateSpecializationType::PrintTemplateArgumentList( + Active->TemplateArgs, + Active->NumTemplateArgs); + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_default_arg_instantiation_here) + << (Template->getNameAsString() + TemplateArgsStr) + << Active->InstantiationRange; + break; + } + } } } @@ -482,6 +537,10 @@ QualType Sema::InstantiateType(QualType T, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation Loc, DeclarationName Entity) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + // If T is not a dependent type, there is nothing to do. if (!T->isDependentType()) return T; |