diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index bf3cc05cdb6e..a1a463f1d037 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1690,15 +1690,19 @@ CFGBuilder::VisitLogicalOperator(BinaryOperator *B, // we have been provided. ExitBlock = RHSBlock = createBlock(false); + // Even though KnownVal is only used in the else branch of the next + // conditional, tryEvaluateBool performs additional checking on the + // Expr, so it should be called unconditionally. + TryResult KnownVal = tryEvaluateBool(RHS); + if (!KnownVal.isKnown()) + KnownVal = tryEvaluateBool(B); + if (!Term) { assert(TrueBlock == FalseBlock); addSuccessor(RHSBlock, TrueBlock); } else { RHSBlock->setTerminator(Term); - TryResult KnownVal = tryEvaluateBool(RHS); - if (!KnownVal.isKnown()) - KnownVal = tryEvaluateBool(B); addSuccessor(RHSBlock, TrueBlock, !KnownVal.isFalse()); addSuccessor(RHSBlock, FalseBlock, !KnownVal.isTrue()); } diff --git a/clang/test/Sema/warn-overlap.c b/clang/test/Sema/warn-overlap.c index 1e8a614d0ffc..6299c511fe23 100644 --- a/clang/test/Sema/warn-overlap.c +++ b/clang/test/Sema/warn-overlap.c @@ -96,3 +96,48 @@ void array_out_of_bounds() { int buffer[4]; x = (-7 > 0) ? (buffer[-7]) : 0; } + +void bool_contexts(int x) { + if (x > 4 || x < 10) {} + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + for (;x > 4 || x < 10;) {} + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + while (x > 4 || x < 10) {} + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + do {} while (x > 4 || x < 10); + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + x = (x > 4 || x < 10) ? 1 : 2; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + if ((void)5, x > 4 || x < 10) {} + // expected-warning@-1{{overlapping comparisons always evaluate to true}} +} + +void assignment(int x) { + int a = x > 4 || x < 10; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + int b = x < 2 && x > 5; + // expected-warning@-1{{overlapping comparisons always evaluate to false}} + + int c = x != 1 || x != 3; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + int d = x == 1 && x == 2; + // expected-warning@-1{{overlapping comparisons always evaluate to false}} + + int e = x < 1 || x != 0; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} +} + +int returns(int x) { + return x > 4 || x < 10; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + return x < 2 && x > 5; + // expected-warning@-1{{overlapping comparisons always evaluate to false}} + + return x != 1 || x != 3; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} + return x == 1 && x == 2; + // expected-warning@-1{{overlapping comparisons always evaluate to false}} + + return x < 1 || x != 0; + // expected-warning@-1{{overlapping comparisons always evaluate to true}} +}