diff options
| author | Chris Lattner <sabre@nondot.org> | 2009-10-16 16:45:22 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2009-10-16 16:45:22 +0000 |
| commit | a96d4279660b5fa49ce44b5cec1f25f895158881 (patch) | |
| tree | 184b69c3aafaf955fd099f7c50f2cfe4df7ccc8b | |
| parent | 519486256cfb15ab61527c90fb45cc44e4389199 (diff) | |
| download | bcm5719-llvm-a96d4279660b5fa49ce44b5cec1f25f895158881.tar.gz bcm5719-llvm-a96d4279660b5fa49ce44b5cec1f25f895158881.zip | |
Implement PR4407 - missing warnings on case value overflow,
patch by Zhanyong Wan!
llvm-svn: 84259
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 29 | ||||
| -rw-r--r-- | clang/test/Sema/switch.c | 7 |
2 files changed, 34 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index e8cd6b081de..efa7e22b2ef 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -368,6 +368,21 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs, 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 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, 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 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, = 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/clang/test/Sema/switch.c b/clang/test/Sema/switch.c index 5999f342aef..122947e7ce5 100644 --- a/clang/test/Sema/switch.c +++ b/clang/test/Sema/switch.c @@ -68,3 +68,10 @@ void test5(int z) { } } +void test6() { + const char ch = 'a'; + switch(ch) { + case 1234: // expected-warning {{overflow converting case value}} + break; + } +} |

