Skip to content

Commit 7503060

Browse files
committed
The constant expression evaluator should examine function arguments for non-constexpr function calls unless the EvalInfo says to stop.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@303317 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d4df3e3 commit 7503060

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

lib/AST/ExprConstant.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4579,7 +4579,7 @@ class ExprEvaluatorBase
45794579
}
45804580

45814581
bool handleCallExpr(const CallExpr *E, APValue &Result,
4582-
const LValue *ResultSlot) {
4582+
const LValue *ResultSlot) {
45834583
const Expr *Callee = E->getCallee()->IgnoreParens();
45844584
QualType CalleeType = Callee->getType();
45854585

@@ -4588,6 +4588,23 @@ class ExprEvaluatorBase
45884588
auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
45894589
bool HasQualifier = false;
45904590

4591+
struct EvaluateIgnoredRAII {
4592+
public:
4593+
EvaluateIgnoredRAII(EvalInfo &Info, llvm::ArrayRef<const Expr*> ToEval)
4594+
: Info(Info), ToEval(ToEval) {}
4595+
~EvaluateIgnoredRAII() {
4596+
if (Info.noteFailure()) {
4597+
for (auto E : ToEval)
4598+
EvaluateIgnoredValue(Info, E);
4599+
}
4600+
}
4601+
void cancel() { ToEval = {}; }
4602+
void drop_front() { ToEval = ToEval.drop_front(); }
4603+
private:
4604+
EvalInfo &Info;
4605+
llvm::ArrayRef<const Expr*> ToEval;
4606+
} EvalArguments(Info, Args);
4607+
45914608
// Extract function decl and 'this' pointer from the callee.
45924609
if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
45934610
const ValueDecl *Member = nullptr;
@@ -4637,10 +4654,12 @@ class ExprEvaluatorBase
46374654
if (Args.empty())
46384655
return Error(E);
46394656

4640-
if (!EvaluateObjectArgument(Info, Args[0], ThisVal))
4657+
const Expr *FirstArg = Args[0];
4658+
Args = Args.drop_front();
4659+
EvalArguments.drop_front();
4660+
if (!EvaluateObjectArgument(Info, FirstArg, ThisVal))
46414661
return false;
46424662
This = &ThisVal;
4643-
Args = Args.slice(1);
46444663
} else if (MD && MD->isLambdaStaticInvoker()) {
46454664
// Map the static invoker for the lambda back to the call operator.
46464665
// Conveniently, we don't have to slice out the 'this' argument (as is
@@ -4692,8 +4711,12 @@ class ExprEvaluatorBase
46924711
const FunctionDecl *Definition = nullptr;
46934712
Stmt *Body = FD->getBody(Definition);
46944713

4695-
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
4696-
!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
4714+
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
4715+
return false;
4716+
4717+
EvalArguments.cancel();
4718+
4719+
if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
46974720
Result, ResultSlot))
46984721
return false;
46994722

test/Sema/integer-overflow.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@ uint64_t check_integer_overflows(int i) {
151151
uint64_t *b;
152152
uint64_t b2 = b[4608 * 1024 * 1024] + 1;
153153

154+
// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
155+
f0(4608 * 1024 * 1024);
156+
f0(4608ul * 1024 * 1024);
157+
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
158+
f1(4608 * 1024 * 1024, 4608 * 1024 * 1024);
159+
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
160+
f2(4608 * 1024 * 1024, 4608 * 1024 * 1024);
161+
154162
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
155163
int j1 = i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024);
156164

0 commit comments

Comments
 (0)