[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.
llvm-svn: 372531
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ddf58ab..7aeace5 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11256,6 +11256,44 @@
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 @@
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;