From: Richard Trieu Date: Wed, 21 Mar 2012 23:30:30 +0000 (+0000) Subject: Change the binary operator data recursive evaluator to not stop at the first X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b778305e95f9977e6710f2b04830ecc36398ab5e;p=clang Change the binary operator data recursive evaluator to not stop at the first non-constant value encountered. This allows the evaluator to deduce that expressions like (x < 5 || true) is equal to true. Previously, it would visit x and determined that the entire expression is could not evaluated to a constant. This fixes PR12318. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153226 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 331c757c12..583bbfc988 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -4510,12 +4510,10 @@ public: bool Traverse(const BinaryOperator *E) { enqueue(E); EvalResult PrevResult; - while (!Queue.empty()) { - if (!process(PrevResult)) { - Queue.clear(); - return false; - } - } + while (!Queue.empty()) + process(PrevResult); + + if (PrevResult.Failed) return false; FinalResult.swap(PrevResult.Val); return true; @@ -4552,7 +4550,7 @@ private: Result.Val = APValue(); } - bool process(EvalResult &Result); + void process(EvalResult &Result); void enqueue(const Expr *E) { E = E->IgnoreParens(); @@ -4785,7 +4783,7 @@ bool DataRecursiveIntBinOpEvaluator:: } } -bool DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { +void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { Job &job = Queue.back(); switch (job.Kind) { @@ -4794,13 +4792,13 @@ bool DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { if (shouldEnqueue(Bop)) { job.Kind = Job::BinOpKind; enqueue(Bop->getLHS()); - return true; + return; } } EvaluateExpr(job.E, Result); Queue.pop_back(); - return true; + return; } case Job::BinOpKind: { @@ -4808,26 +4806,26 @@ bool DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { job.LHSResult.swap(Result); bool IgnoreRHS = false; bool SuppressRHSDiags = false; - bool ret = VisitBinOpLHSOnly(job.LHSResult, Bop, IgnoreRHS, Result.Val, - SuppressRHSDiags); + Result.Failed = !VisitBinOpLHSOnly(job.LHSResult, Bop, IgnoreRHS, + Result.Val, SuppressRHSDiags); if (IgnoreRHS) { Queue.pop_back(); - return ret; + return; } if (SuppressRHSDiags) job.startSpeculativeEval(Info); job.Kind = Job::BinOpVisitedLHSKind; enqueue(Bop->getRHS()); - return ret; + return; } case Job::BinOpVisitedLHSKind: { const BinaryOperator *Bop = cast(job.E); EvalResult RHS; RHS.swap(Result); - bool ret = VisitBinOp(job.LHSResult, RHS, Bop, Result.Val); + Result.Failed = !VisitBinOp(job.LHSResult, RHS, Bop, Result.Val); Queue.pop_back(); - return ret; + return; } } diff --git a/test/Sema/return.c b/test/Sema/return.c index 7a4c1f8e51..77bd3f688e 100644 --- a/test/Sema/return.c +++ b/test/Sema/return.c @@ -255,3 +255,12 @@ int test_enum_cases(enum Cases C) { case C3: return 4; } } // no-warning + +// PR12318 - Don't give a may reach end of non-void function warning. +int test34(int x) { + if (x == 1) { + return 3; + } else if ( x == 2 || 1) { + return 5; + } +}