Author: xbolva00 Date: Tue Sep 24 06:14:18 2019 New Revision: 372749 URL: http://llvm.org/viewvc/llvm-project?rev=372749&view=rev Log: [Diagnostics] Handle tautological left shifts in boolean context
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/Sema/warn-int-in-bool-context.c Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=372749&r1=372748&r2=372749&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Sep 24 06:14:18 2019 @@ -6155,6 +6155,10 @@ def warn_integer_constants_in_conditiona "converting the result of '?:' with integer constants to a boolean always " "evaluates to 'true'">, InGroup<TautologicalConstantCompare>; +def warn_left_shift_always : Warning< + "converting the result of '<<' to a boolean always evaluates " + "to %select{false|true}0">, + 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=372749&r1=372748&r2=372749&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Sep 24 06:14:18 2019 @@ -11314,17 +11314,26 @@ static void DiagnoseIntInBoolContext(Sem if (const auto *BO = dyn_cast<BinaryOperator>(E)) { BinaryOperator::Opcode Opc = BO->getOpcode(); + Expr::EvalResult Result; // Do not diagnose unsigned shifts. - if (Opc == BO_Shl && E->getType()->isSignedIntegerType()) - S.Diag(ExprLoc, diag::warn_left_shift_in_bool_context) << E; + if (Opc == BO_Shl) { + const auto *LHS = getIntegerLiteral(BO->getLHS()); + const auto *RHS = getIntegerLiteral(BO->getRHS()); + if (LHS && LHS->getValue() == 0) + S.Diag(ExprLoc, diag::warn_left_shift_always) << 0; + else if (RHS && RHS->getValue().isNonNegative() && + E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) + S.Diag(ExprLoc, diag::warn_left_shift_always) + << (Result.Val.getInt() != 0); + else if (E->getType()->isSignedIntegerType()) + S.Diag(ExprLoc, diag::warn_left_shift_in_bool_context) << E; + } } if (const auto *CO = dyn_cast<ConditionalOperator>(E)) { const auto *LHS = getIntegerLiteral(CO->getTrueExpr()); - if (!LHS) - return; const auto *RHS = getIntegerLiteral(CO->getFalseExpr()); - if (!RHS) + if (!LHS || !RHS) return; if ((LHS->getValue() == 0 || LHS->getValue() == 1) && (RHS->getValue() == 0 || RHS->getValue() == 1)) Modified: cfe/trunk/test/Sema/warn-int-in-bool-context.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-int-in-bool-context.c?rev=372749&r1=372748&r2=372749&view=diff ============================================================================== --- cfe/trunk/test/Sema/warn-int-in-bool-context.c (original) +++ cfe/trunk/test/Sema/warn-int-in-bool-context.c Tue Sep 24 06:14:18 2019 @@ -24,12 +24,17 @@ enum num { int test(int a, unsigned b, enum num n) { boolean r; - r = a << a; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(a << a) != 0'?}} - r = MM; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(a << a) != 0'?}} - r = (1 << 7); // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << 7) != 0'?}} - r = 2UL << 2; - r = 2 << b; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(2 << b) != 0'?}} - r = (unsigned)(2 << b); + r = a << a; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(a << a) != 0'?}} + r = MM; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(a << a) != 0'?}} + r = (1 << 7); // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}} + r = 2UL << 2; // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}} + r = 0 << a; // expected-warning {{converting the result of '<<' to a boolean always evaluates to false}} + r = 0 << 2; // expected-warning {{converting the result of '<<' to a boolean always evaluates to false}} + r = 1 << 0; // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}} + r = 1 << 2; // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}} + r = 1ULL << 2; // expected-warning {{converting the result of '<<' to a boolean always evaluates to true}} + r = 2 << b; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(2 << b) != 0'?}} + r = (unsigned)(2 << b); r = b << 7; r = (1 << a); // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}} r = TWO << a; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(2 << a) != 0'?}} @@ -39,7 +44,7 @@ int test(int a, unsigned b, enum num n) return a; for (a = 0; 1 << a; a++) // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << a) != 0'?}} - ; + ; if (a << TWO) // expected-warning {{converting the result of '<<' to a boolean; did you mean '(a << 2) != 0'?}} return a; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits