Extracted from D63082.
llvm-svn: 372664
def note_precedence_conditional_first : Note<
"place parentheses around the '?:' expression to evaluate it first">;
+def warn_enum_constant_in_bool_context : Warning<
+ "converting the enum constant to a boolean">,
+ InGroup<IntInBoolContext>;
def warn_left_shift_in_bool_context : Warning<
"converting the result of '<<' to a boolean; did you mean '(%0) != 0'?">,
InGroup<IntInBoolContext>;
"comparison of two values with different enumeration types"
"%diff{ ($ and $)|}0,1">,
InGroup<EnumCompare>;
+def warn_conditional_mixed_enum_types : Warning<
+ "enumeration type mismatch in conditional expression"
+ "%diff{ ($ and $)|}0,1">,
+ InGroup<EnumCompare>;
def warn_comparison_of_mixed_enum_types_switch : Warning<
"comparison of two values with different enumeration types in switch statement"
"%diff{ ($ and $)|}0,1">,
if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
return CheckVectorLogicalOperands(LHS, RHS, Loc);
+ bool EnumConstantInBoolContext = false;
+ for (const ExprResult &HS : {LHS, RHS}) {
+ if (const auto *DREHS = dyn_cast<DeclRefExpr>(HS.get())) {
+ const auto *ECDHS = dyn_cast<EnumConstantDecl>(DREHS->getDecl());
+ if (ECDHS && ECDHS->getInitVal() != 0 && ECDHS->getInitVal() != 1)
+ EnumConstantInBoolContext = true;
+ }
+ }
+
+ if (EnumConstantInBoolContext)
+ Diag(Loc, diag::warn_enum_constant_in_bool_context);
+
// Diagnose cases where the user write a logical and/or but probably meant a
// bitwise one. We do this when the LHS is a non-bool integer and the RHS
// is a constant.
- if (LHS.get()->getType()->isIntegerType() &&
+ if (!EnumConstantInBoolContext && LHS.get()->getType()->isIntegerType() &&
!LHS.get()->getType()->isBooleanType() &&
RHS.get()->getType()->isIntegerType() && !RHS.get()->isValueDependent() &&
// Don't warn in macros or template instantiations.
typedef _Bool boolean;
#endif
-int test(int a) {
+enum num {
+ zero,
+ one,
+ two,
+};
+
+int test(int a, enum num n) {
boolean r;
r = (1 << 3); // expected-warning {{converting the result of '<<' to a boolean; did you mean '(1 << 3) != 0'?}}
r = TWO << 7; // expected-warning {{converting the result of '<<' to a boolean; did you mean '(2 << 7) != 0'?}}
if (a << TWO) // expected-warning {{converting the result of '<<' to a boolean; did you mean '(a << 2) != 0'?}}
return a;
+ if (n || two)
+ // expected-warning@-1 {{converting the enum constant to a boolean}}
+ return a;
+
+ if (n == one || two)
+ // expected-warning@-1 {{converting the enum constant to a boolean}}
+ return a;
+
+ if (r && two)
+ // expected-warning@-1 {{converting the enum constant to a boolean}}
+ return a;
+
+ if (two && r)
+ // expected-warning@-1 {{converting the enum constant to a boolean}}
+ return a;
+
+ if (n == one && two)
+ // expected-warning@-1 {{converting the enum constant to a boolean}}
+ return a;
+
// Don't warn in macros.
return SHIFT(1, a);
}