From: Mike Stump Date: Fri, 17 Jul 2009 01:31:16 +0000 (+0000) Subject: Fixup indentation of rest of switch statement to match llvm coding X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6d9828c82c9321f042ab416fd2ffaa3034347d45;p=clang Fixup indentation of rest of switch statement to match llvm coding conventions. Also reflowed comments and removed spaces at end of lines and fixed up 80 col violations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76140 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index c77f8cebda..884bc177fd 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -38,15 +38,15 @@ struct VISIBILITY_HIDDEN SaveAndRestore { T& X; T old_value; }; - + static SourceLocation GetEndLoc(Decl* D) { if (VarDecl* VD = dyn_cast(D)) if (Expr* Ex = VD->getInit()) return Ex->getSourceRange().getEnd(); - - return D->getLocation(); + + return D->getLocation(); } - + /// 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. @@ -56,13 +56,12 @@ static SourceLocation GetEndLoc(Decl* D) { /// CFGBuilder builder; /// CFG* cfg = builder.BuildAST(stmt1); /// -/// CFG construction is done via a recursive walk of an AST. -/// We actually parse the AST in reverse order so that the successor -/// of a basic block is constructed prior to its predecessor. This -/// allows us to nicely capture implicit fall-throughs without extra -/// basic blocks. +/// CFG construction is done via a recursive walk of an AST. We actually parse +/// the AST in reverse order so that the successor of a basic block is +/// constructed prior to its predecessor. This allows us to nicely capture +/// implicit fall-throughs without extra basic blocks. /// -class VISIBILITY_HIDDEN CFGBuilder : public StmtVisitor { +class VISIBILITY_HIDDEN CFGBuilder : public StmtVisitor { CFG* cfg; CFGBlock* Block; CFGBlock* Succ; @@ -70,36 +69,36 @@ class VISIBILITY_HIDDEN CFGBuilder : public StmtVisitor { CFGBlock* BreakTargetBlock; CFGBlock* SwitchTerminatedBlock; CFGBlock* DefaultCaseBlock; - + // LabelMap records the mapping from Label expressions to their blocks. typedef llvm::DenseMap LabelMapTy; LabelMapTy LabelMap; - - // A list of blocks that end with a "goto" that must be backpatched to - // their resolved targets upon completion of CFG construction. + + // A list of blocks that end with a "goto" that must be backpatched to their + // resolved targets upon completion of CFG construction. typedef std::vector BackpatchBlocksTy; BackpatchBlocksTy BackpatchBlocks; - + // A list of labels whose address has been taken (for indirect gotos). typedef llvm::SmallPtrSet LabelSetTy; LabelSetTy AddressTakenLabels; - -public: + +public: explicit CFGBuilder() : cfg(NULL), Block(NULL), Succ(NULL), ContinueTargetBlock(NULL), BreakTargetBlock(NULL), SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) { // Create an empty CFG. - cfg = new CFG(); + cfg = new CFG(); } - + ~CFGBuilder() { delete cfg; } - + // buildCFG - Used by external clients to construct the CFG. CFG* buildCFG(Stmt* Statement); - - // Visitors to walk an AST and construct the CFG. Called by - // buildCFG. Do not call directly! - + + // Visitors to walk an AST and construct the CFG. Called by buildCFG. Do not + // call directly! + CFGBlock* VisitBreakStmt(BreakStmt* B); CFGBlock* VisitCaseStmt(CaseStmt* Terminator); CFGBlock* VisitCompoundStmt(CompoundStmt* C); @@ -125,24 +124,24 @@ public: badCFG = true; return Block; } - + CFGBlock* VisitObjCAtTryStmt(ObjCAtTryStmt* S); - CFGBlock* VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) { - // FIXME: For now we pretend that @catch and the code it contains - // does not exit. + CFGBlock* VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) { + // FIXME: For now we pretend that @catch and the code it contains does not + // exit. return Block; } - // FIXME: This is not completely supported. We basically @throw like - // a 'return'. + // FIXME: This is not completely supported. We basically @throw like a + // 'return'. CFGBlock* VisitObjCAtThrowStmt(ObjCAtThrowStmt* S); CFGBlock* VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S); - + // Blocks. CFGBlock* VisitBlockExpr(BlockExpr* E) { return NYS(); } - CFGBlock* VisitBlockDeclRefExpr(BlockDeclRefExpr* E) { return NYS(); } - + CFGBlock* VisitBlockDeclRefExpr(BlockDeclRefExpr* E) { return NYS(); } + private: CFGBlock* createBlock(bool add_successor = true); CFGBlock* addStmt(Stmt* Terminator); @@ -151,10 +150,10 @@ private: CFGBlock* WalkAST_VisitDeclSubExpr(Decl* D); CFGBlock* WalkAST_VisitStmtExpr(StmtExpr* Terminator); bool FinishBlock(CFGBlock* B); - + bool badCFG; }; - + // FIXME: Add support for dependent-sized array types in C++? // Does it even make sense to build a CFG for an uninstantiated template? static VariableArrayType* FindVA(Type* t) { @@ -162,45 +161,45 @@ static VariableArrayType* FindVA(Type* t) { if (VariableArrayType* vat = dyn_cast(vt)) if (vat->getSizeExpr()) return vat; - + t = vt->getElementType().getTypePtr(); } - + return 0; } - -/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can -/// represent an arbitrary statement. Examples include a single expression -/// or a function body (compound statement). The ownership of the returned -/// CFG is transferred to the caller. If CFG construction fails, this method -/// returns NULL. + +/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an +/// arbitrary statement. Examples include a single expression or a function +/// body (compound statement). The ownership of the returned CFG is +/// transferred to the caller. If CFG construction fails, this method returns +/// NULL. CFG* CFGBuilder::buildCFG(Stmt* Statement) { assert (cfg); if (!Statement) return NULL; badCFG = false; - - // Create an empty block that will serve as the exit block for the CFG. - // Since this is the first block added to the CFG, it will be implicitly - // registered as the exit block. + + // Create an empty block that will serve as the exit block for the CFG. Since + // this is the first block added to the CFG, it will be implicitly registered + // as the exit block. Succ = createBlock(); assert (Succ == &cfg->getExit()); Block = NULL; // the EXIT block is empty. Create all other blocks lazily. - + // Visit the statements and create the CFG. CFGBlock* B = Visit(Statement); if (!B) B = Succ; - + if (B) { - // Finalize the last constructed block. This usually involves - // reversing the order of the statements in the block. + // Finalize the last constructed block. This usually involves reversing the + // order of the statements in the block. if (Block) FinishBlock(B); - - // Backpatch the gotos whose label -> block mappings we didn't know - // when we encountered them. - for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), + + // Backpatch the gotos whose label -> block mappings we didn't know when we + // encountered them. + for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), E = BackpatchBlocks.end(); I != E; ++I ) { - + CFGBlock* B = *I; GotoStmt* G = cast(B->getTerminator()); LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); @@ -208,10 +207,10 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement) { // If there is no target for the goto, then we are looking at an // incomplete AST. Handle this by not registering a successor. if (LI == LabelMap.end()) continue; - - B->addSuccessor(LI->second); + + B->addSuccessor(LI->second); } - + // Add successors to the Indirect Goto Dispatch block (if we have one). if (CFGBlock* B = cfg->getIndirectGotoBlock()) for (LabelSetTy::iterator I = AddressTakenLabels.begin(), @@ -223,40 +222,39 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement) { // If there is no target block that contains label, then we are looking // at an incomplete AST. Handle this by not registering a successor. if (LI == LabelMap.end()) continue; - - B->addSuccessor(LI->second); + + B->addSuccessor(LI->second); } - + Succ = B; } - - // Create an empty entry block that has no predecessors. + + // Create an empty entry block that has no predecessors. cfg->setEntry(createBlock()); - + if (badCFG) { delete cfg; cfg = NULL; return NULL; } - - // NULL out cfg so that repeated calls to the builder will fail and that - // the ownership of the constructed CFG is passed to the caller. + + // NULL out cfg so that repeated calls to the builder will fail and that the + // ownership of the constructed CFG is passed to the caller. CFG* t = cfg; cfg = NULL; return t; } - + /// createBlock - Used to lazily create blocks that are connected /// to the current (global) succcessor. -CFGBlock* CFGBuilder::createBlock(bool add_successor) { +CFGBlock* CFGBuilder::createBlock(bool add_successor) { CFGBlock* B = cfg->createBlock(); if (add_successor && Succ) B->addSuccessor(Succ); return B; } - -/// FinishBlock - When the last statement has been added to the block, -/// we must reverse the statements because they have been inserted -/// in reverse order. + +/// FinishBlock - When the last statement has been added to the block, we must +/// reverse the statements because they have been inserted in reverse order. bool CFGBuilder::FinishBlock(CFGBlock* B) { if (badCFG) return false; @@ -266,218 +264,214 @@ bool CFGBuilder::FinishBlock(CFGBlock* B) { return true; } -/// addStmt - Used to add statements/expressions to the current CFGBlock +/// addStmt - Used to add statements/expressions to the current CFGBlock /// "Block". This method calls WalkAST on the passed statement to see if it -/// contains any short-circuit expressions. If so, it recursively creates -/// the necessary blocks for such expressions. It returns the "topmost" block -/// of the created blocks, or the original value of "Block" when this method -/// was called if no additional blocks are created. +/// contains any short-circuit expressions. If so, it recursively creates the +/// necessary blocks for such expressions. It returns the "topmost" block of +/// the created blocks, or the original value of "Block" when this method was +/// called if no additional blocks are created. CFGBlock* CFGBuilder::addStmt(Stmt* Terminator) { if (!Block) Block = createBlock(); return WalkAST(Terminator,true); } -/// WalkAST - Used by addStmt to walk the subtree of a statement and -/// add extra blocks for ternary operators, &&, and ||. We also -/// process "," and DeclStmts (which may contain nested control-flow). +/// WalkAST - Used by addStmt to walk the subtree of a statement and add extra +/// blocks for ternary operators, &&, and ||. We also process "," and +/// DeclStmts (which may contain nested control-flow). CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) { switch (Terminator->getStmtClass()) { - case Stmt::ConditionalOperatorClass: { - ConditionalOperator* C = cast(Terminator); + case Stmt::ConditionalOperatorClass: { + ConditionalOperator* C = cast(Terminator); + + // Create the confluence block that will "merge" the results of the ternary + // expression. + CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock(); + ConfluenceBlock->appendStmt(C); + if (!FinishBlock(ConfluenceBlock)) + return 0; - // Create the confluence block that will "merge" the results - // of the ternary expression. - CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock(); - ConfluenceBlock->appendStmt(C); - if (!FinishBlock(ConfluenceBlock)) + // Create a block for the LHS expression if there is an LHS expression. A + // GCC extension allows LHS to be NULL, causing the condition to be the + // value that is returned instead. + // e.g: x ?: y is shorthand for: x ? x : y; + Succ = ConfluenceBlock; + Block = NULL; + CFGBlock* LHSBlock = NULL; + if (C->getLHS()) { + LHSBlock = Visit(C->getLHS()); + if (!FinishBlock(LHSBlock)) return 0; - - // Create a block for the LHS expression if there is an LHS expression. - // A GCC extension allows LHS to be NULL, causing the condition to - // be the value that is returned instead. - // e.g: x ?: y is shorthand for: x ? x : y; - Succ = ConfluenceBlock; Block = NULL; - CFGBlock* LHSBlock = NULL; - if (C->getLHS()) { - LHSBlock = Visit(C->getLHS()); - if (!FinishBlock(LHSBlock)) - return 0; - Block = NULL; - } - - // Create the block for the RHS expression. - Succ = ConfluenceBlock; - CFGBlock* RHSBlock = Visit(C->getRHS()); - if (!FinishBlock(RHSBlock)) - return 0; + } - // Create the block that will contain the condition. - Block = createBlock(false); - - if (LHSBlock) - Block->addSuccessor(LHSBlock); - else { - // If we have no LHS expression, add the ConfluenceBlock as a direct - // successor for the block containing the condition. Moreover, - // we need to reverse the order of the predecessors in the - // ConfluenceBlock because the RHSBlock will have been added to - // the succcessors already, and we want the first predecessor to the - // the block containing the expression for the case when the ternary - // expression evaluates to true. - Block->addSuccessor(ConfluenceBlock); - assert (ConfluenceBlock->pred_size() == 2); - std::reverse(ConfluenceBlock->pred_begin(), - ConfluenceBlock->pred_end()); - } - - Block->addSuccessor(RHSBlock); - - Block->setTerminator(C); - return addStmt(C->getCond()); + // Create the block for the RHS expression. + Succ = ConfluenceBlock; + CFGBlock* RHSBlock = Visit(C->getRHS()); + if (!FinishBlock(RHSBlock)) + return 0; + + // Create the block that will contain the condition. + Block = createBlock(false); + + if (LHSBlock) + Block->addSuccessor(LHSBlock); + else { + // If we have no LHS expression, add the ConfluenceBlock as a direct + // successor for the block containing the condition. Moreover, we need to + // reverse the order of the predecessors in the ConfluenceBlock because + // the RHSBlock will have been added to the succcessors already, and we + // want the first predecessor to the the block containing the expression + // for the case when the ternary expression evaluates to true. + Block->addSuccessor(ConfluenceBlock); + assert (ConfluenceBlock->pred_size() == 2); + std::reverse(ConfluenceBlock->pred_begin(), + ConfluenceBlock->pred_end()); + } + + Block->addSuccessor(RHSBlock); + + Block->setTerminator(C); + return addStmt(C->getCond()); + } + + case Stmt::ChooseExprClass: { + ChooseExpr* C = cast(Terminator); + + CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); + ConfluenceBlock->appendStmt(C); + if (!FinishBlock(ConfluenceBlock)) + return 0; + + Succ = ConfluenceBlock; + Block = NULL; + CFGBlock* LHSBlock = Visit(C->getLHS()); + if (!FinishBlock(LHSBlock)) + return 0; + + Succ = ConfluenceBlock; + Block = NULL; + CFGBlock* RHSBlock = Visit(C->getRHS()); + if (!FinishBlock(RHSBlock)) + return 0; + + Block = createBlock(false); + Block->addSuccessor(LHSBlock); + Block->addSuccessor(RHSBlock); + Block->setTerminator(C); + return addStmt(C->getCond()); + } + + case Stmt::DeclStmtClass: { + DeclStmt *DS = cast(Terminator); + if (DS->isSingleDecl()) { + Block->appendStmt(Terminator); + return WalkAST_VisitDeclSubExpr(DS->getSingleDecl()); } - - case Stmt::ChooseExprClass: { - ChooseExpr* C = cast(Terminator); - - CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); - ConfluenceBlock->appendStmt(C); + + CFGBlock* B = 0; + + // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy. + typedef llvm::SmallVector BufTy; + BufTy Buf(DS->decl_begin(), DS->decl_end()); + + for (BufTy::reverse_iterator I=Buf.rbegin(), E=Buf.rend(); I!=E; ++I) { + // Get the alignment of the new DeclStmt, padding out to >=8 bytes. + unsigned A = llvm::AlignOf::Alignment < 8 + ? 8 : llvm::AlignOf::Alignment; + + // Allocate the DeclStmt using the BumpPtrAllocator. It will get + // automatically freed with the CFG. + DeclGroupRef DG(*I); + Decl* D = *I; + void* Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); + + DeclStmt* DS = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); + + // Append the fake DeclStmt to block. + Block->appendStmt(DS); + B = WalkAST_VisitDeclSubExpr(D); + } + return B; + } + + case Stmt::AddrLabelExprClass: { + AddrLabelExpr* A = cast(Terminator); + AddressTakenLabels.insert(A->getLabel()); + + if (AlwaysAddStmt) Block->appendStmt(Terminator); + return Block; + } + + case Stmt::StmtExprClass: + return WalkAST_VisitStmtExpr(cast(Terminator)); + + case Stmt::SizeOfAlignOfExprClass: { + SizeOfAlignOfExpr* E = cast(Terminator); + + // VLA types have expressions that must be evaluated. + if (E->isArgumentType()) { + for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr()); + VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) + addStmt(VA->getSizeExpr()); + } + // Expressions in sizeof/alignof are not evaluated and thus have no + // control flow. + else + Block->appendStmt(Terminator); + + return Block; + } + + case Stmt::BinaryOperatorClass: { + BinaryOperator* B = cast(Terminator); + + if (B->isLogicalOp()) { // && or || + CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock(); + ConfluenceBlock->appendStmt(B); if (!FinishBlock(ConfluenceBlock)) return 0; - - Succ = ConfluenceBlock; - Block = NULL; - CFGBlock* LHSBlock = Visit(C->getLHS()); - if (!FinishBlock(LHSBlock)) - return 0; + // create the block evaluating the LHS + CFGBlock* LHSBlock = createBlock(false); + LHSBlock->setTerminator(B); + + // create the block evaluating the RHS Succ = ConfluenceBlock; Block = NULL; - CFGBlock* RHSBlock = Visit(C->getRHS()); + CFGBlock* RHSBlock = Visit(B->getRHS()); if (!FinishBlock(RHSBlock)) return 0; - - Block = createBlock(false); - Block->addSuccessor(LHSBlock); - Block->addSuccessor(RHSBlock); - Block->setTerminator(C); - return addStmt(C->getCond()); - } - case Stmt::DeclStmtClass: { - DeclStmt *DS = cast(Terminator); - if (DS->isSingleDecl()) { - Block->appendStmt(Terminator); - return WalkAST_VisitDeclSubExpr(DS->getSingleDecl()); + // Now link the LHSBlock with RHSBlock. + if (B->getOpcode() == BinaryOperator::LOr) { + LHSBlock->addSuccessor(ConfluenceBlock); + LHSBlock->addSuccessor(RHSBlock); + } else { + assert (B->getOpcode() == BinaryOperator::LAnd); + LHSBlock->addSuccessor(RHSBlock); + LHSBlock->addSuccessor(ConfluenceBlock); } - - CFGBlock* B = 0; - - // FIXME: Add a reverse iterator for DeclStmt to avoid this - // extra copy. - typedef llvm::SmallVector BufTy; - BufTy Buf(DS->decl_begin(), DS->decl_end()); - - for (BufTy::reverse_iterator I=Buf.rbegin(), E=Buf.rend(); I!=E; ++I) { - // Get the alignment of the new DeclStmt, padding out to >=8 bytes. - unsigned A = llvm::AlignOf::Alignment < 8 - ? 8 : llvm::AlignOf::Alignment; - - // Allocate the DeclStmt using the BumpPtrAllocator. It will - // get automatically freed with the CFG. - DeclGroupRef DG(*I); - Decl* D = *I; - void* Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); - - DeclStmt* DS = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); - - // Append the fake DeclStmt to block. - Block->appendStmt(DS); - B = WalkAST_VisitDeclSubExpr(D); - } - return B; - } - case Stmt::AddrLabelExprClass: { - AddrLabelExpr* A = cast(Terminator); - AddressTakenLabels.insert(A->getLabel()); - - if (AlwaysAddStmt) Block->appendStmt(Terminator); - return Block; + // Generate the blocks for evaluating the LHS. + Block = LHSBlock; + return addStmt(B->getLHS()); + } else if (B->getOpcode() == BinaryOperator::Comma) { // , + Block->appendStmt(B); + addStmt(B->getRHS()); + return addStmt(B->getLHS()); } - - case Stmt::StmtExprClass: - return WalkAST_VisitStmtExpr(cast(Terminator)); - - case Stmt::SizeOfAlignOfExprClass: { - SizeOfAlignOfExpr* E = cast(Terminator); - - // VLA types have expressions that must be evaluated. - if (E->isArgumentType()) { - for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr()); - VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) - addStmt(VA->getSizeExpr()); - } - // Expressions in sizeof/alignof are not evaluated and thus have no - // control flow. - else - Block->appendStmt(Terminator); - return Block; - } - - case Stmt::BinaryOperatorClass: { - BinaryOperator* B = cast(Terminator); - - if (B->isLogicalOp()) { // && or || - CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock(); - ConfluenceBlock->appendStmt(B); - if (!FinishBlock(ConfluenceBlock)) - return 0; - - // create the block evaluating the LHS - CFGBlock* LHSBlock = createBlock(false); - LHSBlock->setTerminator(B); - - // create the block evaluating the RHS - Succ = ConfluenceBlock; - Block = NULL; - CFGBlock* RHSBlock = Visit(B->getRHS()); - if (!FinishBlock(RHSBlock)) - return 0; - - // Now link the LHSBlock with RHSBlock. - if (B->getOpcode() == BinaryOperator::LOr) { - LHSBlock->addSuccessor(ConfluenceBlock); - LHSBlock->addSuccessor(RHSBlock); - } - else { - assert (B->getOpcode() == BinaryOperator::LAnd); - LHSBlock->addSuccessor(RHSBlock); - LHSBlock->addSuccessor(ConfluenceBlock); - } - - // Generate the blocks for evaluating the LHS. - Block = LHSBlock; - return addStmt(B->getLHS()); - } - else if (B->getOpcode() == BinaryOperator::Comma) { // , - Block->appendStmt(B); - addStmt(B->getRHS()); - return addStmt(B->getLHS()); - } - - break; - } - + break; + } + // Blocks: No support for blocks ... yet - case Stmt::BlockExprClass: - case Stmt::BlockDeclRefExprClass: - return NYS(); - - case Stmt::ParenExprClass: - return WalkAST(cast(Terminator)->getSubExpr(), AlwaysAddStmt); - + case Stmt::BlockExprClass: + case Stmt::BlockDeclRefExprClass: + return NYS(); + + case Stmt::ParenExprClass: + return WalkAST(cast(Terminator)->getSubExpr(), AlwaysAddStmt); + case Stmt::CallExprClass: { bool NoReturn = false; CallExpr *C = cast(Terminator); @@ -508,24 +502,24 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) { return WalkAST_VisitChildren(Terminator); } - default: - break; + default: + break; }; - + if (AlwaysAddStmt) Block->appendStmt(Terminator); return WalkAST_VisitChildren(Terminator); } - -/// WalkAST_VisitDeclSubExpr - Utility method to add block-level expressions -/// for initializers in Decls. + +/// WalkAST_VisitDeclSubExpr - Utility method to add block-level expressions for +/// initializers in Decls. CFGBlock* CFGBuilder::WalkAST_VisitDeclSubExpr(Decl* D) { VarDecl* VD = dyn_cast(D); if (!VD) return Block; - + Expr* Init = VD->getInit(); - + if (Init) { // Optimization: Don't create separate block-level statements for literals. switch (Init->getStmtClass()) { @@ -537,24 +531,24 @@ CFGBlock* CFGBuilder::WalkAST_VisitDeclSubExpr(Decl* D) { Block = addStmt(Init); } } - + // If the type of VD is a VLA, then we must process its size expressions. for (VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) - Block = addStmt(VA->getSizeExpr()); - + Block = addStmt(VA->getSizeExpr()); + return Block; } -/// WalkAST_VisitChildren - Utility method to call WalkAST on the -/// children of a Stmt. +/// WalkAST_VisitChildren - Utility method to call WalkAST on the children of a +/// Stmt. CFGBlock* CFGBuilder::WalkAST_VisitChildren(Stmt* Terminator) { CFGBlock* B = Block; for (Stmt::child_iterator I = Terminator->child_begin(), E = Terminator->child_end(); I != E; ++I) if (*I) B = WalkAST(*I); - + return B; } @@ -562,19 +556,19 @@ CFGBlock* CFGBuilder::WalkAST_VisitChildren(Stmt* Terminator) { /// expressions (a GCC extension). CFGBlock* CFGBuilder::WalkAST_VisitStmtExpr(StmtExpr* Terminator) { Block->appendStmt(Terminator); - return VisitCompoundStmt(Terminator->getSubStmt()); + return VisitCompoundStmt(Terminator->getSubStmt()); } /// VisitStmt - Handle statements with no branching control flow. CFGBlock* CFGBuilder::VisitStmt(Stmt* Statement) { - // We cannot assume that we are in the middle of a basic block, since - // the CFG might only be constructed for this single statement. If - // we have no current basic block, just create one lazily. + // We cannot assume that we are in the middle of a basic block, since the CFG + // might only be constructed for this single statement. If we have no current + // basic block, just create one lazily. if (!Block) Block = createBlock(); - - // Simply add the statement to the current block. We actually - // insert statements in reverse order; this order is reversed later - // when processing the containing element in the AST. + + // Simply add the statement to the current block. We actually insert + // statements in reverse order; this order is reversed later when processing + // the containing element in the AST. addStmt(Statement); return Block; @@ -585,7 +579,7 @@ CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) { } CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { - + CFGBlock* LastBlock = Block; for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); @@ -597,35 +591,35 @@ CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { } CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { - // We may see an if statement in the middle of a basic block, or - // it may be the first statement we are processing. In either case, - // we create a new basic block. First, we create the blocks for - // the then...else statements, and then we create the block containing - // the if statement. If we were in the middle of a block, we - // stop processing that block and reverse its statements. That block - // is then the implicit successor for the "then" and "else" clauses. - - // The block we were proccessing is now finished. Make it the - // successor block. - if (Block) { + // We may see an if statement in the middle of a basic block, or it may be the + // first statement we are processing. In either case, we create a new basic + // block. First, we create the blocks for the then...else statements, and + // then we create the block containing the if statement. If we were in the + // middle of a block, we stop processing that block and reverse its + // statements. That block is then the implicit successor for the "then" and + // "else" clauses. + + // The block we were proccessing is now finished. Make it the successor + // block. + if (Block) { Succ = Block; if (!FinishBlock(Block)) return 0; } - - // Process the false branch. NULL out Block so that the recursive - // call to Visit will create a new basic block. + + // Process the false branch. NULL out Block so that the recursive call to + // Visit will create a new basic block. // Null out Block so that all successor CFGBlock* ElseBlock = Succ; - + if (Stmt* Else = I->getElse()) { SaveAndRestore sv(Succ); - + // NULL out Block so that the recursive call to Visit will - // create a new basic block. + // create a new basic block. Block = NULL; ElseBlock = Visit(Else); - + if (!ElseBlock) // Can occur when the Else body has all NullStmts. ElseBlock = sv.get(); else if (Block) { @@ -633,67 +627,65 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { return 0; } } - - // Process the true branch. NULL out Block so that the recursive - // call to Visit will create a new basic block. + + // Process the true branch. NULL out Block so that the recursive call to + // Visit will create a new basic block. // Null out Block so that all successor CFGBlock* ThenBlock; { Stmt* Then = I->getThen(); assert (Then); SaveAndRestore sv(Succ); - Block = NULL; + Block = NULL; ThenBlock = Visit(Then); - + if (!ThenBlock) { // We can reach here if the "then" body has all NullStmts. // Create an empty block so we can distinguish between true and false // branches in path-sensitive analyses. ThenBlock = createBlock(false); ThenBlock->addSuccessor(sv.get()); - } - else if (Block) { + } else if (Block) { if (!FinishBlock(ThenBlock)) return 0; - } + } } - // Now create a new block containing the if statement. + // Now create a new block containing the if statement. Block = createBlock(false); - + // Set the terminator of the new block to the If statement. Block->setTerminator(I); - + // Now add the successors. Block->addSuccessor(ThenBlock); Block->addSuccessor(ElseBlock); - - // Add the condition as the last statement in the new block. This - // may create new blocks as the condition may contain control-flow. Any - // newly created blocks will be pointed to be "Block". + + // Add the condition as the last statement in the new block. This may create + // new blocks as the condition may contain control-flow. Any newly created + // blocks will be pointed to be "Block". return addStmt(I->getCond()->IgnoreParens()); } - - + + CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) { - // If we were in the middle of a block we stop processing that block - // and reverse its statements. + // If we were in the middle of a block we stop processing that block and + // reverse its statements. // - // NOTE: If a "return" appears in the middle of a block, this means - // that the code afterwards is DEAD (unreachable). We still - // keep a basic block for that code; a simple "mark-and-sweep" - // from the entry block will be able to report such dead - // blocks. + // NOTE: If a "return" appears in the middle of a block, this means that the + // code afterwards is DEAD (unreachable). We still keep a basic block + // for that code; a simple "mark-and-sweep" from the entry block will be + // able to report such dead blocks. if (Block) FinishBlock(Block); // Create the new block. Block = createBlock(false); - + // The Exit block is the only successor. Block->addSuccessor(&cfg->getExit()); - - // Add the return statement to the block. This may create new blocks - // if R contains control-flow (short-circuit operations). + + // Add the return statement to the block. This may create new blocks if R + // contains control-flow (short-circuit operations). return addStmt(R); } @@ -701,75 +693,72 @@ CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) { // Get the block of the labeled statement. Add it to our map. Visit(L->getSubStmt()); CFGBlock* LabelBlock = Block; - + if (!LabelBlock) // This can happen when the body is empty, i.e. LabelBlock=createBlock(); // scopes that only contains NullStmts. - + assert (LabelMap.find(L) == LabelMap.end() && "label already in map"); LabelMap[ L ] = LabelBlock; - - // Labels partition blocks, so this is the end of the basic block - // we were processing (L is the block's label). Because this is - // label (and we have already processed the substatement) there is no - // extra control-flow to worry about. + + // Labels partition blocks, so this is the end of the basic block we were + // processing (L is the block's label). Because this is label (and we have + // already processed the substatement) there is no extra control-flow to worry + // about. LabelBlock->setLabel(L); if (!FinishBlock(LabelBlock)) return 0; - - // We set Block to NULL to allow lazy creation of a new block - // (if necessary); + + // We set Block to NULL to allow lazy creation of a new block (if necessary); Block = NULL; - + // This block is now the implicit successor of other blocks. Succ = LabelBlock; - + return LabelBlock; } CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) { - // Goto is a control-flow statement. Thus we stop processing the - // current block and create a new one. + // Goto is a control-flow statement. Thus we stop processing the current + // block and create a new one. if (Block) FinishBlock(Block); Block = createBlock(false); Block->setTerminator(G); - - // If we already know the mapping to the label block add the - // successor now. + + // If we already know the mapping to the label block add the successor now. LabelMapTy::iterator I = LabelMap.find(G->getLabel()); - + if (I == LabelMap.end()) // We will need to backpatch this block later. BackpatchBlocks.push_back(Block); else Block->addSuccessor(I->second); - return Block; + return Block; } CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { - // "for" is a control-flow statement. Thus we stop processing the - // current block. - + // "for" is a control-flow statement. Thus we stop processing the current + // block. + CFGBlock* LoopSuccessor = NULL; - + if (Block) { if (!FinishBlock(Block)) return 0; LoopSuccessor = Block; - } - else LoopSuccessor = Succ; - - // Because of short-circuit evaluation, the condition of the loop - // can span multiple basic blocks. Thus we need the "Entry" and "Exit" - // blocks that evaluate the condition. + } else LoopSuccessor = Succ; + + // Because of short-circuit evaluation, the condition of the loop can span + // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that + // evaluate the condition. CFGBlock* ExitConditionBlock = createBlock(false); CFGBlock* EntryConditionBlock = ExitConditionBlock; - + // Set the terminator for the "exit" condition block. - ExitConditionBlock->setTerminator(F); - - // Now add the actual condition to the condition block. Because the - // condition itself may contain control-flow, new blocks may be created. + ExitConditionBlock->setTerminator(F); + + // Now add the actual condition to the condition block. Because the condition + // itself may contain control-flow, new blocks may be created. if (Stmt* C = F->getCond()) { Block = ExitConditionBlock; EntryConditionBlock = addStmt(C); @@ -779,34 +768,33 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { } } - // The condition block is the implicit successor for the loop body as - // well as any code above the loop. + // The condition block is the implicit successor for the loop body as well as + // any code above the loop. Succ = EntryConditionBlock; - + // Now create the loop body. { assert (F->getBody()); - + // Save the current values for Block, Succ, and continue and break targets SaveAndRestore save_Block(Block), save_Succ(Succ), save_continue(ContinueTargetBlock), - save_break(BreakTargetBlock); - + save_break(BreakTargetBlock); + // Create a new block to contain the (bottom) of the loop body. Block = NULL; - + if (Stmt* I = F->getInc()) { - // Generate increment code in its own basic block. This is the target - // of continue statements. + // Generate increment code in its own basic block. This is the target of + // continue statements. Succ = Visit(I); - } - else { - // No increment code. Create a special, empty, block that is used as - // the target block for "looping back" to the start of the loop. + } else { + // No increment code. Create a special, empty, block that is used as the + // target block for "looping back" to the start of the loop. assert(Succ == EntryConditionBlock); Succ = createBlock(); } - + // Finish up the increment (or empty) block if it hasn't been already. if (Block) { assert(Block == Succ); @@ -814,45 +802,43 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { return 0; Block = 0; } - + ContinueTargetBlock = Succ; - + // The starting block for the loop increment is the block that should // represent the 'loop target' for looping back to the start of the loop. ContinueTargetBlock->setLoopTarget(F); // All breaks should go to the code following the loop. - BreakTargetBlock = LoopSuccessor; - - // Now populate the body block, and in the process create new blocks - // as we walk the body of the loop. - CFGBlock* BodyBlock = Visit(F->getBody()); + BreakTargetBlock = LoopSuccessor; + + // Now populate the body block, and in the process create new blocks as we + // walk the body of the loop. + CFGBlock* BodyBlock = Visit(F->getBody()); if (!BodyBlock) BodyBlock = EntryConditionBlock; // can happen for "for (...;...; ) ;" else if (Block) { if (!FinishBlock(BodyBlock)) return 0; - } - + } + // This new body block is a successor to our "exit" condition block. ExitConditionBlock->addSuccessor(BodyBlock); } - - // Link up the condition block with the code that follows the loop. - // (the false branch). + + // Link up the condition block with the code that follows the loop. (the + // false branch). ExitConditionBlock->addSuccessor(LoopSuccessor); - + // If the loop contains initialization, create a new block for those - // statements. This block can also contain statements that precede - // the loop. + // statements. This block can also contain statements that precede the loop. if (Stmt* I = F->getInit()) { Block = createBlock(); return addStmt(I); - } - else { - // There is no loop initialization. We are thus basically a while - // loop. NULL out Block to force lazy block construction. + } else { + // There is no loop initialization. We are thus basically a while loop. + // NULL out Block to force lazy block construction. Block = NULL; Succ = EntryConditionBlock; return EntryConditionBlock; @@ -887,70 +873,69 @@ CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { // // becomes: // - // the same with newVariable replaced with existingItem; the binding - // works the same except that for one ObjCForCollectionStmt::getElement() - // returns a DeclStmt and the other returns a DeclRefExpr. + // the same with newVariable replaced with existingItem; the binding works + // the same except that for one ObjCForCollectionStmt::getElement() returns + // a DeclStmt and the other returns a DeclRefExpr. // - + CFGBlock* LoopSuccessor = 0; - + if (Block) { if (!FinishBlock(Block)) return 0; LoopSuccessor = Block; Block = 0; - } - else LoopSuccessor = Succ; - + } else LoopSuccessor = Succ; + // Build the condition blocks. CFGBlock* ExitConditionBlock = createBlock(false); CFGBlock* EntryConditionBlock = ExitConditionBlock; - + // Set the terminator for the "exit" condition block. - ExitConditionBlock->setTerminator(S); - - // The last statement in the block should be the ObjCForCollectionStmt, - // which performs the actual binding to 'element' and determines if there - // are any more items in the collection. + ExitConditionBlock->setTerminator(S); + + // The last statement in the block should be the ObjCForCollectionStmt, which + // performs the actual binding to 'element' and determines if there are any + // more items in the collection. ExitConditionBlock->appendStmt(S); Block = ExitConditionBlock; - + // Walk the 'element' expression to see if there are any side-effects. We - // generate new blocks as necesary. We DON'T add the statement by default - // to the CFG unless it contains control-flow. + // generate new blocks as necesary. We DON'T add the statement by default to + // the CFG unless it contains control-flow. EntryConditionBlock = WalkAST(S->getElement(), false); - if (Block) { + if (Block) { if (!FinishBlock(EntryConditionBlock)) return 0; Block = 0; } - - // The condition block is the implicit successor for the loop body as - // well as any code above the loop. + + // The condition block is the implicit successor for the loop body as well as + // any code above the loop. Succ = EntryConditionBlock; - + // Now create the true branch. - { + { // Save the current values for Succ, continue and break targets. SaveAndRestore save_Succ(Succ), - save_continue(ContinueTargetBlock), save_break(BreakTargetBlock); - + save_continue(ContinueTargetBlock), save_break(BreakTargetBlock); + BreakTargetBlock = LoopSuccessor; - ContinueTargetBlock = EntryConditionBlock; - + ContinueTargetBlock = EntryConditionBlock; + CFGBlock* BodyBlock = Visit(S->getBody()); - + if (!BodyBlock) BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" else if (Block) { if (!FinishBlock(BodyBlock)) return 0; } - + // This new body block is a successor to our "exit" condition block. ExitConditionBlock->addSuccessor(BodyBlock); } - + // Link up the condition block with the code that follows the loop. // (the false branch). ExitConditionBlock->addSuccessor(LoopSuccessor); @@ -958,58 +943,57 @@ CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { // Now create a prologue block to contain the collection expression. Block = createBlock(); return addStmt(S->getCollection()); -} - +} + CFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) { // FIXME: Add locking 'primitives' to CFG for @synchronized. - + // Inline the body. CFGBlock *SyncBlock = Visit(S->getSynchBody()); - + // The sync body starts its own basic block. This makes it a little easier // for diagnostic clients. if (SyncBlock) { if (!FinishBlock(SyncBlock)) return 0; - + Block = 0; } - + Succ = SyncBlock; - + // Inline the sync expression. return Visit(S->getSynchExpr()); } - + CFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) { return NYS(); } CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { - // "while" is a control-flow statement. Thus we stop processing the - // current block. - + // "while" is a control-flow statement. Thus we stop processing the current + // block. + CFGBlock* LoopSuccessor = NULL; - + if (Block) { if (!FinishBlock(Block)) return 0; LoopSuccessor = Block; - } - else LoopSuccessor = Succ; - - // Because of short-circuit evaluation, the condition of the loop - // can span multiple basic blocks. Thus we need the "Entry" and "Exit" - // blocks that evaluate the condition. + } else LoopSuccessor = Succ; + + // Because of short-circuit evaluation, the condition of the loop can span + // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that + // evaluate the condition. CFGBlock* ExitConditionBlock = createBlock(false); CFGBlock* EntryConditionBlock = ExitConditionBlock; - + // Set the terminator for the "exit" condition block. ExitConditionBlock->setTerminator(W); - - // Now add the actual condition to the condition block. Because the - // condition itself may contain control-flow, new blocks may be created. - // Thus we update "Succ" after adding the condition. + + // Now add the actual condition to the condition block. Because the condition + // itself may contain control-flow, new blocks may be created. Thus we update + // "Succ" after adding the condition. if (Stmt* C = W->getCond()) { Block = ExitConditionBlock; EntryConditionBlock = addStmt(C); @@ -1019,11 +1003,11 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { return 0; } } - - // The condition block is the implicit successor for the loop body as - // well as any code above the loop. + + // The condition block is the implicit successor for the loop body as well as + // any code above the loop. Succ = EntryConditionBlock; - + // Process the loop body. { assert(W->getBody()); @@ -1033,94 +1017,92 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { save_continue(ContinueTargetBlock), save_break(BreakTargetBlock); - // Create an empty block to represent the transition block for looping - // back to the head of the loop. + // Create an empty block to represent the transition block for looping back + // to the head of the loop. Block = 0; assert(Succ == EntryConditionBlock); Succ = createBlock(); Succ->setLoopTarget(W); - ContinueTargetBlock = Succ; - + ContinueTargetBlock = Succ; + // All breaks should go to the code following the loop. BreakTargetBlock = LoopSuccessor; - + // NULL out Block to force lazy instantiation of blocks for the body. Block = NULL; - + // Create the body. The returned block is the entry to the loop body. CFGBlock* BodyBlock = Visit(W->getBody()); - + if (!BodyBlock) BodyBlock = EntryConditionBlock; // can happen for "while(...) ;" else if (Block) { if (!FinishBlock(BodyBlock)) return 0; } - + // Add the loop body entry as a successor to the condition. ExitConditionBlock->addSuccessor(BodyBlock); } - - // Link up the condition block with the code that follows the loop. - // (the false branch). + + // Link up the condition block with the code that follows the loop. (the + // false branch). ExitConditionBlock->addSuccessor(LoopSuccessor); - - // There can be no more statements in the condition block - // since we loop back to this block. NULL out Block to force - // lazy creation of another block. + + // There can be no more statements in the condition block since we loop back + // to this block. NULL out Block to force lazy creation of another block. Block = NULL; - + // Return the condition block, which is the dominating block for the loop. Succ = EntryConditionBlock; return EntryConditionBlock; } - + CFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) { // FIXME: This isn't complete. We basically treat @throw like a return // statement. - - // If we were in the middle of a block we stop processing that block - // and reverse its statements. + + // If we were in the middle of a block we stop processing that block and + // reverse its statements. if (Block) { if (!FinishBlock(Block)) return 0; } - + // Create the new block. Block = createBlock(false); - + // The Exit block is the only successor. Block->addSuccessor(&cfg->getExit()); - - // Add the statement to the block. This may create new blocks - // if S contains control-flow (short-circuit operations). + + // Add the statement to the block. This may create new blocks if S contains + // control-flow (short-circuit operations). return addStmt(S); } CFGBlock* CFGBuilder::VisitDoStmt(DoStmt* D) { // "do...while" is a control-flow statement. Thus we stop processing the // current block. - + CFGBlock* LoopSuccessor = NULL; - + if (Block) { if (!FinishBlock(Block)) return 0; LoopSuccessor = Block; - } - else LoopSuccessor = Succ; - - // Because of short-circuit evaluation, the condition of the loop - // can span multiple basic blocks. Thus we need the "Entry" and "Exit" - // blocks that evaluate the condition. + } else LoopSuccessor = Succ; + + // Because of short-circuit evaluation, the condition of the loop can span + // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that + // evaluate the condition. CFGBlock* ExitConditionBlock = createBlock(false); CFGBlock* EntryConditionBlock = ExitConditionBlock; - + // Set the terminator for the "exit" condition block. - ExitConditionBlock->setTerminator(D); - - // Now add the actual condition to the condition block. Because the - // condition itself may contain control-flow, new blocks may be created. + ExitConditionBlock->setTerminator(D); + + // Now add the actual condition to the condition block. Because the condition + // itself may contain control-flow, new blocks may be created. if (Stmt* C = D->getCond()) { Block = ExitConditionBlock; EntryConditionBlock = addStmt(C); @@ -1129,7 +1111,7 @@ CFGBlock* CFGBuilder::VisitDoStmt(DoStmt* D) { return 0; } } - + // The condition block is the implicit successor for the loop body. Succ = EntryConditionBlock; @@ -1137,54 +1119,53 @@ CFGBlock* CFGBuilder::VisitDoStmt(DoStmt* D) { CFGBlock* BodyBlock = NULL; { assert (D->getBody()); - + // Save the current values for Block, Succ, and continue and break targets SaveAndRestore save_Block(Block), save_Succ(Succ), save_continue(ContinueTargetBlock), save_break(BreakTargetBlock); - + // All continues within this loop should go to the condition block ContinueTargetBlock = EntryConditionBlock; - + // All breaks should go to the code following the loop. BreakTargetBlock = LoopSuccessor; - + // NULL out Block to force lazy instantiation of blocks for the body. Block = NULL; - + // Create the body. The returned block is the entry to the loop body. BodyBlock = Visit(D->getBody()); - + if (!BodyBlock) BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" else if (Block) { if (!FinishBlock(BodyBlock)) return 0; } - + // Add an intermediate block between the BodyBlock and the - // ExitConditionBlock to represent the "loop back" transition. - // Create an empty block to represent the transition block for looping - // back to the head of the loop. + // ExitConditionBlock to represent the "loop back" transition. Create an + // empty block to represent the transition block for looping back to the + // head of the loop. // FIXME: Can we do this more efficiently without adding another block? Block = NULL; Succ = BodyBlock; CFGBlock *LoopBackBlock = createBlock(); LoopBackBlock->setLoopTarget(D); - + // Add the loop body entry as a successor to the condition. ExitConditionBlock->addSuccessor(LoopBackBlock); } - + // Link up the condition block with the code that follows the loop. // (the false branch). ExitConditionBlock->addSuccessor(LoopSuccessor); - - // There can be no more statements in the body block(s) - // since we loop back to the body. NULL out Block to force - // lazy creation of another block. + + // There can be no more statements in the body block(s) since we loop back to + // the body. NULL out Block to force lazy creation of another block. Block = NULL; - + // Return the loop body, which is the dominating block for the loop. Succ = BodyBlock; return BodyBlock; @@ -1197,77 +1178,76 @@ CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) { if (!FinishBlock(Block)) return 0; } - + // Now create a new block that ends with the continue statement. Block = createBlock(false); Block->setTerminator(C); - + // If there is no target for the continue, then we are looking at an // incomplete AST. This means the CFG cannot be constructed. if (ContinueTargetBlock) Block->addSuccessor(ContinueTargetBlock); else badCFG = true; - + return Block; } CFGBlock* CFGBuilder::VisitBreakStmt(BreakStmt* B) { - // "break" is a control-flow statement. Thus we stop processing the - // current block. + // "break" is a control-flow statement. Thus we stop processing the current + // block. if (Block) { if (!FinishBlock(Block)) return 0; } - + // Now create a new block that ends with the break statement. Block = createBlock(false); Block->setTerminator(B); - - // If there is no target for the break, then we are looking at an - // incomplete AST. This means that the CFG cannot be constructed. + + // If there is no target for the break, then we are looking at an incomplete + // AST. This means that the CFG cannot be constructed. if (BreakTargetBlock) Block->addSuccessor(BreakTargetBlock); - else + else badCFG = true; - return Block; + return Block; } CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { - // "switch" is a control-flow statement. Thus we stop processing the - // current block. + // "switch" is a control-flow statement. Thus we stop processing the current + // block. CFGBlock* SwitchSuccessor = NULL; - + if (Block) { if (!FinishBlock(Block)) return 0; SwitchSuccessor = Block; - } - else SwitchSuccessor = Succ; + } else SwitchSuccessor = Succ; // Save the current "switch" context. SaveAndRestore save_switch(SwitchTerminatedBlock), save_break(BreakTargetBlock), save_default(DefaultCaseBlock); - // Set the "default" case to be the block after the switch statement. - // If the switch statement contains a "default:", this value will - // be overwritten with the block for that code. + // Set the "default" case to be the block after the switch statement. If the + // switch statement contains a "default:", this value will be overwritten with + // the block for that code. DefaultCaseBlock = SwitchSuccessor; - + // Create a new block that will contain the switch statement. SwitchTerminatedBlock = createBlock(false); - + // Now process the switch body. The code after the switch is the implicit // successor. Succ = SwitchSuccessor; BreakTargetBlock = SwitchSuccessor; - - // When visiting the body, the case statements should automatically get - // linked up to the switch. We also don't keep a pointer to the body, - // since all control-flow from the switch goes to case/default statements. + + // When visiting the body, the case statements should automatically get linked + // up to the switch. We also don't keep a pointer to the body, since all + // control-flow from the switch goes to case/default statements. assert (Terminator->getBody() && "switch must contain a non-NULL body"); Block = NULL; CFGBlock *BodyBlock = Visit(Terminator->getBody()); @@ -1276,83 +1256,81 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { return 0; } - // If we have no "default:" case, the default transition is to the - // code following the switch body. + // If we have no "default:" case, the default transition is to the code + // following the switch body. SwitchTerminatedBlock->addSuccessor(DefaultCaseBlock); - + // Add the terminator and condition in the switch block. SwitchTerminatedBlock->setTerminator(Terminator); assert (Terminator->getCond() && "switch condition must be non-NULL"); Block = SwitchTerminatedBlock; - + return addStmt(Terminator->getCond()); } CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* Terminator) { - // CaseStmts are essentially labels, so they are the - // first statement in a block. + // CaseStmts are essentially labels, so they are the first statement in a + // block. if (Terminator->getSubStmt()) Visit(Terminator->getSubStmt()); CFGBlock* CaseBlock = Block; - if (!CaseBlock) CaseBlock = createBlock(); - - // Cases statements partition blocks, so this is the top of - // the basic block we were processing (the "case XXX:" is the label). + if (!CaseBlock) CaseBlock = createBlock(); + + // Cases statements partition blocks, so this is the top of the basic block we + // were processing (the "case XXX:" is the label). CaseBlock->setLabel(Terminator); if (!FinishBlock(CaseBlock)) return 0; - - // Add this block to the list of successors for the block with the - // switch statement. + + // Add this block to the list of successors for the block with the switch + // statement. assert (SwitchTerminatedBlock); SwitchTerminatedBlock->addSuccessor(CaseBlock); - + // We set Block to NULL to allow lazy creation of a new block (if necessary) Block = NULL; - + // This block is now the implicit successor of other blocks. Succ = CaseBlock; - + return CaseBlock; } - + CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) { if (Terminator->getSubStmt()) Visit(Terminator->getSubStmt()); DefaultCaseBlock = Block; - if (!DefaultCaseBlock) DefaultCaseBlock = createBlock(); - - // Default statements partition blocks, so this is the top of - // the basic block we were processing (the "default:" is the label). + if (!DefaultCaseBlock) DefaultCaseBlock = createBlock(); + + // Default statements partition blocks, so this is the top of the basic block + // we were processing (the "default:" is the label). DefaultCaseBlock->setLabel(Terminator); if (!FinishBlock(DefaultCaseBlock)) return 0; - // Unlike case statements, we don't add the default block to the - // successors for the switch statement immediately. This is done - // when we finish processing the switch statement. This allows for - // the default case (including a fall-through to the code after the - // switch statement) to always be the last successor of a switch-terminated - // block. - + // Unlike case statements, we don't add the default block to the successors + // for the switch statement immediately. This is done when we finish + // processing the switch statement. This allows for the default case + // (including a fall-through to the code after the switch statement) to always + // be the last successor of a switch-terminated block. + // We set Block to NULL to allow lazy creation of a new block (if necessary) Block = NULL; - + // This block is now the implicit successor of other blocks. Succ = DefaultCaseBlock; - - return DefaultCaseBlock; + + return DefaultCaseBlock; } CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) { - // Lazily create the indirect-goto dispatch block if there isn't one - // already. + // Lazily create the indirect-goto dispatch block if there isn't one already. CFGBlock* IBlock = cfg->getIndirectGotoBlock(); - + if (!IBlock) { IBlock = createBlock(false); cfg->setIndirectGotoBlock(IBlock); } - + // IndirectGoto is a control-flow statement. Thus we stop processing the // current block and create a new one. if (Block) { @@ -1368,10 +1346,9 @@ CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) { } // end anonymous namespace -/// createBlock - Constructs and adds a new CFGBlock to the CFG. The -/// block has no successors or predecessors. If this is the first block -/// created in the CFG, it is automatically set to be the Entry and Exit -/// of the CFG. +/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has +/// no successors or predecessors. If this is the first block created in the +/// CFG, it is automatically set to be the Entry and Exit of the CFG. CFGBlock* CFG::createBlock() { bool first_block = begin() == end(); @@ -1406,48 +1383,47 @@ namespace { static void FindSubExprAssignments(Stmt* Terminator, llvm::SmallPtrSet& Set) { if (!Terminator) return; - + for (Stmt::child_iterator I=Terminator->child_begin(), E=Terminator->child_end(); I!=E; ++I) { if (!*I) continue; - + if (BinaryOperator* B = dyn_cast(*I)) if (B->isAssignmentOp()) Set.insert(B); - + FindSubExprAssignments(*I, Set); } } static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { BlkExprMapTy* M = new BlkExprMapTy(); - - // Look for assignments that are used as subexpressions. These are the - // only assignments that we want to *possibly* register as a block-level - // expression. Basically, if an assignment occurs both in a subexpression - // and at the block-level, it is a block-level expression. + + // Look for assignments that are used as subexpressions. These are the only + // assignments that we want to *possibly* register as a block-level + // expression. Basically, if an assignment occurs both in a subexpression and + // at the block-level, it is a block-level expression. llvm::SmallPtrSet SubExprAssignments; - + for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) for (CFGBlock::iterator BI=I->begin(), EI=I->end(); BI != EI; ++BI) FindSubExprAssignments(*BI, SubExprAssignments); for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { - - // Iterate over the statements again on identify the Expr* and Stmt* at - // the block-level that are block-level expressions. + + // Iterate over the statements again on identify the Expr* and Stmt* at the + // block-level that are block-level expressions. for (CFGBlock::iterator BI=I->begin(), EI=I->end(); BI != EI; ++BI) if (Expr* Exp = dyn_cast(*BI)) { - + if (BinaryOperator* B = dyn_cast(Exp)) { // Assignment expressions that are not nested within another - // expression are really "statements" whose value is never - // used by another expression. + // expression are really "statements" whose value is never used by + // another expression. if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) continue; - } - else if (const StmtExpr* Terminator = dyn_cast(Exp)) { - // Special handling for statement expressions. The last statement - // in the statement expression is also a block-level expr. + } else if (const StmtExpr* Terminator = dyn_cast(Exp)) { + // Special handling for statement expressions. The last statement in + // the statement expression is also a block-level expr. const CompoundStmt* C = Terminator->getSubStmt(); if (!C->body_empty()) { unsigned x = M->size(); @@ -1458,27 +1434,27 @@ static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { unsigned x = M->size(); (*M)[Exp] = x; } - + // Look at terminators. The condition is a block-level expression. - + Stmt* S = I->getTerminatorCondition(); - + if (S && M->find(S) == M->end()) { unsigned x = M->size(); (*M)[S] = x; } } - + return M; } CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) { assert(S != NULL); if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } - + BlkExprMapTy* M = reinterpret_cast(BlkExprMap); BlkExprMapTy::iterator I = M->find(S); - + if (I == M->end()) return CFG::BlkExprNumTy(); else return CFG::BlkExprNumTy(I->second); } @@ -1501,7 +1477,7 @@ unsigned CFG::getNumBlkExprs() { CFG::~CFG() { delete reinterpret_cast(BlkExprMap); } - + //===----------------------------------------------------------------------===// // CFG pretty printing //===----------------------------------------------------------------------===// @@ -1509,7 +1485,7 @@ CFG::~CFG() { namespace { class VISIBILITY_HIDDEN StmtPrinterHelper : public PrinterHelper { - + typedef llvm::DenseMap > StmtMapTy; StmtMapTy StmtMap; signed CurrentBlock; @@ -1526,24 +1502,24 @@ public: StmtMap[*BI] = std::make_pair(I->getBlockID(),j); } } - + virtual ~StmtPrinterHelper() {} - + const LangOptions &getLangOpts() const { return LangOpts; } void setBlockID(signed i) { CurrentBlock = i; } void setStmtID(unsigned i) { CurrentStmt = i; } - + virtual bool handledStmt(Stmt* Terminator, llvm::raw_ostream& OS) { - + StmtMapTy::iterator I = StmtMap.find(Terminator); if (I == StmtMap.end()) return false; - - if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock + + if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock && I->second.second == CurrentStmt) return false; - + OS << "[B" << I->second.first << "." << I->second.second << "]"; return true; } @@ -1554,7 +1530,7 @@ public: namespace { class VISIBILITY_HIDDEN CFGBlockTerminatorPrint : public StmtVisitor { - + llvm::raw_ostream& OS; StmtPrinterHelper* Helper; PrintingPolicy Policy; @@ -1563,15 +1539,17 @@ public: CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper, const PrintingPolicy &Policy) : OS(os), Helper(helper), Policy(Policy) {} - + void VisitIfStmt(IfStmt* I) { OS << "if "; I->getCond()->printPretty(OS,Helper,Policy); } - + // Default case. - void VisitStmt(Stmt* Terminator) { Terminator->printPretty(OS, Helper, Policy); } - + void VisitStmt(Stmt* Terminator) { + Terminator->printPretty(OS, Helper, Policy); + } + void VisitForStmt(ForStmt* F) { OS << "for (" ; if (F->getInit()) OS << "..."; @@ -1581,46 +1559,46 @@ public: if (F->getInc()) OS << "..."; OS << ")"; } - + void VisitWhileStmt(WhileStmt* W) { OS << "while " ; if (Stmt* C = W->getCond()) C->printPretty(OS, Helper, Policy); } - + void VisitDoStmt(DoStmt* D) { OS << "do ... while "; if (Stmt* C = D->getCond()) C->printPretty(OS, Helper, Policy); } - + void VisitSwitchStmt(SwitchStmt* Terminator) { OS << "switch "; Terminator->getCond()->printPretty(OS, Helper, Policy); } - + void VisitConditionalOperator(ConditionalOperator* C) { C->getCond()->printPretty(OS, Helper, Policy); - OS << " ? ... : ..."; + OS << " ? ... : ..."; } - + void VisitChooseExpr(ChooseExpr* C) { OS << "__builtin_choose_expr( "; C->getCond()->printPretty(OS, Helper, Policy); OS << " )"; } - + void VisitIndirectGotoStmt(IndirectGotoStmt* I) { OS << "goto *"; I->getTarget()->printPretty(OS, Helper, Policy); } - + void VisitBinaryOperator(BinaryOperator* B) { if (!B->isLogicalOp()) { VisitExpr(B); return; } - + B->getLHS()->printPretty(OS, Helper, Policy); - + switch (B->getOpcode()) { case BinaryOperator::LOr: OS << " || ..."; @@ -1630,23 +1608,23 @@ public: return; default: assert(false && "Invalid logical operator."); - } + } } - + void VisitExpr(Expr* E) { E->printPretty(OS, Helper, Policy); - } + } }; } // end anonymous namespace - + static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, Stmt* Terminator) { if (Helper) { // special printing for statement-expressions. if (StmtExpr* SE = dyn_cast(Terminator)) { CompoundStmt* Sub = SE->getSubStmt(); - + if (Sub->child_begin() != Sub->child_end()) { OS << "({ ... ; "; Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); @@ -1654,7 +1632,7 @@ static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, return; } } - + // special printing for comma expressions. if (BinaryOperator* B = dyn_cast(Terminator)) { if (B->getOpcode() == BinaryOperator::Comma) { @@ -1662,25 +1640,25 @@ static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, Helper->handledStmt(B->getRHS(),OS); OS << '\n'; return; - } - } + } + } } - + Terminator->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); - + // Expressions need a newline. if (isa(Terminator)) OS << '\n'; } - + static void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B, StmtPrinterHelper* Helper, bool print_edges) { - + if (Helper) Helper->setBlockID(B.getBlockID()); - + // Print the header. - OS << "\n [ B" << B.getBlockID(); - + OS << "\n [ B" << B.getBlockID(); + if (&B == &cfg->getEntry()) OS << " (ENTRY) ]\n"; else if (&B == &cfg->getExit()) @@ -1689,13 +1667,13 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg, OS << " (INDIRECT GOTO DISPATCH) ]\n"; else OS << " ]\n"; - + // Print the label of this block. if (Stmt* Terminator = const_cast(B.getLabel())) { if (print_edges) OS << " "; - + if (LabelStmt* L = dyn_cast(Terminator)) OS << L->getName(); else if (CaseStmt* C = dyn_cast(Terminator)) { @@ -1707,48 +1685,47 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg, C->getRHS()->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); } - } - else if (isa(Terminator)) + } else if (isa(Terminator)) OS << "default"; else assert(false && "Invalid label statement in CFGBlock."); - + OS << ":\n"; } - + // Iterate through the statements in the block and print them. unsigned j = 1; - + for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; I != E ; ++I, ++j ) { - + // Print the statement # in the basic block and the statement itself. if (print_edges) OS << " "; - + OS << llvm::format("%3d", j) << ": "; - + if (Helper) Helper->setStmtID(j); - + print_stmt(OS,Helper,*I); } - + // Print the terminator of this block. if (B.getTerminator()) { if (print_edges) OS << " "; - + OS << " T: "; - + if (Helper) Helper->setBlockID(-1); - + CFGBlockTerminatorPrint TPrinter(OS, Helper, PrintingPolicy(Helper->getLangOpts())); TPrinter.Visit(const_cast(B.getTerminator())); OS << '\n'; } - + if (print_edges) { // Print the predecessors of this block. OS << " Predecessors (" << B.pred_size() << "):"; @@ -1756,31 +1733,31 @@ static void print_block(llvm::raw_ostream& OS, const CFG* cfg, for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); I != E; ++I, ++i) { - + if (i == 8 || (i-8) == 0) OS << "\n "; - + OS << " B" << (*I)->getBlockID(); } - + OS << '\n'; - + // Print the successors of this block. OS << " Successors (" << B.succ_size() << "):"; i = 0; for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); I != E; ++I, ++i) { - + if (i == 8 || (i-8) % 10 == 0) OS << "\n "; OS << " B" << (*I)->getBlockID(); } - + OS << '\n'; } -} +} /// dump - A simple pretty printer of a CFG that outputs to stderr. @@ -1789,23 +1766,23 @@ void CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); } /// print - A simple pretty printer of a CFG that outputs to an ostream. void CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const { StmtPrinterHelper Helper(this, LO); - + // Print the entry block. print_block(OS, this, getEntry(), &Helper, true); - + // Iterate through the CFGBlocks and print them one by one. for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { // Skip the entry block, because we already printed it. if (&(*I) == &getEntry() || &(*I) == &getExit()) continue; - + print_block(OS, this, *I, &Helper, true); } - + // Print the exit block. print_block(OS, this, getExit(), &Helper, true); OS.flush(); -} +} /// dump - A simply pretty printer of a CFGBlock that outputs to stderr. void CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const { @@ -1822,86 +1799,86 @@ void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg, /// printTerminator - A simple pretty printer of the terminator of a CFGBlock. void CFGBlock::printTerminator(llvm::raw_ostream &OS, - const LangOptions &LO) const { + const LangOptions &LO) const { CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); TPrinter.Visit(const_cast(getTerminator())); } Stmt* CFGBlock::getTerminatorCondition() { - + if (!Terminator) return NULL; - + Expr* E = NULL; - + switch (Terminator->getStmtClass()) { default: break; - + case Stmt::ForStmtClass: E = cast(Terminator)->getCond(); break; - + case Stmt::WhileStmtClass: E = cast(Terminator)->getCond(); break; - + case Stmt::DoStmtClass: E = cast(Terminator)->getCond(); break; - + case Stmt::IfStmtClass: E = cast(Terminator)->getCond(); break; - + case Stmt::ChooseExprClass: E = cast(Terminator)->getCond(); break; - + case Stmt::IndirectGotoStmtClass: E = cast(Terminator)->getTarget(); break; - + case Stmt::SwitchStmtClass: E = cast(Terminator)->getCond(); break; - + case Stmt::ConditionalOperatorClass: E = cast(Terminator)->getCond(); break; - + case Stmt::BinaryOperatorClass: // '&&' and '||' E = cast(Terminator)->getLHS(); break; - + case Stmt::ObjCForCollectionStmtClass: - return Terminator; + return Terminator; } - + return E ? E->IgnoreParens() : NULL; } bool CFGBlock::hasBinaryBranchTerminator() const { - + if (!Terminator) return false; - + Expr* E = NULL; - + switch (Terminator->getStmtClass()) { default: return false; - - case Stmt::ForStmtClass: + + case Stmt::ForStmtClass: case Stmt::WhileStmtClass: case Stmt::DoStmtClass: case Stmt::IfStmtClass: case Stmt::ChooseExprClass: case Stmt::ConditionalOperatorClass: case Stmt::BinaryOperatorClass: - return true; + return true; } - + return E ? E->IgnoreParens() : NULL; } @@ -1912,7 +1889,7 @@ bool CFGBlock::hasBinaryBranchTerminator() const { #ifndef NDEBUG -static StmtPrinterHelper* GraphHelper; +static StmtPrinterHelper* GraphHelper; #endif void CFG::viewCFG(const LangOptions &LO) const { @@ -1944,7 +1921,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { OutStr[i] = '\\'; OutStr.insert(OutStr.begin()+i+1, 'l'); } - + return OutStr; #else return "";