From: Chris Lattner Date: Sat, 24 Jul 2010 01:10:11 +0000 (+0000) Subject: turn down the logical bitwise confusion warning to not warn X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b7690b425845b636849f25074d64d30aad646473;p=clang turn down the logical bitwise confusion warning to not warn when the RHS of the ||/&& is ever 0 or 1. This handles a variety of creative idioms for "true" used in C programs and fixes many false positives at the expense of a few false negatives. This fixes rdar://8230351. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109314 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8b2e0203b3..5281f3ff79 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5819,18 +5819,21 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] // bitwise one. We do this when the LHS is a non-bool integer and the RHS // is a constant. if (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() && - rex->getType()->isIntegerType() && rex->isEvaluatable(Context) && - // Don't warn if the RHS is a (constant folded) boolean expression like - // "sizeof(int) == 4". - !rex->isKnownToHaveBooleanValue() && + rex->getType()->isIntegerType() && // Don't warn in macros. - !Loc.isMacroID()) - Diag(Loc, diag::warn_logical_instead_of_bitwise) - << rex->getSourceRange() - << (Opc == BinaryOperator::LAnd ? "&&" : "||") - << (Opc == BinaryOperator::LAnd ? "&" : "|"); - - + !Loc.isMacroID()) { + // If the RHS can be constant folded, and if it constant folds to something + // that isn't 0 or 1 (which indicate a potential logical operation that + // happened to fold to true/false) then warn. + Expr::EvalResult Result; + if (rex->Evaluate(Result, Context) && !Result.HasSideEffects && + Result.Val.getInt() != 0 && Result.Val.getInt() != 1) { + Diag(Loc, diag::warn_logical_instead_of_bitwise) + << rex->getSourceRange() + << (Opc == BinaryOperator::LAnd ? "&&" : "||") + << (Opc == BinaryOperator::LAnd ? "&" : "|"); + } + } if (!Context.getLangOptions().CPlusPlus) { UsualUnaryConversions(lex); diff --git a/test/CodeGenCXX/static-init-2.cpp b/test/CodeGenCXX/static-init-2.cpp index 7eb4a7d5aa..65ab3bb126 100644 --- a/test/CodeGenCXX/static-init-2.cpp +++ b/test/CodeGenCXX/static-init-2.cpp @@ -3,4 +3,4 @@ // Make sure we don't crash generating y; its value is constant, but the // initializer has side effects, so EmitConstantExpr should fail. int x(); -int y = x() && 0; // expected-warning {{use of logical && with constant operand}} +int y = x() && 0; diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c index 9d3da90854..56a52bed1b 100644 --- a/test/Sema/exprs.c +++ b/test/Sema/exprs.c @@ -145,5 +145,8 @@ void test19() { int test20(int x) { return x && 4; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}} - return x && sizeof(int) == 4; // no warning. + return x && sizeof(int) == 4; // no warning, RHS is logical op. + + // no warning, this is an idiom for "true" in old C style. + return x && (signed char)1; } diff --git a/test/Sema/switch.c b/test/Sema/switch.c index 4e39e0f0c2..bb4822916c 100644 --- a/test/Sema/switch.c +++ b/test/Sema/switch.c @@ -50,14 +50,12 @@ void test4() } switch (cond) { - case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} \ - expected-warning {{use of logical && with constant operand}} + case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} break; } switch (cond) { - case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} \\ - expected-warning {{use of logical || with constant operand}} + case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} break; } } diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp index 54240dcc30..fc13630bbf 100644 --- a/test/SemaCXX/switch.cpp +++ b/test/SemaCXX/switch.cpp @@ -8,8 +8,7 @@ void test() { } int n = 3; - switch (n && 1) { // expected-warning {{bool}} \ - // expected-warning {{use of logical && with constant operand}} + switch (n && 1) { // expected-warning {{bool}} case 1: break; }