]> granicus.if.org Git - clang/commitdiff
Don't emit warn_logical_and_in_logical_or for cases like "a && b || 0".
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 17 Nov 2010 19:18:19 +0000 (19:18 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 17 Nov 2010 19:18:19 +0000 (19:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119540 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/Sema/parentheses.c

index 7a73ad633f4ab5bd538778291fd4f49831142473..4728b0d1990da9109ae7d3958c79f43d17c5966a 100644 (file)
@@ -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<BinaryOperator>(E)) {
+                                             Expr *OrLHS, Expr *OrRHS) {
+  if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(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<BinaryOperator>(E)) {
+                                             Expr *OrLHS, Expr *OrRHS) {
+  if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(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);
   }
 }
 
index 52aadde32e367a96589d40ce7f24e5258571550c..6d6fa1d4bd42fd5e9839b2757eb7bba76cf69e0c 100644 (file)
@@ -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.
 }