forked from OSchip/llvm-project
The constant expression evaluator should examine function arguments for non-constexpr function calls unless the EvalInfo says to stop.
llvm-svn: 303317
This commit is contained in:
parent
0cf5b2f88a
commit
9add1594d2
|
@ -4579,7 +4579,7 @@ public:
|
|||
}
|
||||
|
||||
bool handleCallExpr(const CallExpr *E, APValue &Result,
|
||||
const LValue *ResultSlot) {
|
||||
const LValue *ResultSlot) {
|
||||
const Expr *Callee = E->getCallee()->IgnoreParens();
|
||||
QualType CalleeType = Callee->getType();
|
||||
|
||||
|
@ -4588,6 +4588,23 @@ public:
|
|||
auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
|
||||
bool HasQualifier = false;
|
||||
|
||||
struct EvaluateIgnoredRAII {
|
||||
public:
|
||||
EvaluateIgnoredRAII(EvalInfo &Info, llvm::ArrayRef<const Expr*> ToEval)
|
||||
: Info(Info), ToEval(ToEval) {}
|
||||
~EvaluateIgnoredRAII() {
|
||||
if (Info.noteFailure()) {
|
||||
for (auto E : ToEval)
|
||||
EvaluateIgnoredValue(Info, E);
|
||||
}
|
||||
}
|
||||
void cancel() { ToEval = {}; }
|
||||
void drop_front() { ToEval = ToEval.drop_front(); }
|
||||
private:
|
||||
EvalInfo &Info;
|
||||
llvm::ArrayRef<const Expr*> ToEval;
|
||||
} EvalArguments(Info, Args);
|
||||
|
||||
// Extract function decl and 'this' pointer from the callee.
|
||||
if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
|
||||
const ValueDecl *Member = nullptr;
|
||||
|
@ -4637,10 +4654,12 @@ public:
|
|||
if (Args.empty())
|
||||
return Error(E);
|
||||
|
||||
if (!EvaluateObjectArgument(Info, Args[0], ThisVal))
|
||||
const Expr *FirstArg = Args[0];
|
||||
Args = Args.drop_front();
|
||||
EvalArguments.drop_front();
|
||||
if (!EvaluateObjectArgument(Info, FirstArg, ThisVal))
|
||||
return false;
|
||||
This = &ThisVal;
|
||||
Args = Args.slice(1);
|
||||
} else if (MD && MD->isLambdaStaticInvoker()) {
|
||||
// Map the static invoker for the lambda back to the call operator.
|
||||
// Conveniently, we don't have to slice out the 'this' argument (as is
|
||||
|
@ -4692,8 +4711,12 @@ public:
|
|||
const FunctionDecl *Definition = nullptr;
|
||||
Stmt *Body = FD->getBody(Definition);
|
||||
|
||||
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
|
||||
!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
|
||||
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
|
||||
return false;
|
||||
|
||||
EvalArguments.cancel();
|
||||
|
||||
if (!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
|
||||
Result, ResultSlot))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -151,6 +151,14 @@ uint64_t check_integer_overflows(int i) {
|
|||
uint64_t *b;
|
||||
uint64_t b2 = b[4608 * 1024 * 1024] + 1;
|
||||
|
||||
// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
|
||||
f0(4608 * 1024 * 1024);
|
||||
f0(4608ul * 1024 * 1024);
|
||||
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
|
||||
f1(4608 * 1024 * 1024, 4608 * 1024 * 1024);
|
||||
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
|
||||
f2(4608 * 1024 * 1024, 4608 * 1024 * 1024);
|
||||
|
||||
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
|
||||
int j1 = i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024);
|
||||
|
||||
|
|
Loading…
Reference in New Issue