Implement PR4407 - missing warnings on case value overflow,
patch by Zhanyong Wan!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84259 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index e8cd6b0..efa7e22 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -368,6 +368,21 @@
   return false;
 }
 
+/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
+/// potentially integral-promoted expression @p expr.
+static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) {
+  const ImplicitCastExpr *ImplicitCast =
+      dyn_cast_or_null<ImplicitCastExpr>(expr);
+  if (ImplicitCast != NULL) {
+    const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr();
+    QualType TypeBeforePromotion = ExprBeforePromotion->getType();
+    if (TypeBeforePromotion->isIntegralType()) {
+      return TypeBeforePromotion;
+    }
+  }
+  return expr->getType();
+}
+
 Action::OwningStmtResult
 Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
                             StmtArg Body) {
@@ -382,6 +397,16 @@
   Expr *CondExpr = SS->getCond();
   QualType CondType = CondExpr->getType();
 
+  // C++ 6.4.2.p2:
+  // Integral promotions are performed (on the switch condition).
+  //
+  // A case value unrepresentable by the original switch condition
+  // type (before the promotion) doesn't make sense, even when it can
+  // be represented by the promoted type.  Therefore we need to find
+  // the pre-promotion type of the switch condition.
+  QualType CondTypeBeforePromotion =
+      GetTypeBeforeIntegralPromotion(CondExpr);
+
   if (!CondExpr->isTypeDependent() &&
       !CondType->isIntegerType()) { // C99 6.8.4.2p1
     Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
@@ -395,8 +420,8 @@
     = CondExpr->isTypeDependent() || CondExpr->isValueDependent();
   unsigned CondWidth
     = HasDependentValue? 0
-                       : static_cast<unsigned>(Context.getTypeSize(CondType));
-  bool CondIsSigned = CondType->isSignedIntegerType();
+      : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion));
+  bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType();
 
   // Accumulate all of the case values in a vector so that we can sort them
   // and detect duplicates.  This vector contains the APInt for the case after
diff --git a/test/Sema/switch.c b/test/Sema/switch.c
index 5999f34..122947e 100644
--- a/test/Sema/switch.c
+++ b/test/Sema/switch.c
@@ -68,3 +68,10 @@
   }
 } 
 
+void test6() {
+  const char ch = 'a';
+  switch(ch) {
+    case 1234:  // expected-warning {{overflow converting case value}}
+      break;
+  }
+}