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'}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits