Skip to content
Permalink
Browse files

[Diagnostics] Warn for enum constants in bool context (-Wint-in-bool-…

…context; GCC compatibility)

Extracted from D63082.

llvm-svn: 372664
  • Loading branch information
davidbolvansky committed Sep 23, 2019
1 parent bf9c8ff commit 28b38c277a2941e9e891b2db30652cfd962f070b
@@ -5720,6 +5720,9 @@ def warn_precedence_conditional : Warning<
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>;
@@ -6156,6 +6159,10 @@ def warn_comparison_of_mixed_enum_types : Warning<
"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">,
@@ -11297,10 +11297,22 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
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.
@@ -14,7 +14,13 @@ typedef bool boolean;
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'?}}
@@ -26,6 +32,26 @@ int test(int a) {
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);
}

0 comments on commit 28b38c2

Please sign in to comment.