aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h3
-rw-r--r--include/clang/AST/ExprCXX.h31
-rw-r--r--include/clang/AST/Stmt.h24
-rw-r--r--include/clang/AST/StmtNodes.def1
-rw-r--r--include/clang/Frontend/StmtXML.def7
-rw-r--r--include/clang/Parse/Action.h93
-rw-r--r--include/clang/Parse/Parser.h10
-rw-r--r--lib/AST/Expr.cpp3
-rw-r--r--lib/AST/ExprCXX.cpp8
-rw-r--r--lib/AST/StmtPrinter.cpp5
-rw-r--r--lib/AST/StmtProfile.cpp7
-rw-r--r--lib/CodeGen/CGExpr.cpp8
-rw-r--r--lib/CodeGen/CGStmt.cpp10
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp1
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp1
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp15
-rw-r--r--lib/Frontend/StmtXML.cpp2
-rw-r--r--lib/Parse/ParseExprCXX.cpp50
-rw-r--r--lib/Parse/ParseStmt.cpp66
-rw-r--r--lib/Sema/Sema.h25
-rw-r--r--lib/Sema/SemaDeclCXX.cpp36
-rw-r--r--lib/Sema/SemaExprCXX.cpp59
-rw-r--r--lib/Sema/SemaStmt.cpp109
-rw-r--r--lib/Sema/TreeTransform.h120
-rw-r--r--test/CodeGenCXX/condition.cpp14
-rw-r--r--test/SemaCXX/condition.cpp8
27 files changed, 388 insertions, 329 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 61cb9587d6..7cf9aabc6d 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -540,8 +540,7 @@ public:
}
static bool classof(const Stmt *T) {
- return T->getStmtClass() == DeclRefExprClass ||
- T->getStmtClass() == CXXConditionDeclExprClass;
+ return T->getStmtClass() == DeclRefExprClass;
}
static bool classof(const DeclRefExpr *) { return true; }
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 63b153a17e..ce29d84c5c 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -671,37 +671,6 @@ public:
virtual child_iterator child_end();
};
-/// CXXConditionDeclExpr - Condition declaration of a if/switch/while/for
-/// statement, e.g: "if (int x = f()) {...}".
-/// The main difference with DeclRefExpr is that CXXConditionDeclExpr owns the
-/// decl that it references.
-///
-class CXXConditionDeclExpr : public DeclRefExpr {
-public:
- CXXConditionDeclExpr(SourceLocation startLoc,
- SourceLocation eqLoc, VarDecl *var)
- : DeclRefExpr(CXXConditionDeclExprClass, var,
- var->getType().getNonReferenceType(), startLoc) {}
-
- SourceLocation getStartLoc() const { return getLocation(); }
-
- VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); }
- const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); }
-
- virtual SourceRange getSourceRange() const {
- return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd());
- }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXConditionDeclExprClass;
- }
- static bool classof(const CXXConditionDeclExpr *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-};
-
/// CXXNewExpr - A new expression for memory allocation and constructor calls,
/// e.g: "new CXXNewExpr(foo)".
class CXXNewExpr : public Expr {
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index b7505e1bc7..14bffd0fd7 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -855,26 +855,38 @@ public:
class ForStmt : public Stmt {
enum { INIT, COND, INC, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
+ VarDecl *CondVar;
SourceLocation ForLoc;
SourceLocation LParenLoc, RParenLoc;
public:
- ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL,
- SourceLocation LP, SourceLocation RP)
- : Stmt(ForStmtClass) {
+ ForStmt(Stmt *Init, Expr *Cond, VarDecl *CondVar, Expr *Inc, Stmt *Body,
+ SourceLocation FL, SourceLocation LP, SourceLocation RP)
+ : Stmt(ForStmtClass), CondVar(CondVar), ForLoc(FL), LParenLoc(LP),
+ RParenLoc(RP)
+ {
SubExprs[INIT] = Init;
SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
SubExprs[BODY] = Body;
- ForLoc = FL;
- LParenLoc = LP;
- RParenLoc = RP;
}
/// \brief Build an empty for statement.
explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
Stmt *getInit() { return SubExprs[INIT]; }
+
+ /// \brief Retrieve the variable declared in this "for" statement, if any.
+ ///
+ /// In the following example, "y" is the condition variable.
+ /// \code
+ /// for (int x = random(); int y = mangle(x); ++x) {
+ /// // ...
+ /// }
+ /// \endcode
+ VarDecl *getConditionVariable() const { return CondVar; }
+ void setConditionVariable(VarDecl *V) { CondVar = V; }
+
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); }
Stmt *getBody() { return SubExprs[BODY]; }
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index dd8a685a95..316521b4e4 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -121,7 +121,6 @@ EXPR(CXXThisExpr , Expr)
EXPR(CXXThrowExpr , Expr)
EXPR(CXXDefaultArgExpr , Expr)
EXPR(CXXZeroInitValueExpr , Expr)
-EXPR(CXXConditionDeclExpr , DeclRefExpr)
EXPR(CXXNewExpr , Expr)
EXPR(CXXDeleteExpr , Expr)
EXPR(CXXPseudoDestructorExpr, Expr)
diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def
index 332aad2dd2..2f0da9e7b1 100644
--- a/include/clang/Frontend/StmtXML.def
+++ b/include/clang/Frontend/StmtXML.def
@@ -495,13 +495,6 @@ NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr")
ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration)
END_NODE_XML
-NODE_XML(CXXConditionDeclExpr, "CXXConditionDeclExpr")
- ATTRIBUTE_FILE_LOCATION_XML
- TYPE_ATTRIBUTE_XML(getType())
- SUB_NODE_XML(VarDecl) // a CXXConditionDeclExpr owns the declaration
-END_NODE_XML
-
-
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 3db90c6574..4b09cabfaa 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -705,14 +705,39 @@ public:
return StmtEmpty();
}
+ /// \brief Parsed an "if" statement.
+ ///
+ /// \param IfLoc the location of the "if" keyword.
+ ///
+ /// \param CondVal if the "if" condition was parsed as an expression,
+ /// the expression itself.
+ ///
+ /// \param CondVar if the "if" condition was parsed as a condition variable,
+ /// the condition variable itself.
+ ///
+ /// \param ThenVal the "then" statement.
+ ///
+ /// \param ElseLoc the location of the "else" keyword.
+ ///
+ /// \param ElseVal the "else" statement.
virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
- FullExprArg CondVal, StmtArg ThenVal,
+ FullExprArg CondVal,
+ DeclPtrTy CondVar,
+ StmtArg ThenVal,
SourceLocation ElseLoc,
StmtArg ElseVal) {
return StmtEmpty();
}
- virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) {
+ /// \brief Parsed the start of a "switch" statement.
+ ///
+ /// \param Cond if the "switch" condition was parsed as an expression,
+ /// the expression itself.
+ ///
+ /// \param CondVar if the "switch" condition was parsed as a condition
+ /// variable, the condition variable itself.
+ virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond,
+ DeclPtrTy CondVar) {
return StmtEmpty();
}
@@ -721,8 +746,18 @@ public:
return StmtEmpty();
}
+ /// \brief Parsed a "while" statement.
+ ///
+ /// \param Cond if the "while" condition was parsed as an expression,
+ /// the expression itself.
+ ///
+ /// \param CondVar if the "while" condition was parsed as a condition
+ /// variable, the condition variable itself.
+ ///
+ /// \param Body the body of the "while" loop.
virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
- FullExprArg Cond, StmtArg Body) {
+ FullExprArg Cond, DeclPtrTy CondVar,
+ StmtArg Body) {
return StmtEmpty();
}
virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
@@ -732,13 +767,36 @@ public:
SourceLocation CondRParen) {
return StmtEmpty();
}
+
+ /// \brief Parsed a "for" statement.
+ ///
+ /// \param ForLoc the location of the "for" keyword.
+ ///
+ /// \param LParenLoc the location of the left parentheses.
+ ///
+ /// \param First the statement used to initialize the for loop.
+ ///
+ /// \param Second the condition to be checked during each iteration, if
+ /// that condition was parsed as an expression.
+ ///
+ /// \param SecondArg the condition variable to be checked during each
+ /// iterator, if that condition was parsed as a variable declaration.
+ ///
+ /// \param Third the expression that will be evaluated to "increment" any
+ /// values prior to the next iteration.
+ ///
+ /// \param RParenLoc the location of the right parentheses.
+ ///
+ /// \param Body the body of the "body" loop.
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) {
return StmtEmpty();
}
+
virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
SourceLocation LParenLoc,
StmtArg First, ExprArg Second,
@@ -1382,15 +1440,22 @@ public:
return ExprEmpty();
}
- /// 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) {
- return ExprEmpty();
+ /// \brief Parsed a condition declaration in a C++ if, switch, or while
+ /// statement.
+ ///
+ /// This callback will be invoked after parsing the declaration of "x" in
+ ///
+ /// \code
+ /// if (int x = f()) {
+ /// // ...
+ /// }
+ /// \endcode
+ ///
+ /// \param S the scope of the if, switch, or while statement.
+ ///
+ /// \param D the declarator that that describes the variable being declared.
+ virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
+ return DeclResult();
}
/// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index b1375d7d65..30c6b90d1f 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -934,8 +934,8 @@ private:
SourceLocation Start);
//===--------------------------------------------------------------------===//
- // C++ if/switch/while/for condition expression.
- OwningExprResult ParseCXXCondition();
+ // C++ if/switch/while condition expression.
+ bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult);
//===--------------------------------------------------------------------===//
// C++ types
@@ -1001,10 +1001,8 @@ private:
OwningStmtResult ParseCompoundStatement(AttributeList *Attr,
bool isStmtExpr = false);
OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
- bool ParseParenExprOrCondition(OwningExprResult &CondExp,
- bool OnlyAllowCondition = false,
- SourceLocation *LParenLoc = 0,
- SourceLocation *RParenLoc = 0);
+ bool ParseParenExprOrCondition(OwningExprResult &ExprResult,
+ DeclPtrTy &DeclResult);
OwningStmtResult ParseIfStatement(AttributeList *Attr);
OwningStmtResult ParseSwitchStatement(AttributeList *Attr);
OwningStmtResult ParseWhileStatement(AttributeList *Attr);
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();