diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-06-21 23:44:13 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-06-21 23:44:13 +0000 |
| commit | 27b98eae80d1790f22804e5c6c33c2666a97b53e (patch) | |
| tree | e1bd6d401e7f1de5eabd209148e2143c9e3a7e11 /clang/lib/AST | |
| parent | c9fec975e6cf021d861bd399612da7656a7907f8 (diff) | |
| download | bcm5719-llvm-27b98eae80d1790f22804e5c6c33c2666a97b53e.tar.gz bcm5719-llvm-27b98eae80d1790f22804e5c6c33c2666a97b53e.zip | |
Alter the internal representation of the condition variable in
if/while/switch/for statements to ensure that walking the children of
these statements actually works. Previously, we stored the condition
variable as a VarDecl. However, StmtIterator isn't able to walk from a
VarDecl to a set of statements, and would (in some circumstances) walk
beyond the end of the list of statements, cause Bad Behavior.
In this change, we've gone back to representing the condition
variables as DeclStmts. While not as memory-efficient as VarDecls, it
greatly simplifies iteration over the children.
Fixes the remainder of <rdar://problem/8104754>.
llvm-svn: 106504
Diffstat (limited to 'clang/lib/AST')
| -rw-r--r-- | clang/lib/AST/Stmt.cpp | 132 |
1 files changed, 124 insertions, 8 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 80f5695e42a..6dbe8f4d18c 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -499,14 +499,101 @@ void DeclStmt::DoDestroy(ASTContext &C) { DG.getDeclGroup().Destroy(C); } +IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, + Stmt *then, SourceLocation EL, Stmt *elsev) + : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) +{ + setConditionVariable(C, var); + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[THEN] = then; + SubExprs[ELSE] = elsev; +} + +VarDecl *IfStmt::getConditionVariable() const { + if (!SubExprs[VAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[VAR] = 0; + return; + } + + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void IfStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } +ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, + Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, + SourceLocation RP) + : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP) +{ + SubExprs[INIT] = Init; + setConditionVariable(C, condVar); + SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); + SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); + SubExprs[BODY] = Body; +} + +VarDecl *ForStmt::getConditionVariable() const { + if (!SubExprs[CONDVAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[CONDVAR] = 0; + return; + } + + SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void ForStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } +SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond) + : Stmt(SwitchStmtClass), FirstCase(0) +{ + setConditionVariable(C, Var); + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = NULL; +} + +VarDecl *SwitchStmt::getConditionVariable() const { + if (!SubExprs[VAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[VAR] = 0; + return; + } + + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void SwitchStmt::DoDestroy(ASTContext &C) { // Destroy the SwitchCase statements in this switch. In the normal // case, this loop will merely decrement the reference counts from @@ -521,6 +608,35 @@ void SwitchStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } +WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, + SourceLocation WL) +: Stmt(WhileStmtClass) +{ + setConditionVariable(C, Var); + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = body; + WhileLoc = WL; +} + +VarDecl *WhileStmt::getConditionVariable() const { + if (!SubExprs[VAR]) + return 0; + + DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); + return cast<VarDecl>(DS->getSingleDecl()); +} + +void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) { + if (!V) { + SubExprs[VAR] = 0; + return; + } + + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), + V->getSourceRange().getBegin(), + V->getSourceRange().getEnd()); +} + void WhileStmt::DoDestroy(ASTContext &C) { BranchDestroy(C, this, SubExprs, END_EXPR); } @@ -572,26 +688,26 @@ Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; } // IfStmt Stmt::child_iterator IfStmt::child_begin() { - return child_iterator(Var, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator IfStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // SwitchStmt Stmt::child_iterator SwitchStmt::child_begin() { - return child_iterator(Var, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator SwitchStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // WhileStmt Stmt::child_iterator WhileStmt::child_begin() { - return child_iterator(Var, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator WhileStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // DoStmt @@ -600,10 +716,10 @@ Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; } // ForStmt Stmt::child_iterator ForStmt::child_begin() { - return child_iterator(CondVar, &SubExprs[0]); + return &SubExprs[0]; } Stmt::child_iterator ForStmt::child_end() { - return child_iterator(0, &SubExprs[0]+END_EXPR); + return &SubExprs[0]+END_EXPR; } // ObjCForCollectionStmt |

