From: Argyrios Kyrtzidis Date: Wed, 17 Nov 2010 19:18:19 +0000 (+0000) Subject: Don't emit warn_logical_and_in_logical_or for cases like "a && b || 0". X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47d512c337d06376d56beeb7eccc7c581ed5ff57;p=clang Don't emit warn_logical_and_in_logical_or for cases like "a && b || 0". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119540 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7a73ad633f..4728b0d199 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -7352,11 +7352,21 @@ static bool EvaluatesAsTrue(Sema &S, Expr *E) { return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res; } +/// \brief Returns true if the given expression can be evaluated as a constant +/// 'false'. +static bool EvaluatesAsFalse(Sema &S, Expr *E) { + bool Res; + return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res; +} + /// \brief Look for '&&' in the left hand of a '||' expr. static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc, - Expr *E) { - if (BinaryOperator *Bop = dyn_cast(E)) { + Expr *OrLHS, Expr *OrRHS) { + if (BinaryOperator *Bop = dyn_cast(OrLHS)) { if (Bop->getOpcode() == BO_LAnd) { + // If it's "a && b || 0" don't warn since the precedence doesn't matter. + if (EvaluatesAsFalse(S, OrRHS)) + return; // If it's "1 && a || b" don't warn since the precedence doesn't matter. if (!EvaluatesAsTrue(S, Bop->getLHS())) return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop); @@ -7373,9 +7383,12 @@ static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc, /// \brief Look for '&&' in the right hand of a '||' expr. static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc, - Expr *E) { - if (BinaryOperator *Bop = dyn_cast(E)) { + Expr *OrLHS, Expr *OrRHS) { + if (BinaryOperator *Bop = dyn_cast(OrRHS)) { if (Bop->getOpcode() == BO_LAnd) { + // If it's "0 || a && b" don't warn since the precedence doesn't matter. + if (EvaluatesAsFalse(S, OrLHS)) + return; // If it's "a || b && 1" don't warn since the precedence doesn't matter. if (!EvaluatesAsTrue(S, Bop->getRHS())) return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop); @@ -7394,8 +7407,8 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, // Warn about arg1 || arg2 && arg3, as GCC 4.3+ does. // We don't warn for 'assert(a || b && "bad")' since this is safe. if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) { - DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, lhs); - DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, rhs); + DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, lhs, rhs); + DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, lhs, rhs); } } diff --git a/test/Sema/parentheses.c b/test/Sema/parentheses.c index 52aadde32e..6d6fa1d4bd 100644 --- a/test/Sema/parentheses.c +++ b/test/Sema/parentheses.c @@ -34,4 +34,6 @@ void bitwise_rel(unsigned i) { // expected-note {{place parentheses around the '&&' expression to silence this warning}} (void)(i || "w00t" && i || i); // expected-warning {{'&&' within '||'}} \ // expected-note {{place parentheses around the '&&' expression to silence this warning}} + (void)(i && i || 0); // no warning. + (void)(0 || i && i); // no warning. }