Skip to content

Commit 471910d

Browse files
committedSep 30, 2019
[Diagnostics] Warn if enumeration type mismatch in conditional expression
Summary: - Useful warning - GCC compatibility (GCC warns in C++ mode) Reviewers: rsmith, aaron.ballman Reviewed By: aaron.ballman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67919 llvm-svn: 373252
1 parent a05e671 commit 471910d

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed
 

‎clang/lib/Sema/SemaChecking.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -11308,6 +11308,32 @@ static const IntegerLiteral *getIntegerLiteral(Expr *E) {
1130811308
return IL;
1130911309
}
1131011310

11311+
static void CheckConditionalWithEnumTypes(Sema &S, SourceLocation Loc,
11312+
Expr *LHS, Expr *RHS) {
11313+
QualType LHSStrippedType = LHS->IgnoreParenImpCasts()->getType();
11314+
QualType RHSStrippedType = RHS->IgnoreParenImpCasts()->getType();
11315+
11316+
const auto *LHSEnumType = LHSStrippedType->getAs<EnumType>();
11317+
if (!LHSEnumType)
11318+
return;
11319+
const auto *RHSEnumType = RHSStrippedType->getAs<EnumType>();
11320+
if (!RHSEnumType)
11321+
return;
11322+
11323+
// Ignore anonymous enums.
11324+
if (!LHSEnumType->getDecl()->hasNameForLinkage())
11325+
return;
11326+
if (!RHSEnumType->getDecl()->hasNameForLinkage())
11327+
return;
11328+
11329+
if (S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType))
11330+
return;
11331+
11332+
S.Diag(Loc, diag::warn_conditional_mixed_enum_types)
11333+
<< LHSStrippedType << RHSStrippedType << LHS->getSourceRange()
11334+
<< RHS->getSourceRange();
11335+
}
11336+
1131111337
static void DiagnoseIntInBoolContext(Sema &S, Expr *E) {
1131211338
E = E->IgnoreParenImpCasts();
1131311339
SourceLocation ExprLoc = E->getExprLoc();
@@ -11799,6 +11825,8 @@ static void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
1179911825
bool Suspicious = false;
1180011826
CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
1180111827
CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
11828+
CheckConditionalWithEnumTypes(S, E->getBeginLoc(), E->getTrueExpr(),
11829+
E->getFalseExpr());
1180211830

1180311831
if (T->isBooleanType())
1180411832
DiagnoseIntInBoolContext(S, E);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wenum-compare %s
2+
// RUN: %clang_cc1 -x c -fsyntax-only -verify %s
3+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wenum-compare %s
4+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s
5+
6+
enum ro { A = 0x10 };
7+
enum rw { B = 0xFF };
8+
enum { C = 0x1A};
9+
10+
enum {
11+
STATUS_SUCCESS,
12+
STATUS_FAILURE,
13+
MAX_BASE_STATUS_CODE
14+
};
15+
16+
enum ExtendedStatusCodes {
17+
STATUS_SOMETHING_INTERESTING = MAX_BASE_STATUS_CODE + 1000,
18+
};
19+
20+
21+
int get_flag(int cond) {
22+
return cond ? A : B;
23+
#ifdef __cplusplus
24+
// expected-warning@-2 {{enumeration type mismatch in conditional expression ('ro' and 'rw')}}
25+
#else
26+
// expected-no-diagnostics
27+
#endif
28+
}
29+
30+
// In the following cases we purposefully differ from GCC and dont warn because
31+
// this code pattern is quite sensitive and we dont want to produce so many false positives.
32+
33+
int get_flag_anon_enum(int cond) {
34+
return cond ? A : C;
35+
}
36+
37+
int foo(int c) {
38+
return c ? STATUS_SOMETHING_INTERESTING : STATUS_SUCCESS;
39+
}

0 commit comments

Comments
 (0)
Please sign in to comment.