summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r--lib/Sema/SemaStmt.cpp52
1 files changed, 43 insertions, 9 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index e8cd6b0..1453424 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/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,11 +397,30 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
Expr *CondExpr = SS->getCond();
QualType CondType = CondExpr->getType();
- if (!CondExpr->isTypeDependent() &&
- !CondType->isIntegerType()) { // C99 6.8.4.2p1
- Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
- << CondType << CondExpr->getSourceRange();
- return StmtError();
+ // 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()) {
+ if (!CondType->isIntegerType()) { // C99 6.8.4.2p1
+ Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
+ << CondType << CondExpr->getSourceRange();
+ return StmtError();
+ }
+
+ if (CondTypeBeforePromotion->isBooleanType()) {
+ // switch(bool_expr) {...} is often a programmer error, e.g.
+ // switch(n && mask) { ... } // Doh - should be "n & mask".
+ // One can always use an if statement instead of switch(bool_expr).
+ Diag(SwitchLoc, diag::warn_bool_switch_condition)
+ << CondExpr->getSourceRange();
+ }
}
// Get the bitwidth of the switched-on value before promotions. We must
@@ -395,8 +429,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
@@ -448,7 +482,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Lo, CondType);
+ ImpCastExprToType(Lo, CondType, CastExpr::CK_IntegralCast);
CS->setLHS(Lo);
// If this is a case range, remember it in CaseRanges, otherwise CaseVals.
@@ -504,7 +538,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Hi, CondType);
+ ImpCastExprToType(Hi, CondType, CastExpr::CK_IntegralCast);
CR->setRHS(Hi);
// If the low value is bigger than the high value, the case is empty.
OpenPOWER on IntegriCloud