r181388 - C++1y: Add a step limit to constexpr evaluation, to catch runaway loops.
Richard Smith
richard-llvm at metafoo.co.uk
Tue May 7 19:12:04 PDT 2013
Author: rsmith
Date: Tue May 7 21:12:03 2013
New Revision: 181388
URL: http://llvm.org/viewvc/llvm-project?rev=181388&view=rev
Log:
C++1y: Add a step limit to constexpr evaluation, to catch runaway loops.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
cfe/trunk/include/clang/Basic/LangOptions.def
cfe/trunk/include/clang/Driver/CC1Options.td
cfe/trunk/include/clang/Driver/Options.td
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/Driver/Tools.cpp
cfe/trunk/lib/Frontend/CompilerInvocation.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=181388&r1=181387&r2=181388&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Tue May 7 21:12:03 2013
@@ -83,6 +83,8 @@ def note_constexpr_depth_limit_exceeded
"constexpr evaluation exceeded maximum depth of %0 calls">;
def note_constexpr_call_limit_exceeded : Note<
"constexpr evaluation hit maximum call limit">;
+def note_constexpr_step_limit_exceeded : Note<
+ "constexpr evaluation hit maximum step limit; possible infinite loop?">;
def note_constexpr_lifetime_ended : Note<
"%select{read of|assignment to|increment of|decrement of}0 "
"%select{temporary|variable}1 whose lifetime has ended">;
Modified: cfe/trunk/include/clang/Basic/LangOptions.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=181388&r1=181387&r2=181388&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.def (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.def Tue May 7 21:12:03 2013
@@ -160,6 +160,8 @@ BENIGN_LANGOPT(InstantiationDepth, 32, 2
"maximum template instantiation depth")
BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
"maximum constexpr call depth")
+BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576,
+ "maximum constexpr evaluation steps")
BENIGN_LANGOPT(BracketDepth, 32, 256,
"maximum bracket nesting depth")
BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=181388&r1=181387&r2=181388&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Tue May 7 21:12:03 2013
@@ -434,6 +434,8 @@ def ftemplate_depth : Separate<["-"], "f
HelpText<"Maximum depth of recursive template instantiation">;
def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">,
HelpText<"Maximum depth of recursive constexpr function calls">;
+def fconstexpr_steps : Separate<["-"], "fconstexpr-steps">,
+ HelpText<"Maximum number of steps in constexpr function evaluation">;
def fbracket_depth : Separate<["-"], "fbracket-depth">,
HelpText<"Maximum nesting level for parentheses, brackets, and braces">;
def fconst_strings : Flag<["-"], "fconst-strings">,
Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=181388&r1=181387&r2=181388&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Tue May 7 21:12:03 2013
@@ -344,6 +344,7 @@ def fcompile_resource_EQ : Joined<["-"],
def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>;
def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group<f_Group>;
def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
+def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">,
Group<f_Group>;
def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>;
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=181388&r1=181387&r2=181388&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue May 7 21:12:03 2013
@@ -380,6 +380,11 @@ namespace {
/// NextCallIndex - The next call index to assign.
unsigned NextCallIndex;
+ /// StepsLeft - The remaining number of evaluation steps we're permitted
+ /// to perform. This is essentially a limit for the number of statements
+ /// we will evaluate.
+ unsigned StepsLeft;
+
/// BottomFrame - The frame in which evaluation started. This must be
/// initialized after CurrentCall and CallStackDepth.
CallStackFrame BottomFrame;
@@ -404,9 +409,10 @@ namespace {
bool IntOverflowCheckMode;
EvalInfo(const ASTContext &C, Expr::EvalStatus &S,
- bool OverflowCheckMode=false)
+ bool OverflowCheckMode = false)
: Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0),
CallStackDepth(0), NextCallIndex(1),
+ StepsLeft(getLangOpts().ConstexprStepLimit),
BottomFrame(*this, SourceLocation(), 0, 0, 0),
EvaluatingDecl(0), EvaluatingDeclValue(0), HasActiveDiagnostic(false),
CheckingPotentialConstantExpression(false),
@@ -446,6 +452,15 @@ namespace {
return (Frame->Index == CallIndex) ? Frame : 0;
}
+ bool nextStep(const Stmt *S) {
+ if (!StepsLeft) {
+ Diag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded);
+ return false;
+ }
+ --StepsLeft;
+ return true;
+ }
+
private:
/// Add a diagnostic to the diagnostics list.
PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId) {
@@ -530,9 +545,9 @@ namespace {
bool keepEvaluatingAfterFailure() {
// Should return true in IntOverflowCheckMode, so that we check for
// overflow even if some subexpressions can't be evaluated as constants.
- return IntOverflowCheckMode ||
- (CheckingPotentialConstantExpression &&
- EvalStatus.Diag && EvalStatus.Diag->empty());
+ return StepsLeft && (IntOverflowCheckMode ||
+ (CheckingPotentialConstantExpression &&
+ EvalStatus.Diag && EvalStatus.Diag->empty()));
}
};
@@ -2794,6 +2809,9 @@ static EvalStmtResult EvaluateLoopBody(A
// Evaluate a statement.
static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
const Stmt *S) {
+ if (!Info.nextStep(S))
+ return ESR_Failed;
+
// FIXME: Mark all temporaries in the current frame as destroyed at
// the end of each full-expression.
switch (S->getStmtClass()) {
Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=181388&r1=181387&r2=181388&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Tue May 7 21:12:03 2013
@@ -2667,6 +2667,11 @@ void Clang::ConstructJob(Compilation &C,
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
+ CmdArgs.push_back("-fconstexpr-steps");
+ CmdArgs.push_back(A->getValue());
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
CmdArgs.push_back("-fbracket-depth");
CmdArgs.push_back(A->getValue());
Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=181388&r1=181387&r2=181388&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Tue May 7 21:12:03 2013
@@ -1251,6 +1251,8 @@ static void ParseLangArgs(LangOptions &O
Diags);
Opts.ConstexprCallDepth = Args.getLastArgIntValue(OPT_fconstexpr_depth, 512,
Diags);
+ Opts.ConstexprStepLimit = Args.getLastArgIntValue(OPT_fconstexpr_steps,
+ 1048576, Diags);
Opts.BracketDepth = Args.getLastArgIntValue(OPT_fbracket_depth, 256, Diags);
Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy_EQ,
More information about the cfe-commits
mailing list