aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--include/clang/Basic/LangOptions.def2
-rw-r--r--include/clang/Driver/CC1Options.td2
-rw-r--r--include/clang/Driver/Options.td2
-rw-r--r--lib/AST/ExprConstant.cpp16
-rw-r--r--lib/Driver/Tools.cpp8
-rw-r--r--lib/Frontend/CompilerInvocation.cpp8
-rw-r--r--test/SemaCXX/constexpr-depth.cpp8
-rw-r--r--test/SemaTemplate/instantiation-depth.cpp4
9 files changed, 40 insertions, 12 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6c5e79a901..c8b138f2c7 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2384,7 +2384,7 @@ def err_template_recursion_depth_exceeded : Error<
"recursive template instantiation exceeded maximum depth of %0">,
DefaultFatal, NoSFINAE;
def note_template_recursion_depth : Note<
- "use -ftemplate-depth-N to increase recursive template instantiation depth">;
+ "use -ftemplate-depth=N to increase recursive template instantiation depth">;
def err_template_instantiate_within_definition : Error<
"%select{implicit|explicit}0 instantiation of template %1 within its"
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index 5cf40ec578..1936be1fb6 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -145,6 +145,8 @@ ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
BENIGN_LANGOPT(InstantiationDepth, 32, 1024,
"maximum template instantiation depth")
+BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
+ "maximum constexpr call depth")
BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
"if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.")
VALUE_LANGOPT(MSCVersion, 32, 0,
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index c8f4a1d77e..01e4e4b687 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -584,6 +584,8 @@ def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">,
HelpText<"Give inline C++ member functions default visibility by default">;
def ftemplate_depth : Separate<"-ftemplate-depth">,
HelpText<"Maximum depth of recursive template instantiation">;
+def fconstexpr_depth : Separate<"-fconstexpr-depth">,
+ HelpText<"Maximum depth of recursive constexpr function calls">;
def Wlarge_by_value_copy : Separate<"-Wlarge-by-value-copy">,
HelpText<"Warn if a function definition returns or accepts an object larger "
"in bytes that a given value">;
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 1cda33d758..470ca5716a 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -478,7 +478,9 @@ def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<f_Group>;
def fstrict_overflow : Flag<"-fstrict-overflow">, Group<f_Group>;
def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>;
def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>;
+def ftemplate_depth_EQ : Joined<"-ftemplate-depth=">, Group<f_Group>;
def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>;
+def fconstexpr_depth_EQ : Joined<"-fconstexpr-depth=">, Group<f_Group>;
def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
Group<f_Group>;
def ftest_coverage : Flag<"-ftest-coverage">, Group<f_Group>;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index d602be4581..81fe7e3a4e 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -257,9 +257,6 @@ namespace {
/// CurrentCall - The top of the constexpr call stack.
CallStackFrame *CurrentCall;
- /// NumCalls - The number of calls we've evaluated so far.
- unsigned NumCalls;
-
/// CallStackDepth - The number of calls in the call stack right now.
unsigned CallStackDepth;
@@ -282,7 +279,7 @@ namespace {
EvalInfo(const ASTContext &C, Expr::EvalStatus &S)
- : Ctx(C), EvalStatus(S), CurrentCall(0), NumCalls(0), CallStackDepth(0),
+ : Ctx(C), EvalStatus(S), CurrentCall(0), CallStackDepth(0),
BottomFrame(*this, 0, 0), EvaluatingDecl(0), EvaluatingDeclValue(0) {}
const CCValue *getOpaqueValue(const OpaqueValueExpr *e) const {
@@ -296,7 +293,11 @@ namespace {
EvaluatingDeclValue = &Value;
}
- const LangOptions &getLangOpts() { return Ctx.getLangOptions(); }
+ const LangOptions &getLangOpts() const { return Ctx.getLangOptions(); }
+
+ bool atCallLimit() const {
+ return CallStackDepth > getLangOpts().ConstexprCallDepth;
+ }
};
CallStackFrame::CallStackFrame(EvalInfo &Info, const LValue *This,
@@ -1278,8 +1279,7 @@ static bool EvaluateArgs(ArrayRef<const Expr*> Args, ArgVector &ArgValues,
static bool HandleFunctionCall(const LValue *This, ArrayRef<const Expr*> Args,
const Stmt *Body, EvalInfo &Info,
CCValue &Result) {
- // FIXME: Implement a proper call limit, along with a command-line flag.
- if (Info.NumCalls >= 1000000 || Info.CallStackDepth >= 512)
+ if (Info.atCallLimit())
return false;
ArgVector ArgValues(Args.size());
@@ -1296,7 +1296,7 @@ static bool HandleConstructorCall(const LValue &This,
const CXXConstructorDecl *Definition,
EvalInfo &Info,
APValue &Result) {
- if (Info.NumCalls >= 1000000 || Info.CallStackDepth >= 512)
+ if (Info.atCallLimit())
return false;
ArgVector ArgValues(Args.size());
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 4229987f52..918b4551c5 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1619,11 +1619,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) {
+ if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
+ options::OPT_ftemplate_depth_EQ)) {
CmdArgs.push_back("-ftemplate-depth");
CmdArgs.push_back(A->getValue(Args));
}
+ if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
+ CmdArgs.push_back("-fconstexpr-depth");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
options::OPT_Wlarge_by_value_copy_def)) {
CmdArgs.push_back("-Wlarge-by-value-copy");
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 738facf069..34080908c0 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -789,6 +789,10 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-ftemplate-depth");
Res.push_back(llvm::utostr(Opts.InstantiationDepth));
}
+ if (Opts.ConstexprCallDepth != DefaultLangOpts.ConstexprCallDepth) {
+ Res.push_back("-fconstexpr-depth");
+ Res.push_back(llvm::utostr(Opts.ConstexprCallDepth));
+ }
if (!Opts.ObjCConstantStringClass.empty()) {
Res.push_back("-fconstant-string-class");
Res.push_back(Opts.ObjCConstantStringClass);
@@ -1777,7 +1781,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
Opts.MathErrno = Args.hasArg(OPT_fmath_errno);
Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 1024,
- Diags);
+ Diags);
+ Opts.ConstexprCallDepth = Args.getLastArgIntValue(OPT_fconstexpr_depth, 512,
+ Diags);
Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy,
0, Diags);
diff --git a/test/SemaCXX/constexpr-depth.cpp b/test/SemaCXX/constexpr-depth.cpp
new file mode 100644
index 0000000000..b8ae6682c5
--- /dev/null
+++ b/test/SemaCXX/constexpr-depth.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=128 -fconstexpr-depth 128
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -DMAX=1 -fconstexpr-depth 1
+// RUN: %clang -std=c++11 -fsyntax-only -Xclang -verify %s -DMAX=10 -fconstexpr-depth=10
+
+constexpr int depth(int n) { return n > 1 ? depth(n-1) : 0; }
+
+constexpr int kBad = depth(MAX + 1); // expected-error {{must be initialized by a constant expression}}
+constexpr int kGood = depth(MAX);
diff --git a/test/SemaTemplate/instantiation-depth.cpp b/test/SemaTemplate/instantiation-depth.cpp
index a2b9d2eb15..8e1b80368d 100644
--- a/test/SemaTemplate/instantiation-depth.cpp
+++ b/test/SemaTemplate/instantiation-depth.cpp
@@ -1,10 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-depth 5 -ftemplate-backtrace-limit 4 %s
+// RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth-5 -ftemplate-backtrace-limit=4 %s
+// RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth=5 -ftemplate-backtrace-limit=4 %s
template<typename T> struct X : X<T*> { }; \
// expected-error{{recursive template instantiation exceeded maximum depth of 5}} \
// expected-note 3 {{instantiation of template class}} \
// expected-note {{skipping 2 contexts in backtrace}} \
-// expected-note {{use -ftemplate-depth-N to increase recursive template instantiation depth}}
+// expected-note {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
void test() {
(void)sizeof(X<int>); // expected-note {{instantiation of template class}}