summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-08-31 02:15:21 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-08-31 02:15:21 +0000
commit434bc3478f4a1c49e18cc881b8135b9d073a23c9 (patch)
tree82479b005d3e825c49c1e11b0deff2d0bb41fe8f /lib/Sema/SemaTemplateInstantiate.cpp
parentf08aef7aa48a59d900845b61962c19ba1bec4f4c (diff)
PR12298 et al: don't recursively instantiate a template specialization from
within the instantiation of that same specialization. This could previously happen for eagerly-instantiated function templates, variable templates, exception specifications, default arguments, and a handful of other cases. We still have an issue here for default template arguments that recursively make use of themselves and likewise for substitution into the type of a non-type template parameter, but in those cases we're producing a different entity each time, so they should instead be caught by the instantiation depth limit. However, currently we will typically run out of stack before we reach it. :( git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@280190 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp37
1 files changed, 30 insertions, 7 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4749962d04..50663f9f4b 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/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");