[PATCH] D36407: [Sema] Extend -Wenum-compare to handle mixed enum comparisons in switch statements

Reka Kovacs via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 7 09:27:41 PDT 2017


rnkovacs created this revision.

`-Wenum-compare` warns if two values with different enumeration types are compared in expressions with binary operators. This patch extends this diagnostic so that comparisons of mixed enumeration types are recognized in switch statements as well.

Example:

  enum MixedA { A1, A2, A3 };
  enum MixedB { B1, B2, B3 };
  
  void MixedEnums(MixedA a) {
    switch (a) {
      case A1: break; // OK, same enum types.
      case B1: break; // Warn, different enum types.
    }
  }


https://reviews.llvm.org/D36407

Files:
  lib/Sema/SemaStmt.cpp
  test/Sema/switch.c
  test/SemaCXX/warn-enum-compare.cpp


Index: test/SemaCXX/warn-enum-compare.cpp
===================================================================
--- test/SemaCXX/warn-enum-compare.cpp
+++ test/SemaCXX/warn-enum-compare.cpp
@@ -209,4 +209,21 @@
   while (getBar() > x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}}
   while (getBar() < x); // expected-warning  {{comparison of two values with different enumeration types ('Bar' and 'Foo')}}
 
+  switch (a) {
+    case name1::F1: break;
+    case name1::F3: break;
+    case name2::B2: break; // expected-warning {{comparison of two values with different enumeration types ('name1::Foo' and 'name2::Baz')}}
+  }
+
+  switch (x) {
+    case FooB: break;
+    case FooC: break;
+    case BarD: break; // expected-warning {{comparison of two values with different enumeration types ('Foo' and 'Bar')}}
+  }
+
+  switch(getBar()) {
+    case BarE: break;
+    case BarF: break;
+    case FooA: break; // expected-warning {{comparison of two values with different enumeration types ('Bar' and 'Foo')}}
+  }
 }
Index: test/Sema/switch.c
===================================================================
--- test/Sema/switch.c
+++ test/Sema/switch.c
@@ -372,6 +372,7 @@
   case EE1_b: break;
   case EE1_c: break; // no-warning
   case EE1_d: break; // expected-warning {{case value not in enumerated type 'enum ExtendedEnum1'}}
+  // expected-warning at -1 {{comparison of two values with different enumeration types ('enum ExtendedEnum1' and 'const enum ExtendedEnum1_unrelated')}}
   }
 }
 
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -743,6 +743,24 @@
   return true;
 }
 
+static void checkEnumTypesInSwitchStmt(Sema &S, Expr *Cond, Expr *Case) {
+  QualType CondType = GetTypeBeforeIntegralPromotion(Cond);
+  QualType CaseType = Case->getType();
+
+  const EnumType *CondEnumType = CondType->getAs<EnumType>();
+  const EnumType *CaseEnumType = CaseType->getAs<EnumType>();
+  if (!CondEnumType || !CaseEnumType)
+    return;
+
+  if (S.Context.hasSameUnqualifiedType(CondType, CaseType))
+    return;
+
+  SourceLocation Loc = Case->getExprLoc();
+  S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
+      << CondType << CaseType << Cond->getSourceRange()
+      << Case->getSourceRange();
+}
+
 StmtResult
 Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
                             Stmt *BodyStmt) {
@@ -843,6 +861,8 @@
         break;
       }
 
+      checkEnumTypesInSwitchStmt(*this, CondExpr, Lo);
+
       llvm::APSInt LoVal;
 
       if (getLangOpts().CPlusPlus11) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D36407.110019.patch
Type: text/x-patch
Size: 2681 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170807/c03c76a4/attachment.bin>


More information about the cfe-commits mailing list