From c18c42345636e2866fed75c7e434fb659d747672 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 21 Nov 2011 19:36:32 +0000 Subject: [PATCH] Add driver arguments -ftemplate-depth=N and -fconstexpr-depth=N, with the same semantics and defaults as the corresponding g++ arguments. The historical g++ argument -ftemplate-depth-N is kept for compatibility, but modern g++ versions no longer document that option. Add -cc1 argument -fconstexpr-depth N to implement the corresponding functionality. The -ftemplate-depth=N part of this fixes PR9890. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145045 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 +- include/clang/Basic/LangOptions.def | 2 ++ include/clang/Driver/CC1Options.td | 2 ++ include/clang/Driver/Options.td | 2 ++ lib/AST/ExprConstant.cpp | 16 ++++++++-------- lib/Driver/Tools.cpp | 8 +++++++- lib/Frontend/CompilerInvocation.cpp | 8 +++++++- test/SemaCXX/constexpr-depth.cpp | 8 ++++++++ test/SemaTemplate/instantiation-depth.cpp | 4 +++- 9 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 test/SemaCXX/constexpr-depth.cpp 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; def fstrict_overflow : Flag<"-fstrict-overflow">, Group; def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; def ftabstop_EQ : Joined<"-ftabstop=">, Group; +def ftemplate_depth_EQ : Joined<"-ftemplate-depth=">, Group; def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group; +def fconstexpr_depth_EQ : Joined<"-fconstexpr-depth=">, Group; def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, Group; def ftest_coverage : Flag<"-ftest-coverage">, 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 Args, ArgVector &ArgValues, static bool HandleFunctionCall(const LValue *This, ArrayRef 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 struct X : X { }; \ // 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); // expected-note {{instantiation of template class}} -- 2.40.0