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. :(
llvm-svn: 280190
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f7d9787..d686798 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3396,6 +3396,13 @@
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 @@
}
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 @@
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 @@
}
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 @@
// 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 @@
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
- if (Inst.isInvalid())
+ if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return;
PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
"instantiating variable definition");