From a18e70b25c85d7e653e642b5e6e58d6063af3d83 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 9 Jan 2013 23:04:56 +0000 Subject: [PATCH] Issue warning when case value is too large to fit 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 | 3 ++- lib/AST/ExprConstant.cpp | 4 +++- lib/Sema/SemaStmt.cpp | 10 +++++++++- test/Sema/switch-1.c | 17 +++++++++++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 test/Sema/switch-1.c diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index cbb800e70a..44c6cb0570 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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 *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. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 338cd74b32..622f37b178 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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 *Diag) const { EvalResult EvalResult; + EvalResult.Diag = Diag; bool Result = EvaluateAsRValue(EvalResult, Ctx); (void)Result; assert(Result && "Could not evaluate expression"); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 08f78d06ca..592c6a6b74 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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 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 index 0000000000..b45cbdbf2f --- /dev/null +++ b/test/Sema/switch-1.c @@ -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; +} -- 2.40.0