From a8e0cd8cdecc7e0ba1792e46773b884c6eed4829 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 6 Aug 2011 07:30:58 +0000 Subject: [PATCH] Do l-value conversion, etc., on a switch condition expression in ActOnStartOfSwitchStmt (i.e. before binding up a full-expression) instead of ActOnFinishSwitchStmt. Among other things, this means that property l-values are properly converted inside the full-expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137014 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaCodeComplete.cpp | 9 +++++---- lib/Sema/SemaStmt.cpp | 35 ++++++++++++++++------------------- test/SemaObjC/arc.m | 13 +++++++++++++ 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 5803a76600..cff9d6b4a9 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3448,10 +3448,11 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { void Sema::CodeCompleteCase(Scope *S) { if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) return; - + SwitchStmt *Switch = getCurFunction()->SwitchStack.back(); - if (!Switch->getCond()->getType()->isEnumeralType()) { - CodeCompleteExpressionData Data(Switch->getCond()->getType()); + QualType type = Switch->getCond()->IgnoreImplicit()->getType(); + if (!type->isEnumeralType()) { + CodeCompleteExpressionData Data(type); Data.IntegralConstantExpression = true; CodeCompleteExpression(S, Data); return; @@ -3459,7 +3460,7 @@ void Sema::CodeCompleteCase(Scope *S) { // Code-complete the cases of a switch statement over an enumeration type // by providing the list of - EnumDecl *Enum = Switch->getCond()->getType()->getAs()->getDecl(); + EnumDecl *Enum = type->castAs()->getDecl(); // Determine which enumerators we have already seen in the switch statement. // FIXME: Ideally, we would also be able to look *past* the code-completion diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 6b2935fdf7..6e814e53bd 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -407,13 +407,12 @@ static bool EqEnumVals(const std::pair& lhs, /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of /// potentially integral-promoted expression @p expr. -static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { - if (const CastExpr *ImplicitCast = dyn_cast(expr)) { - const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr(); - QualType TypeBeforePromotion = ExprBeforePromotion->getType(); - if (TypeBeforePromotion->isIntegralOrEnumerationType()) { - return TypeBeforePromotion; - } +static QualType GetTypeBeforeIntegralPromotion(Expr *&expr) { + if (ExprWithCleanups *cleanups = dyn_cast(expr)) + expr = cleanups->getSubExpr(); + while (ImplicitCastExpr *impcast = dyn_cast(expr)) { + if (impcast->getCastKind() != CK_IntegralCast) break; + expr = impcast->getSubExpr(); } return expr->getType(); } @@ -449,6 +448,11 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); + // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. + CondResult = UsualUnaryConversions(Cond); + if (CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); + if (!CondVar) { CheckImplicitConversions(Cond, SwitchLoc); CondResult = MaybeCreateExprWithCleanups(Cond); @@ -482,21 +486,14 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, SS->setBody(BodyStmt, SwitchLoc); getCurFunction()->SwitchStack.pop_back(); - if (SS->getCond() == 0) - return StmtError(); - Expr *CondExpr = SS->getCond(); - Expr *CondExprBeforePromotion = CondExpr; - QualType CondTypeBeforePromotion = - GetTypeBeforeIntegralPromotion(CondExpr); + if (!CondExpr) return StmtError(); - // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. - ExprResult CondResult = UsualUnaryConversions(CondExpr); - if (CondResult.isInvalid()) - return StmtError(); - CondExpr = CondResult.take(); QualType CondType = CondExpr->getType(); - SS->setCond(CondExpr); + + Expr *CondExprBeforePromotion = CondExpr; + QualType CondTypeBeforePromotion = + GetTypeBeforeIntegralPromotion(CondExprBeforePromotion); // C++ 6.4.2.p2: // Integral promotions are performed (on the switch condition). diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m index 88d08181f6..83835ebd03 100644 --- a/test/SemaObjC/arc.m +++ b/test/SemaObjC/arc.m @@ -649,3 +649,16 @@ void test37(Test37 *c) { (void) y; } } + +// rdar://problem/9887979 +@interface Test38 +@property int value; +@end +void test38() { + extern Test38 *test38_helper(void); + switch (test38_helper().value) { + case 0: + case 1: + ; + } +} -- 2.40.0