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(); + const EnumType *CaseEnumType = CaseType->getAs(); + 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) { 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@-1 {{comparison of two values with different enumeration types ('enum ExtendedEnum1' and 'const enum ExtendedEnum1_unrelated')}} } } 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')}} + } }