r372531 - [Diagnostics] Warn if ?: with integer constants always evaluates to true

David Bolvansky via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 22 15:00:48 PDT 2019


Author: xbolva00
Date: Sun Sep 22 15:00:48 2019
New Revision: 372531

URL: http://llvm.org/viewvc/llvm-project?rev=372531&view=rev
Log:
[Diagnostics] Warn if ?: with integer constants always evaluates to true

Extracted from D63082. GCC has this warning under -Wint-in-bool-context, but as noted in the D63082's review, we should put it under TautologicalConstantCompare.


Added:
    cfe/trunk/test/Sema/warn-integer-constants-in-ternary.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaChecking.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=372531&r1=372530&r2=372531&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Sep 22 15:00:48 2019
@@ -6137,6 +6137,10 @@ def warn_out_of_range_compare : Warning<
   InGroup<TautologicalOutOfRangeCompare>;
 def warn_tautological_bool_compare : Warning<warn_out_of_range_compare.Text>,
   InGroup<TautologicalConstantCompare>;
+def warn_integer_constants_in_conditional_always_true : Warning<
+  "converting the result of '?:' with integer constants to a boolean always "
+  "evaluates to 'true'">,
+  InGroup<TautologicalConstantCompare>;
 def warn_comparison_of_mixed_enum_types : Warning<
   "comparison of two values with different enumeration types"
   "%diff{ ($ and $)|}0,1">,

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=372531&r1=372530&r2=372531&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Sun Sep 22 15:00:48 2019
@@ -11256,6 +11256,44 @@ static bool isSameWidthConstantConversio
   return true;
 }
 
+static void DiagnoseIntInBoolContext(Sema &S, const Expr *E) {
+  E = E->IgnoreParenImpCasts();
+  SourceLocation ExprLoc = E->getExprLoc();
+
+  if (const auto *CO = dyn_cast<ConditionalOperator>(E)) {
+    const auto *LHS = dyn_cast<IntegerLiteral>(CO->getTrueExpr());
+    if (!LHS) {
+      if (auto *UO = dyn_cast<UnaryOperator>(CO->getTrueExpr())) {
+        if (UO->getOpcode() == UO_Minus)
+          LHS = dyn_cast<IntegerLiteral>(UO->getSubExpr());
+        if (!LHS)
+          return;
+      } else {
+        return;
+      }
+    }
+
+    const auto *RHS = dyn_cast<IntegerLiteral>(CO->getFalseExpr());
+    if (!RHS) {
+      if (auto *UO = dyn_cast<UnaryOperator>(CO->getFalseExpr())) {
+        if (UO->getOpcode() == UO_Minus)
+          RHS = dyn_cast<IntegerLiteral>(UO->getSubExpr());
+        if (!RHS)
+          return;
+      } else {
+        return;
+      }
+    }
+
+    if ((LHS->getValue() == 0 || LHS->getValue() == 1) &&
+        (RHS->getValue() == 0 || RHS->getValue() == 1))
+      // Do not diagnose common idioms
+      return;
+    if (LHS->getValue() != 0 && LHS->getValue() != 0)
+      S.Diag(ExprLoc, diag::warn_integer_constants_in_conditional_always_true);
+  }
+}
+
 static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
                                     SourceLocation CC,
                                     bool *ICContext = nullptr,
@@ -11708,6 +11746,9 @@ static void CheckConditionalOperator(Sem
   CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
   CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
 
+  if (T->isBooleanType())
+    DiagnoseIntInBoolContext(S, E);
+
   // If -Wconversion would have warned about either of the candidates
   // for a signedness conversion to the context type...
   if (!Suspicious) return;

Added: cfe/trunk/test/Sema/warn-integer-constants-in-ternary.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-integer-constants-in-ternary.c?rev=372531&view=auto
==============================================================================
--- cfe/trunk/test/Sema/warn-integer-constants-in-ternary.c (added)
+++ cfe/trunk/test/Sema/warn-integer-constants-in-ternary.c Sun Sep 22 15:00:48 2019
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wtautological-constant-compare %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wtautological-constant-compare %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s
+
+#define ONE 1
+#define TWO 2
+
+#define TERN(c, l, r) c ? l : r
+
+#ifdef __cplusplus
+typedef bool boolean;
+#else
+typedef _Bool boolean;
+#endif
+
+void test(boolean a) {
+  boolean r;
+  r = a ? (1) : TWO;
+  r = a ? 3 : TWO; // expected-warning {{converting the result of '?:' with integer constants to a boolean always evaluates to 'true'}}
+  r = a ? -2 : 0;  // expected-warning {{converting the result of '?:' with integer constants to a boolean always evaluates to 'true'}}
+  r = a ? 3 : -2;  // expected-warning {{converting the result of '?:' with integer constants to a boolean always evaluates to 'true'}}
+  r = a ? 0 : TWO;
+  r = a ? 3 : ONE; // expected-warning {{converting the result of '?:' with integer constants to a boolean always evaluates to 'true'}}
+  r = a ? ONE : 0;
+  r = a ? 0 : -0;
+  r = a ? 1 : 0;
+  r = a ? ONE : 0;
+  r = a ? ONE : ONE;
+  r = TERN(a, 4, 8);   // expected-warning {{converting the result of '?:' with integer constants to a boolean always evaluates to 'true'}}
+  r = TERN(a, -1, -8); // expected-warning {{converting the result of '?:' with integer constants to a boolean always evaluates to 'true'}}
+}




More information about the cfe-commits mailing list