summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2017-05-17 23:56:54 +0000
committerNick Lewycky <nicholas@mxc.ca>2017-05-17 23:56:54 +0000
commit9add1594d2cd5250bf6ea57bcfdb3dce676ba736 (patch)
treee58268d783d63d72c73008b5f680b5c991cc6946
parent0cf5b2f88a299e17ca80e562f2fe9f35c7375ba3 (diff)
downloadbcm5719-llvm-9add1594d2cd5250bf6ea57bcfdb3dce676ba736.tar.gz
bcm5719-llvm-9add1594d2cd5250bf6ea57bcfdb3dce676ba736.zip
The constant expression evaluator should examine function arguments for non-constexpr function calls unless the EvalInfo says to stop.
llvm-svn: 303317
-rw-r--r--clang/lib/AST/ExprConstant.cpp33
-rw-r--r--clang/test/Sema/integer-overflow.c8
2 files changed, 36 insertions, 5 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 75bb0cac51b..bd8b3abd927 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -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;
diff --git a/clang/test/Sema/integer-overflow.c b/clang/test/Sema/integer-overflow.c
index 62ee33e3d18..c2b6ba209b7 100644
--- a/clang/test/Sema/integer-overflow.c
+++ b/clang/test/Sema/integer-overflow.c
@@ -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);
OpenPOWER on IntegriCloud