]> granicus.if.org Git - clang/commitdiff
Issue warning when case value is too large to fit
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 9 Jan 2013 23:04:56 +0000 (23:04 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 9 Jan 2013 23:04:56 +0000 (23:04 +0000)
in case condition type. // rdar://11577384.
Test is conditionalized on x86_64-apple triple as
I am not sure if the INT_MAX/LONG_MAX values in the test
will pass this test for other hosts.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172016 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/ExprConstant.cpp
lib/Sema/SemaStmt.cpp
test/Sema/switch-1.c [new file with mode: 0644]

index cbb800e70a80ebc467953f92923e0c80d021f58e..44c6cb05707acbca296821be5168891253643844 100644 (file)
@@ -568,7 +568,8 @@ public:
   /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
   /// integer. This must be called on an expression that constant folds to an
   /// integer.
-  llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const;
+  llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
+                  llvm::SmallVectorImpl<PartialDiagnosticAt> *Diag=0) const;
 
   /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an
   /// lvalue with link time known address, with no side-effects.
index 338cd74b32a17280d90fdc990eb8b5993f32c094..622f37b178c31017849f79b8fbfd589e1fbd2a39 100644 (file)
@@ -6364,8 +6364,10 @@ bool Expr::isEvaluatable(const ASTContext &Ctx) const {
   return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects;
 }
 
-APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const {
+APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
+               llvm::SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
   EvalResult EvalResult;
+  EvalResult.Diag = Diag;
   bool Result = EvaluateAsRValue(EvalResult, Ctx);
   (void)Result;
   assert(Result && "Could not evaluate expression");
index 08f78d06ca19b450fe47163f645508be22cbd23e..592c6a6b744b3784bc09074bbec81e7803850d7c 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "clang/Sema/SemaInternal.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
@@ -725,7 +726,14 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
       } else {
         // We already verified that the expression has a i-c-e value (C99
         // 6.8.4.2p3) - get that value now.
-        LoVal = Lo->EvaluateKnownConstInt(Context);
+        llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
+        LoVal = Lo->EvaluateKnownConstInt(Context, &Diags);
+        if (Diags.size() == 1 && 
+            Diags[0].second.getDiagID() == diag::note_constexpr_overflow) {
+          Diag(Lo->getLocStart(), diag::warn_case_value_overflow) <<
+            LoVal.toString(10) << "switch condition value";
+          Diag(Diags[0].first, Diags[0].second);
+        }
 
         // If the LHS is not the same type as the condition, insert an implicit
         // cast.
diff --git a/test/Sema/switch-1.c b/test/Sema/switch-1.c
new file mode 100644 (file)
index 0000000..b45cbdb
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-apple-darwin10 %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -triple x86_64-apple-darwin10 %s
+// rdar://11577384
+
+int f(int i) {
+  switch (i) {
+    case 2147483647 + 2: // expected-note {{value 2147483649 is outside the range of representable values of type 'int'}}  \
+                      // expected-warning {{overflow converting case value to switch condition type}} 
+      return 1;
+    case 9223372036854775807L * 4 : // expected-note {{value 36893488147419103228 is outside the range of representable values of type 'long'}}   \
+                        // expected-warning {{overflow converting case value to switch condition type}} 
+      return 2;
+    case 2147483647:
+      return 0;
+  }
+  return 0;
+}