diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-25 00:27:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-25 00:27:52 +0000 |
commit | 99e9b4d172f6877e6ba5ebe75bb8238721f5e01c (patch) | |
tree | 16c143b06b39022258614b713ed5999a7d7679c0 /lib | |
parent | d1a7846699a82f85ff3ce6b2e383409537c3f5c5 (diff) |
Eliminate CXXConditionDeclExpr with extreme prejudice.
All statements that involve conditions can now hold on to a separate
condition declaration (a VarDecl), and will use a DeclRefExpr
referring to that VarDecl for the condition expression. ForStmts now
have such a VarDecl (I'd missed those in previous commits).
Also, since this change reworks the Action interface for
if/while/switch/for, use FullExprArg for the full expressions in those
expressions, to ensure that we're emitting
Note that we are (still) not generating the right cleanups for
condition variables in for statements. That will be a follow-on
commit.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89817 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Expr.cpp | 3 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 8 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 1 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderStmt.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterStmt.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/PrintParserCallbacks.cpp | 15 | ||||
-rw-r--r-- | lib/Frontend/StmtXML.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 50 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 66 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 25 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 36 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 59 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 109 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 120 |
18 files changed, 264 insertions, 262 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 9f08271694..e4de703029 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1130,8 +1130,6 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; case CXXDefaultArgExprClass: return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx); - case CXXConditionDeclExprClass: - return LV_Valid; case CStyleCastExprClass: case CXXFunctionalCastExprClass: case CXXStaticCastExprClass: @@ -1516,7 +1514,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXNullPtrLiteralExprClass: case Expr::CXXThisExprClass: case Expr::CXXThrowExprClass: - case Expr::CXXConditionDeclExprClass: // FIXME: is this correct? case Expr::CXXNewExprClass: case Expr::CXXDeleteExprClass: case Expr::CXXPseudoDestructorExprClass: diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 8591a4d8bd..0e724a8d5c 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -72,14 +72,6 @@ Stmt::child_iterator CXXZeroInitValueExpr::child_end() { return child_iterator(); } -// CXXConditionDeclExpr -Stmt::child_iterator CXXConditionDeclExpr::child_begin() { - return getVarDecl(); -} -Stmt::child_iterator CXXConditionDeclExpr::child_end() { - return child_iterator(); -} - // CXXNewExpr CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs, unsigned numPlaceArgs, diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index a7cfed9788..7a02a451d8 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1055,11 +1055,6 @@ void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) { OS << Node->getType().getAsString() << "()"; } -void -StmtPrinter::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E) { - PrintRawDecl(E->getVarDecl()); -} - void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isGlobalNew()) OS << "::"; diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 2699cdfc4f..201724e861 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -108,14 +108,17 @@ void StmtProfiler::VisitLabelStmt(LabelStmt *S) { void StmtProfiler::VisitIfStmt(IfStmt *S) { VisitStmt(S); + VisitDecl(S->getConditionVariable()); } void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) { VisitStmt(S); + VisitDecl(S->getConditionVariable()); } void StmtProfiler::VisitWhileStmt(WhileStmt *S) { VisitStmt(S); + VisitDecl(S->getConditionVariable()); } void StmtProfiler::VisitDoStmt(DoStmt *S) { @@ -481,10 +484,6 @@ void StmtProfiler::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *S) { VisitExpr(S); } -void StmtProfiler::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *S) { - VisitDeclRefExpr(S); -} - void StmtProfiler::VisitCXXDeleteExpr(CXXDeleteExpr *S) { VisitExpr(S); ID.AddBoolean(S->isGlobalDelete()); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2c7ea9b60e..853715cce2 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -258,8 +258,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::BlockDeclRefExprClass: return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E)); - case Expr::CXXConditionDeclExprClass: - return EmitCXXConditionDeclLValue(cast<CXXConditionDeclExpr>(E)); case Expr::CXXTemporaryObjectExprClass: case Expr::CXXConstructExprClass: return EmitCXXConstructLValue(cast<CXXConstructExpr>(E)); @@ -1476,12 +1474,6 @@ LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) { return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } -LValue -CodeGenFunction::EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E) { - EmitLocalBlockVarDecl(*E->getVarDecl()); - return EmitDeclRefLValue(E); -} - LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "tmp"); EmitCXXConstructExpr(Temp, E); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 6fddcf6b04..be571fac71 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -479,6 +479,7 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) { void CodeGenFunction::EmitForStmt(const ForStmt &S) { // FIXME: What do we do if the increment (f.e.) contains a stmt expression, // which contains a continue/break? + CleanupScope ForScope(*this); // Evaluate the first part before the loop. if (S.getInit()) @@ -490,9 +491,18 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) { EmitBlock(CondBlock); + // Create a cleanup scope + CleanupScope ConditionScope(*this); + // Evaluate the condition if present. If not, treat it as a // non-zero-constant according to 6.8.5.3p2, aka, true. if (S.getCond()) { + // If the for statement has a condition scope, emit the local variable + // declaration. + // FIXME: The cleanup points for this are all wrong. + if (S.getConditionVariable()) + EmitLocalBlockVarDecl(*S.getConditionVariable()); + // As long as the condition is true, iterate the loop. llvm::BasicBlock *ForBody = createBasicBlock("for.body"); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index a42fa51265..4fde0dd864 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -916,7 +916,6 @@ public: LValue EmitBlockDeclRefLValue(const BlockDeclRefExpr *E); - LValue EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E); LValue EmitCXXConstructLValue(const CXXConstructExpr *E); LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E); LValue EmitCXXExprWithTemporariesLValue(const CXXExprWithTemporaries *E); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index ea2c979c52..00734a0854 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -231,6 +231,7 @@ unsigned PCHStmtReader::VisitForStmt(ForStmt *S) { VisitStmt(S); S->setInit(StmtStack[StmtStack.size() - 4]); S->setCond(cast_or_null<Expr>(StmtStack[StmtStack.size() - 3])); + S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); S->setInc(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2])); S->setBody(StmtStack.back()); S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 5138776a90..27b83ed6cb 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -214,6 +214,7 @@ void PCHStmtWriter::VisitForStmt(ForStmt *S) { VisitStmt(S); Writer.WriteSubStmt(S->getInit()); Writer.WriteSubStmt(S->getCond()); + Writer.AddDeclRef(S->getConditionVariable(), Record); Writer.WriteSubStmt(S->getInc()); Writer.WriteSubStmt(S->getBody()); Writer.AddSourceLocation(S->getForLoc(), Record); diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index deb5498b90..c5dc979f65 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -305,14 +305,16 @@ namespace { } virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, StmtArg ThenVal, + FullExprArg CondVal, DeclPtrTy CondVar, + StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } - virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) { + virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, + DeclPtrTy CondVar) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } @@ -325,7 +327,8 @@ namespace { } virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, StmtArg Body) { + FullExprArg Cond, DeclPtrTy CondVar, + StmtArg Body) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } @@ -338,8 +341,10 @@ namespace { } virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - ExprArg Third, SourceLocation RParenLoc, + StmtArg First, FullExprArg Second, + DeclPtrTy SecondVar, + FullExprArg Third, + SourceLocation RParenLoc, StmtArg Body) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index 4a3c0bf1c6..b98417fc31 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -61,8 +61,6 @@ namespace { Doc.PrintDecl(*DI); } } else { - if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S)) - Doc.PrintDecl(CCDE->getVarDecl()); for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i) DumpSubTree(*i); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 56484720db..157d8837a9 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -549,7 +549,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { CommaLocs.data(), RParenLoc); } -/// ParseCXXCondition - if/switch/while/for condition expression. +/// ParseCXXCondition - if/switch/while condition expression. /// /// condition: /// expression @@ -557,11 +557,20 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] /// '=' assignment-expression /// -Parser::OwningExprResult Parser::ParseCXXCondition() { - if (!isCXXConditionDeclaration()) - return ParseExpression(); // expression - - SourceLocation StartLoc = Tok.getLocation(); +/// \param ExprResult if the condition was parsed as an expression, the +/// parsed expression. +/// +/// \param DeclResult if the condition was parsed as a declaration, the +/// parsed declaration. +/// +/// \returns true if there was a parsing, false otherwise. +bool Parser::ParseCXXCondition(OwningExprResult &ExprResult, + DeclPtrTy &DeclResult) { + if (!isCXXConditionDeclaration()) { + ExprResult = ParseExpression(); // expression + DeclResult = DeclPtrTy(); + return ExprResult.isInvalid(); + } // type-specifier-seq DeclSpec DS; @@ -577,7 +586,7 @@ Parser::OwningExprResult Parser::ParseCXXCondition() { OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); if (AsmLabel.isInvalid()) { SkipUntil(tok::semi); - return ExprError(); + return true; } DeclaratorInfo.setAsmLabel(AsmLabel.release()); DeclaratorInfo.SetRangeEnd(Loc); @@ -590,17 +599,24 @@ Parser::OwningExprResult Parser::ParseCXXCondition() { DeclaratorInfo.AddAttributes(AttrList, Loc); } + // Type-check the declaration itself. + Action::DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(CurScope, + DeclaratorInfo); + DeclResult = Dcl.get(); + ExprResult = ExprError(); + // '=' assignment-expression - if (Tok.isNot(tok::equal)) - return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator)); - SourceLocation EqualLoc = ConsumeToken(); - OwningExprResult AssignExpr(ParseAssignmentExpression()); - if (AssignExpr.isInvalid()) - return ExprError(); - - return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, - DeclaratorInfo,EqualLoc, - move(AssignExpr)); + if (Tok.is(tok::equal)) { + SourceLocation EqualLoc = ConsumeToken(); + OwningExprResult AssignExpr(ParseAssignmentExpression()); + if (!AssignExpr.isInvalid()) + Actions.AddInitializerToDecl(DeclResult, move(AssignExpr)); + } else { + // FIXME: C++0x allows a braced-init-list + Diag(Tok, diag::err_expected_equal_after_declarator); + } + + return false; } /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 294f872988..2022fa51cf 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -517,22 +517,22 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { /// should try to recover harder. It returns false if the condition is /// successfully parsed. Note that a successful parse can still have semantic /// errors in the condition. -bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp, - bool OnlyAllowCondition, - SourceLocation *LParenLocPtr, - SourceLocation *RParenLocPtr) { +bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult, + DeclPtrTy &DeclResult) { + bool ParseError = false; + SourceLocation LParenLoc = ConsumeParen(); - if (LParenLocPtr) *LParenLocPtr = LParenLoc; - - if (getLang().CPlusPlus) - CondExp = ParseCXXCondition(); - else - CondExp = ParseExpression(); + if (getLang().CPlusPlus) + ParseError = ParseCXXCondition(ExprResult, DeclResult); + else { + ExprResult = ParseExpression(); + DeclResult = DeclPtrTy(); + } // If the parser was confused by the condition and we don't have a ')', try to // recover by skipping ahead to a semi and bailing out. If condexp is // semantically invalid but we have well formed code, keep going. - if (CondExp.isInvalid() && Tok.isNot(tok::r_paren)) { + if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) { SkipUntil(tok::semi); // Skipping may have stopped if it found the containing ')'. If so, we can // continue parsing the if statement. @@ -541,8 +541,7 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp, } // Otherwise the condition is valid or the rparen is present. - SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - if (RParenLocPtr) *RParenLocPtr = RPLoc; + MatchRHSPunctuation(tok::r_paren, LParenLoc); return false; } @@ -583,7 +582,8 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) { // Parse the condition. OwningExprResult CondExp(Actions); - if (ParseParenExprOrCondition(CondExp)) + DeclPtrTy CondVar; + if (ParseParenExprOrCondition(CondExp, CondVar)) return StmtError(); FullExprArg FullCondExp(Actions.FullExpr(CondExp)); @@ -650,7 +650,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) { // If the condition was invalid, discard the if statement. We could recover // better by replacing it with a valid expr, but don't do that yet. - if (CondExp.isInvalid()) + if (CondExp.isInvalid() && !CondVar.get()) return StmtError(); // If the then or else stmt is invalid and the other is valid (and present), @@ -669,7 +669,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) { if (ElseStmt.isInvalid()) ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc); - return Actions.ActOnIfStmt(IfLoc, FullCondExp, move(ThenStmt), + return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt), ElseLoc, move(ElseStmt)); } @@ -709,12 +709,15 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) { // Parse the condition. OwningExprResult Cond(Actions); - if (ParseParenExprOrCondition(Cond)) + DeclPtrTy CondVar; + if (ParseParenExprOrCondition(Cond, CondVar)) return StmtError(); + FullExprArg FullCond(Actions.FullExpr(Cond)); + OwningStmtResult Switch(Actions); - if (!Cond.isInvalid()) - Switch = Actions.ActOnStartOfSwitchStmt(move(Cond)); + if (!Cond.isInvalid() || CondVar.get()) + Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar); // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -743,7 +746,7 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) { SwitchScope.Exit(); - if (Cond.isInvalid()) + if (Cond.isInvalid() && !CondVar.get()) return StmtError(); return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body)); @@ -789,7 +792,8 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) { // Parse the condition. OwningExprResult Cond(Actions); - if (ParseParenExprOrCondition(Cond)) + DeclPtrTy CondVar; + if (ParseParenExprOrCondition(Cond, CondVar)) return StmtError(); FullExprArg FullCond(Actions.FullExpr(Cond)); @@ -815,10 +819,10 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) { InnerScope.Exit(); WhileScope.Exit(); - if (Cond.isInvalid() || Body.isInvalid()) + if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid()) return StmtError(); - return Actions.ActOnWhileStmt(WhileLoc, FullCond, move(Body)); + return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body)); } /// ParseDoStatement @@ -943,7 +947,8 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { bool ForEach = false; OwningStmtResult FirstPart(Actions); OwningExprResult SecondPart(Actions), ThirdPart(Actions); - + DeclPtrTy SecondVar; + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(CurScope); ConsumeToken(); @@ -1001,13 +1006,17 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { if (Tok.is(tok::semi)) { // for (...;; // no second part. } else { - SecondPart =getLang().CPlusPlus ? ParseCXXCondition() : ParseExpression(); + if (getLang().CPlusPlus) + ParseCXXCondition(SecondPart, SecondVar); + else + SecondPart = ParseExpression(); } if (Tok.is(tok::semi)) { ConsumeToken(); } else { - if (!SecondPart.isInvalid()) Diag(Tok, diag::err_expected_semi_for); + if (!SecondPart.isInvalid() || SecondVar.get()) + Diag(Tok, diag::err_expected_semi_for); SkipUntil(tok::semi); } @@ -1046,8 +1055,9 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { if (!ForEach) return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), - move(SecondPart), move(ThirdPart), - RParenLoc, move(Body)); + Actions.FullExpr(SecondPart), SecondVar, + Actions.FullExpr(ThirdPart), RParenLoc, + move(Body)); return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, move(FirstPart), diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index feff59a026..19a255ce6a 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1266,13 +1266,16 @@ public: SourceLocation ColonLoc, StmtArg SubStmt); virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, StmtArg ThenVal, + FullExprArg CondVal, DeclPtrTy CondVar, + StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal); - virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond); + virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, + DeclPtrTy CondVar); virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body); virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, StmtArg Body); + FullExprArg Cond, + DeclPtrTy CondVar, StmtArg Body); virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, SourceLocation WhileLoc, SourceLocation CondLParen, ExprArg Cond, @@ -1280,8 +1283,10 @@ public: virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - ExprArg Third, SourceLocation RParenLoc, + StmtArg First, FullExprArg Second, + DeclPtrTy SecondVar, + FullExprArg Third, + SourceLocation RParenLoc, StmtArg Body); virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, SourceLocation LParenLoc, @@ -1880,14 +1885,8 @@ public: bool UseGlobal, bool ArrayForm, ExprArg Operand); - /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a - /// C++ if/switch/while/for statement. - /// e.g: "if (int x = f()) {...}" - virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S, - SourceLocation StartLoc, - Declarator &D, - SourceLocation EqualLoc, - ExprArg AssignExprVal); + virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, + Declarator &D); OwningExprResult CheckConditionVariable(VarDecl *ConditionVar); /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b5419c1c90..1df1173121 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4918,3 +4918,39 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { assert(S->getEntity() == D->getDeclContext() && "Context imbalance!"); ExitDeclaratorContext(S); } + +/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a +/// C++ if/switch/while/for statement. +/// e.g: "if (int x = f()) {...}" +Action::DeclResult +Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { + // C++ 6.4p2: + // The declarator shall not specify a function or an array. + // The type-specifier-seq shall not contain typedef and shall not declare a + // new class or enumeration. + assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class of condition decl."); + + DeclaratorInfo *DInfo = 0; + TagDecl *OwnedTag = 0; + QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag); + + if (Ty->isFunctionType()) { // The declarator shall not specify a function... + // We exit without creating a CXXConditionDeclExpr because a FunctionDecl + // would be created and CXXConditionDeclExpr wants a VarDecl. + Diag(D.getIdentifierLoc(), diag::err_invalid_use_of_function_type) + << D.getSourceRange(); + return DeclResult(); + } else if (OwnedTag && OwnedTag->isDefinition()) { + // The type-specifier-seq shall not declare a new class or enumeration. + Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition); + } + + DeclPtrTy Dcl = ActOnDeclarator(S, D); + if (!Dcl) + return DeclResult(); + + VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>()); + VD->setDeclaredInCondition(true); + return Dcl; +} diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 40e5707028..3b18b3a1ba 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -943,56 +943,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, OperatorDelete, Ex, StartLoc)); } - -/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a -/// C++ if/switch/while/for statement. -/// e.g: "if (int x = f()) {...}" -Action::OwningExprResult -Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc, - Declarator &D, - SourceLocation EqualLoc, - ExprArg AssignExprVal) { - assert(AssignExprVal.get() && "Null assignment expression"); - - // C++ 6.4p2: - // The declarator shall not specify a function or an array. - // The type-specifier-seq shall not contain typedef and shall not declare a - // new class or enumeration. - - assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && - "Parser allowed 'typedef' as storage class of condition decl."); - - // FIXME: Store DeclaratorInfo in the expression. - DeclaratorInfo *DInfo = 0; - TagDecl *OwnedTag = 0; - QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag); - - if (Ty->isFunctionType()) { // The declarator shall not specify a function... - // We exit without creating a CXXConditionDeclExpr because a FunctionDecl - // would be created and CXXConditionDeclExpr wants a VarDecl. - return ExprError(Diag(StartLoc, diag::err_invalid_use_of_function_type) - << SourceRange(StartLoc, EqualLoc)); - } else if (Ty->isArrayType()) { // ...or an array. - Diag(StartLoc, diag::err_invalid_use_of_array_type) - << SourceRange(StartLoc, EqualLoc); - } else if (OwnedTag && OwnedTag->isDefinition()) { - // The type-specifier-seq shall not declare a new class or enumeration. - Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition); - } - - DeclPtrTy Dcl = ActOnDeclarator(S, D); - if (!Dcl) - return ExprError(); - AddInitializerToDecl(Dcl, move(AssignExprVal), /*DirectInit=*/false); - - // Mark this variable as one that is declared within a conditional. - // We know that the decl had to be a VarDecl because that is the only type of - // decl that can be assigned and the grammar requires an '='. - VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>()); - VD->setDeclaredInCondition(true); - return Owned(new (Context) CXXConditionDeclExpr(StartLoc, EqualLoc, VD)); -} - /// \brief Check the use of the given variable as a C++ condition in an if, /// while, do-while, or switch statement. Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar) { @@ -1009,18 +959,9 @@ Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar) { diag::err_invalid_use_of_array_type) << ConditionVar->getSourceRange()); - // FIXME: Switch to building a DeclRefExpr, once we've eliminated the - // need for CXXConditionDeclExpr. -#if 0 return Owned(DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar, ConditionVar->getLocation(), ConditionVar->getType().getNonReferenceType())); -#else - return Owned(new (Context) CXXConditionDeclExpr( - ConditionVar->getSourceRange().getBegin(), - ConditionVar->getSourceRange().getEnd(), - ConditionVar)); -#endif } /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 61d48cb63e..be9a09bc1d 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -236,25 +236,24 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, } Action::OwningStmtResult -Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, +Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar, StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal) { OwningExprResult CondResult(CondVal.release()); - Expr *condExpr = CondResult.takeAs<Expr>(); - assert(condExpr && "ActOnIfStmt(): missing expression"); - VarDecl *ConditionVar = 0; - if (CXXConditionDeclExpr *Cond = dyn_cast<CXXConditionDeclExpr>(condExpr)) { - ConditionVar = Cond->getVarDecl(); - condExpr = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar, - ConditionVar->getLocation(), - ConditionVar->getType().getNonReferenceType()); - // FIXME: Leaks the old condExpr + if (CondVar.get()) { + ConditionVar = CondVar.getAs<VarDecl>(); + CondResult = CheckConditionVariable(ConditionVar); + if (CondResult.isInvalid()) + return StmtError(); } + Expr *ConditionExpr = CondResult.takeAs<Expr>(); + if (!ConditionExpr) + return StmtError(); - if (CheckBooleanCondition(condExpr, IfLoc)) { - CondResult = condExpr; + if (CheckBooleanCondition(ConditionExpr, IfLoc)) { + CondResult = ConditionExpr; return StmtError(); } @@ -274,23 +273,27 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DiagnoseUnusedExprResult(elseStmt); CondResult.release(); - return Owned(new (Context) IfStmt(IfLoc, ConditionVar, condExpr, thenStmt, - ElseLoc, elseStmt)); + return Owned(new (Context) IfStmt(IfLoc, ConditionVar, ConditionExpr, + thenStmt, ElseLoc, elseStmt)); } Action::OwningStmtResult -Sema::ActOnStartOfSwitchStmt(ExprArg cond) { - Expr *condExpr = cond.takeAs<Expr>(); +Sema::ActOnStartOfSwitchStmt(FullExprArg cond, DeclPtrTy CondVar) { + OwningExprResult CondResult(cond.release()); + VarDecl *ConditionVar = 0; |