From ba4d0871f7d11979e4fb76e02eef354885cb9971 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Wed, 21 Mar 2012 23:30:30 +0000 Subject: [PATCH] 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. llvm-svn: 153226 --- clang/lib/AST/ExprConstant.cpp | 30 ++++++++++++++---------------- clang/test/Sema/return.c | 9 +++++++++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 331c757c1246..583bbfc9883e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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/clang/test/Sema/return.c b/clang/test/Sema/return.c index 7a4c1f8e514c..77bd3f688ed9 100644 --- a/clang/test/Sema/return.c +++ b/clang/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; + } +}