aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/CFG.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-08-06 23:20:50 +0000
committerTed Kremenek <kremenek@apple.com>2008-08-06 23:20:50 +0000
commitc7eb9031159f30a63db960fad4640d779f1617c8 (patch)
treef90044d45f1432f977a7d50717f88c1d193e4239 /lib/AST/CFG.cpp
parent0eb8458655d525e5e65a9a621990e7a920cc9ce7 (diff)
Cleanup some processing with DeclStmt, and gradually start using the internal BumpPtrAllocator to allocator more of CFG's data structures.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54433 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/CFG.cpp')
-rw-r--r--lib/AST/CFG.cpp95
1 files changed, 73 insertions, 22 deletions
diff --git a/lib/AST/CFG.cpp b/lib/AST/CFG.cpp
index ffc42bb6e1..dc49b45d8d 100644
--- a/lib/AST/CFG.cpp
+++ b/lib/AST/CFG.cpp
@@ -42,6 +42,41 @@ struct VISIBILITY_HIDDEN SaveAndRestore {
T old_value;
};
+static SourceLocation GetEndLoc(ScopedDecl* D) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(D))
+ if (Expr* Ex = VD->getInit())
+ return Ex->getSourceRange().getEnd();
+
+ return D->getLocation();
+}
+
+class VISIBILITY_HIDDEN UnaryDeclStmt : public DeclStmt {
+ Stmt* Ex;
+public:
+ UnaryDeclStmt(ScopedDecl* D)
+ : DeclStmt(D, D->getLocation(), GetEndLoc(D)), Ex(0) {
+ if (VarDecl* VD = dyn_cast<VarDecl>(D))
+ Ex = VD->getInit();
+ }
+
+ virtual ~UnaryDeclStmt() {}
+ virtual void Destroy(ASTContext& Ctx) { assert(false && "Do not call"); }
+
+ virtual child_iterator child_begin() {
+ return Ex ? &Ex : 0;
+ }
+ virtual child_iterator child_end() {
+ return Ex ? &Ex + 1 : 0;
+ }
+ virtual decl_iterator decl_begin() {
+ return getDecl();
+ }
+ virtual decl_iterator decl_end() {
+ ScopedDecl* D = getDecl();
+ return D ? D->getNextDeclarator() : 0;
+ }
+};
+
/// CFGBuilder - This class implements CFG construction from an AST.
/// The builder is stateful: an instance of the builder should be used to only
/// construct a single CFG.
@@ -135,7 +170,7 @@ private:
CFGBlock* addStmt(Stmt* Terminator);
CFGBlock* WalkAST(Stmt* Terminator, bool AlwaysAddStmt);
CFGBlock* WalkAST_VisitChildren(Stmt* Terminator);
- CFGBlock* WalkAST_VisitDeclSubExprs(StmtIterator& I);
+ CFGBlock* WalkAST_VisitDeclSubExpr(ScopedDecl* D);
CFGBlock* WalkAST_VisitStmtExpr(StmtExpr* Terminator);
void FinishBlock(CFGBlock* B);
@@ -329,12 +364,32 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) {
case Stmt::DeclStmtClass: {
ScopedDecl* D = cast<DeclStmt>(Terminator)->getDecl();
- Block->appendStmt(Terminator);
- StmtIterator I(D);
- return WalkAST_VisitDeclSubExprs(I);
+ if (!D->getNextDeclarator()) {
+ Block->appendStmt(Terminator);
+ return WalkAST_VisitDeclSubExpr(D);
+ }
+ else {
+ typedef llvm::SmallVector<ScopedDecl*,10> BufTy;
+ BufTy Buf;
+ CFGBlock* B = 0;
+ do { Buf.push_back(D); D = D->getNextDeclarator(); } while (D);
+ for (BufTy::reverse_iterator I=Buf.rbegin(), E=Buf.rend(); I!=E; ++I) {
+ // Get the alignment of UnaryDeclStmt, padding out to >=8 bytes.
+ unsigned A = llvm::AlignOf<UnaryDeclStmt>::Alignment < 8
+ ? 8 : llvm::AlignOf<UnaryDeclStmt>::Alignment;
+
+ // Allocate the UnaryDeclStmt using the BumpPtrAllocator. It will
+ // get automatically freed with the CFG.
+ void* Mem = cfg->getAllocator().Allocate(sizeof(UnaryDeclStmt), A);
+ // Append the fake DeclStmt to block.
+ Block->appendStmt(new (Mem) UnaryDeclStmt(*I));
+ B = WalkAST_VisitDeclSubExpr(*I);
+ }
+ return B;
+ }
}
-
+
case Stmt::AddrLabelExprClass: {
AddrLabelExpr* A = cast<AddrLabelExpr>(Terminator);
AddressTakenLabels.insert(A->getLabel());
@@ -412,31 +467,27 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) {
return WalkAST_VisitChildren(Terminator);
}
-/// WalkAST_VisitDeclSubExprs - Utility method to handle Decls contained in
-/// DeclStmts. Because the initialization code (and sometimes the
-/// the type declarations) for DeclStmts can contain arbitrary expressions,
-/// we must linearize declarations to handle arbitrary control-flow induced by
-/// those expressions.
-CFGBlock* CFGBuilder::WalkAST_VisitDeclSubExprs(StmtIterator& I) {
- if (I == StmtIterator())
+/// WalkAST_VisitDeclSubExpr - Utility method to add block-level expressions
+/// for initializers in Decls.
+CFGBlock* CFGBuilder::WalkAST_VisitDeclSubExpr(ScopedDecl* D) {
+ VarDecl* VD = dyn_cast<VarDecl>(D);
+
+ if (!VD)
return Block;
- Stmt* Terminator = *I;
- ++I;
- WalkAST_VisitDeclSubExprs(I);
-
- // Optimization: Don't create separate block-level statements for literals.
+ Expr* Init = VD->getInit();
- switch (Terminator->getStmtClass()) {
+ if (!Init)
+ return Block;
+
+ // Optimization: Don't create separate block-level statements for literals.
+ switch (Init->getStmtClass()) {
case Stmt::IntegerLiteralClass:
case Stmt::CharacterLiteralClass:
case Stmt::StringLiteralClass:
break;
-
- // All other cases.
-
default:
- Block = addStmt(Terminator);
+ Block = addStmt(Init);
}
return Block;