r373252 - [Diagnostics] Warn if enumeration type mismatch in conditional expression
David Bolvansky via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 30 12:55:50 PDT 2019
Author: xbolva00
Date: Mon Sep 30 12:55:50 2019
New Revision: 373252
URL: http://llvm.org/viewvc/llvm-project?rev=373252&view=rev
Log:
[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
Added:
cfe/trunk/test/Sema/warn-conditional-emum-types-mismatch.c
Modified:
cfe/trunk/lib/Sema/SemaChecking.cpp
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=373252&r1=373251&r2=373252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Sep 30 12:55:50 2019
@@ -11308,6 +11308,32 @@ static const IntegerLiteral *getIntegerL
return IL;
}
+static void CheckConditionalWithEnumTypes(Sema &S, SourceLocation Loc,
+ Expr *LHS, Expr *RHS) {
+ QualType LHSStrippedType = LHS->IgnoreParenImpCasts()->getType();
+ QualType RHSStrippedType = RHS->IgnoreParenImpCasts()->getType();
+
+ const auto *LHSEnumType = LHSStrippedType->getAs<EnumType>();
+ if (!LHSEnumType)
+ return;
+ const auto *RHSEnumType = RHSStrippedType->getAs<EnumType>();
+ if (!RHSEnumType)
+ return;
+
+ // Ignore anonymous enums.
+ if (!LHSEnumType->getDecl()->hasNameForLinkage())
+ return;
+ if (!RHSEnumType->getDecl()->hasNameForLinkage())
+ return;
+
+ if (S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType))
+ return;
+
+ S.Diag(Loc, diag::warn_conditional_mixed_enum_types)
+ << LHSStrippedType << RHSStrippedType << LHS->getSourceRange()
+ << RHS->getSourceRange();
+}
+
static void DiagnoseIntInBoolContext(Sema &S, Expr *E) {
E = E->IgnoreParenImpCasts();
SourceLocation ExprLoc = E->getExprLoc();
@@ -11799,6 +11825,8 @@ static void CheckConditionalOperator(Sem
bool Suspicious = false;
CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious);
CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);
+ CheckConditionalWithEnumTypes(S, E->getBeginLoc(), E->getTrueExpr(),
+ E->getFalseExpr());
if (T->isBooleanType())
DiagnoseIntInBoolContext(S, E);
Added: cfe/trunk/test/Sema/warn-conditional-emum-types-mismatch.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-conditional-emum-types-mismatch.c?rev=373252&view=auto
==============================================================================
--- cfe/trunk/test/Sema/warn-conditional-emum-types-mismatch.c (added)
+++ cfe/trunk/test/Sema/warn-conditional-emum-types-mismatch.c Mon Sep 30 12:55:50 2019
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wenum-compare %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wenum-compare %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s
+
+enum ro { A = 0x10 };
+enum rw { B = 0xFF };
+enum { C = 0x1A};
+
+enum {
+ STATUS_SUCCESS,
+ STATUS_FAILURE,
+ MAX_BASE_STATUS_CODE
+};
+
+enum ExtendedStatusCodes {
+ STATUS_SOMETHING_INTERESTING = MAX_BASE_STATUS_CODE + 1000,
+};
+
+
+int get_flag(int cond) {
+ return cond ? A : B;
+ #ifdef __cplusplus
+ // expected-warning at -2 {{enumeration type mismatch in conditional expression ('ro' and 'rw')}}
+ #else
+ // expected-no-diagnostics
+ #endif
+}
+
+// In the following cases we purposefully differ from GCC and dont warn because
+// this code pattern is quite sensitive and we dont want to produce so many false positives.
+
+int get_flag_anon_enum(int cond) {
+ return cond ? A : C;
+}
+
+int foo(int c) {
+ return c ? STATUS_SOMETHING_INTERESTING : STATUS_SUCCESS;
+}
More information about the cfe-commits
mailing list