From 750306071663247152ab611f63e1d97ec175786d Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 17 May 2017 23:56:54 +0000 Subject: [PATCH] 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 --- lib/AST/ExprConstant.cpp | 33 ++++++++++++++++++++++++++++----- test/Sema/integer-overflow.c | 8 ++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 75bb0cac51..bd8b3abd92 100644 --- a/lib/AST/ExprConstant.cpp +++ b/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 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 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/test/Sema/integer-overflow.c b/test/Sema/integer-overflow.c index 62ee33e3d1..c2b6ba209b 100644 --- a/test/Sema/integer-overflow.c +++ b/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); -- 2.50.1