CFG.cpp revision 4beaa9f51b2da57c64740cef2bd1c2fdb0c325d5
1fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===// 2fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 3fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// The LLVM Compiler Infrastructure 4fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 7fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 8fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 9fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 10fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// This file defines the CFG and CFGBuilder classes for representing and 11fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// building Control-Flow Graphs (CFGs) from ASTs. 12fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 13fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 14fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 15bd0487825751230a4396952b770349d2beac60b3Ted Kremenek#include "clang/Analysis/Support/SaveAndRestore.h" 16e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h" 17b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump#include "clang/AST/DeclCXX.h" 18c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek#include "clang/AST/StmtVisitor.h" 1942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#include "clang/AST/PrettyPrinter.h" 207dba8607e59096014b7139ff20ef00870041d518Ted Kremenek#include "llvm/Support/GraphWriter.h" 216cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Allocator.h" 226cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Format.h" 236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/DenseMap.h" 246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/SmallPtrSet.h" 250ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek#include "llvm/ADT/OwningPtr.h" 2683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 27fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenekusing namespace clang; 28fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 29fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremeneknamespace { 30fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 314afa39deaa245592977136d367251ee2c173dd8dDouglas Gregorstatic SourceLocation GetEndLoc(Decl* D) { 32c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(D)) 33c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek if (Expr* Ex = VD->getInit()) 34c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek return Ex->getSourceRange().getEnd(); 356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return D->getLocation(); 37c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek} 38ad5a894df1841698c824381b414630799adc26caTed Kremenek 39852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekclass AddStmtChoice { 40852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekpublic: 415ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek enum Kind { NotAlwaysAdd = 0, 425ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek AlwaysAdd = 1, 435ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek AsLValueNotAlwaysAdd = 2, 445ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek AlwaysAddAsLValue = 3 }; 455ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 46792bea97c42dabffce457cc79f6bfede9ed21712Benjamin Kramer AddStmtChoice(Kind kind) : k(kind) {} 475ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 48792bea97c42dabffce457cc79f6bfede9ed21712Benjamin Kramer bool alwaysAdd() const { return (unsigned)k & 0x1; } 49431ac2d9c2f7596af6187daf88be411cb1ea34cfTed Kremenek bool asLValue() const { return k >= AsLValueNotAlwaysAdd; } 505ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 51852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekprivate: 52792bea97c42dabffce457cc79f6bfede9ed21712Benjamin Kramer Kind k; 53852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek}; 546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 55a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 56fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 57fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 58fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 59fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 60fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 61fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 62fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 63fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 68c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 69ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 70e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 710ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek llvm::OwningPtr<CFG> cfg; 72ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 73fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBlock* Block; 74fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBlock* Succ; 75bf15b278a439d73b605ec00a8d3977ef305712f4Ted Kremenek CFGBlock* ContinueTargetBlock; 768a294713e032e4a27bae61c040abb41397952676Ted Kremenek CFGBlock* BreakTargetBlock; 77b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek CFGBlock* SwitchTerminatedBlock; 78eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek CFGBlock* DefaultCaseBlock; 795d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* TryTerminatedBlock; 806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 8119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // LabelMap records the mapping from Label expressions to their blocks. 820cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy; 830cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 874a2b8a10c4730eb2ceeec24505bef26eb7d829edTed Kremenek typedef std::vector<CFGBlock*> BackpatchBlocksTy; 880cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 9119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek typedef llvm::SmallPtrSet<LabelStmt*,5> LabelSetTy; 9219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 95ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG 96ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Block(NULL), Succ(NULL), 978a294713e032e4a27bae61c040abb41397952676Ted Kremenek ContinueTargetBlock(NULL), BreakTargetBlock(NULL), 985d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 995d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TryTerminatedBlock(NULL) {} 1006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 101d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 102ad5a894df1841698c824381b414630799adc26caTed Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, 103ad5a894df1841698c824381b414630799adc26caTed Kremenek bool pruneTriviallyFalseEdges, bool AddEHEdges, 1044c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddScopes); 1056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 1074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 108852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 109852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 110852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBlockExpr(BlockExpr* E, AddStmtChoice asc); 1114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 1127ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 1137ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 1147ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 115c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc); 116852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 1174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 118852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 1193fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 1207ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitConditionalOperator(ConditionalOperator *C, AddStmtChoice asc); 1213fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 1224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 1234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclSubExpr(Decl* D); 1243fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 1253fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 1263fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 1274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt* G); 1284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 1294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 1304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 131115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 1324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 1334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 1344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 1354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 1364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 1374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitReturnStmt(ReturnStmt* R); 138852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc); 139852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 1404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 1414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 1424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 143852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 144852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 1454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitChildren(Stmt* S); 146cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 147274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 148274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek CFGBlock* NYS() { 1494102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 1504102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 1514102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 1526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 153079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump CFGBlock *StartScope(Stmt *S, CFGBlock *B) { 154079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (!AddScopes) 155079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return B; 156079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 157079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (B == 0) 158079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump B = createBlock(); 159079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump B->StartScope(S, cfg->getBumpVectorContext()); 160079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return B; 161079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 162079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 163079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump void EndScope(Stmt *S) { 164079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (!AddScopes) 165079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return; 166079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 167079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block == 0) 168079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Block = createBlock(); 169079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Block->EndScope(S, cfg->getBumpVectorContext()); 170079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 171079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 1734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 174d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 175df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 176df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 177852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 178ad5a894df1841698c824381b414630799adc26caTed Kremenek 179852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek void AppendStmt(CFGBlock *B, Stmt *S, 180852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc = AddStmtChoice::AlwaysAdd) { 181852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue()); 182ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 183ad5a894df1841698c824381b414630799adc26caTed Kremenek 184ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek void AddSuccessor(CFGBlock *B, CFGBlock *S) { 185ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 186ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 1871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 188fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// TryResult - a class representing a variant over the values 189fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// 'true', 'false', or 'unknown'. This is returned by TryEvaluateBool, 190fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// and is used by the CFGBuilder to decide if a branch condition 191fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// can be decided up front during CFG construction. 192941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek class TryResult { 193941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek int X; 194941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek public: 195941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 196941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult() : X(-1) {} 1971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 198941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isTrue() const { return X == 1; } 199941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isFalse() const { return X == 0; } 200941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isKnown() const { return X >= 0; } 201941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek void negate() { 202941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(isKnown()); 203941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek X ^= 0x1; 204941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek } 205941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek }; 2061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20700998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// TryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 20800998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 209941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult TryEvaluateBool(Expr *S) { 210ad5a894df1841698c824381b414630799adc26caTed Kremenek if (!PruneTriviallyFalseEdges) 211ad5a894df1841698c824381b414630799adc26caTed Kremenek return TryResult(); 212ad5a894df1841698c824381b414630799adc26caTed Kremenek 21300998a068e50945118f334c98af05ed44d7c22a6Mike Stump Expr::EvalResult Result; 2149983cc110422a2e976191a0ce6ac4f1d7b634cc0Douglas Gregor if (!S->isTypeDependent() && !S->isValueDependent() && 2159983cc110422a2e976191a0ce6ac4f1d7b634cc0Douglas Gregor S->Evaluate(Result, *Context) && Result.Val.isInt()) 216fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek return Result.Val.getInt().getBoolValue(); 217941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek 218941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return TryResult(); 21900998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 22000998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2214102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek bool badCFG; 2224c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 223ad5a894df1841698c824381b414630799adc26caTed Kremenek // True iff trivially false edges should be pruned from the CFG. 224ad5a894df1841698c824381b414630799adc26caTed Kremenek bool PruneTriviallyFalseEdges; 225ad5a894df1841698c824381b414630799adc26caTed Kremenek 2264c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump // True iff EH edges on CallExprs should be added to the CFG. 2274c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdges; 2284c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 2294c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump // True iff scope start and scope end notes should be added to the CFG. 230079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump bool AddScopes; 231d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 2326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 233898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 234898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 235610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenekstatic VariableArrayType* FindVA(Type* t) { 236610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek while (ArrayType* vt = dyn_cast<ArrayType>(t)) { 237610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt)) 238610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 239610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 2406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 241610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 242610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 2436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 244610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 245610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 2466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 2486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 2496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 2506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 2516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 252b978a441c7d8bf59e7fede938e1f3b672573b443Mike StumpCFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, 253ad5a894df1841698c824381b414630799adc26caTed Kremenek bool pruneTriviallyFalseEdges, 25455f988efeb08b84c2dd9e4c05990b88c81fe2b58Mike Stump bool addehedges, bool AddScopes) { 255ad5a894df1841698c824381b414630799adc26caTed Kremenek 25655f988efeb08b84c2dd9e4c05990b88c81fe2b58Mike Stump AddEHEdges = addehedges; 257ad5a894df1841698c824381b414630799adc26caTed Kremenek PruneTriviallyFalseEdges = pruneTriviallyFalseEdges; 258ad5a894df1841698c824381b414630799adc26caTed Kremenek 259e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump Context = C; 2600ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 2614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 2624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 263d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 264079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump this->AddScopes = AddScopes; 2654102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = false; 2666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 2686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 2696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 27049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 271ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 27249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 2736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 274d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 2751b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 2761b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 2771b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 2781b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 2791b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 2801b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (B) 2811b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu Succ = B; 282b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump 283b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 284b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump // FIXME: Add code for base initializers and member initializers. 285b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump (void)CD; 286b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 2876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2881b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 2891b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 2901b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 2911b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 292c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 2931b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock* B = *I; 2941b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu GotoStmt* G = cast<GotoStmt>(B->getTerminator()); 2951b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 2966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2971b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 2981b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 2991b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 300d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 3011b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu AddSuccessor(B, LI->second); 3021b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 3036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3041b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 3051b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (CFGBlock* B = cfg->getIndirectGotoBlock()) 3061b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 3071b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 3081b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 3091b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 3101b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 3111b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 3121b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 3131b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 3141b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 3151b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 316c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar AddSuccessor(B, LI->second); 317c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 3186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 320322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 3216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3221b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 323d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 3246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 325d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 326d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 3276d9828c82c9321f042ab416fd2ffaa3034347d45Mike StumpCFGBlock* CFGBuilder::createBlock(bool add_successor) { 3289438252ad2ecae5338df565ca33c6969e4fbfa41Ted Kremenek CFGBlock* B = cfg->createBlock(); 3294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 330ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(B, Succ); 331d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 332d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 3336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 3356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 3366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 337852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 3384f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenektryAgain: 339f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 340f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 341f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 342f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 3434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 3444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 345852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 3464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 3474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 348852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 351852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 354852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBlockExpr(cast<BlockExpr>(S), asc); 3554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 3564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 3574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 360a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 361852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 3621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 3644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 3654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 3664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 367852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 3681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 3704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 373852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 3764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 3771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 378021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 379021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 380021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 38147e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek case Stmt::CXXExprWithTemporariesClass: { 38247e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek // FIXME: Handle temporaries. For now, just visit the subexpression 38347e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek // so we don't artificially create extra blocks. 384a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek return Visit(cast<CXXExprWithTemporaries>(S)->getSubExpr(), asc); 38547e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek } 38647e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 387c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu case Stmt::CXXMemberCallExprClass: 388c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc); 389c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu 390021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 391021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 392ad5a894df1841698c824381b414630799adc26caTed Kremenek 393021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 394021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 395ad5a894df1841698c824381b414630799adc26caTed Kremenek 3964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 3974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 4004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 4034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 4064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 4094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 4124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 4131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 4154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 4161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 4184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 420115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 421115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 422115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 4234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 4241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 4251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 4274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 4281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 4304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 4311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 4334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 4341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 4364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 4371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ParenExprClass: 4394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek S = cast<ParenExpr>(S)->getSubExpr(); 4401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump goto tryAgain; 4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::NullStmtClass: 4434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 4464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SizeOfAlignOfExprClass: 449852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), asc); 4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 452852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 4531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 4554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 4561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 4584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 4594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 4604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 4611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 462852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 463852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 4644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 465852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, S, asc); 4666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 4694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 4706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 4724f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) { 4734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = Block; 4744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (Stmt::child_iterator I = Terminator->child_begin(), 4754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek E = Terminator->child_end(); I != E; ++I) { 4764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (*I) B = Visit(*I); 4776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 4784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return B; 4794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 4801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 481852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 482852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 4834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 4846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 485852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 4864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 487852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, A, asc); 4886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 4896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 4914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 4921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 493852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 494852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 4954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (B->isLogicalOp()) { // && or || 4964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 497852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, B, asc); 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 499d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 5004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 5011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the LHS 5034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* LHSBlock = createBlock(false); 5044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LHSBlock->setTerminator(B); 5051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the RHS 5074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = ConfluenceBlock; 5084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = NULL; 5094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* RHSBlock = addStmt(B->getRHS()); 510862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 511862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek if (RHSBlock) { 512d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 513862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek return 0; 514862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 515862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek else { 516862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // Create an empty block for cases where the RHS doesn't require 517862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // any explicit statements in the CFG. 518862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek RHSBlock = createBlock(); 519862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 5201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52100998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 522941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal = TryEvaluateBool(B->getLHS()); 5232de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr)) 524941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek KnownVal.negate(); 52500998a068e50945118f334c98af05ed44d7c22a6Mike Stump 5264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now link the LHSBlock with RHSBlock. 5272de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LOr) { 528ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 529ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 5301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else { 5312de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LAnd); 532ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 533ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 53419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 5351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Generate the blocks for evaluating the LHS. 5374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = LHSBlock; 5384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 5391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 5402de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall else if (B->getOpcode() == BO_Comma) { // , 5416dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 542852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, B, asc); 5434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 5444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 5456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 546fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu else if (B->isAssignmentOp()) { 547fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (asc.alwaysAdd()) { 548fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 549fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu AppendStmt(Block, B, asc); 550fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 551ad5a894df1841698c824381b414630799adc26caTed Kremenek 552fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu Visit(B->getRHS()); 553fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu return Visit(B->getLHS(), AddStmtChoice::AsLValueNotAlwaysAdd); 554fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 5551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 556852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(B, asc); 5574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 5586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 559852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { 560852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 561721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 562852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, E, asc); 563721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 564721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 5654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 566cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 5674f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 5684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 5694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 570d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 571d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 5721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 5744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 5754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 5784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 5794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (BreakTargetBlock) 580ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, BreakTargetBlock); 5814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek else 5824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 5831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 5864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 5871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5884c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stumpstatic bool CanThrow(Expr *E) { 5894c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 5904c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 5914c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 5924c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 5934c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 594ad5a894df1841698c824381b414630799adc26caTed Kremenek 5954c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 5964c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 5974c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 5984c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Proto->hasEmptyExceptionSpec()) 5994c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 6004c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 6014c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 6024c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 6034c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 604852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 6054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If this is a call to a no-return function, this stops the block here. 6062455636163fdd18581d7fdae816433f886d88213Mike Stump bool NoReturn = false; 607264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) { 6082455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 6092455636163fdd18581d7fdae816433f886d88213Mike Stump } 6102455636163fdd18581d7fdae816433f886d88213Mike Stump 6114c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 612079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 613079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 614079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Context->getLangOptions().Exceptions) { 6154c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdges) 6164c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 617079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 618079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 619079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 6202455636163fdd18581d7fdae816433f886d88213Mike Stump if (FD->hasAttr<NoReturnAttr>()) 6212455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 622079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 6234c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 624079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 6252455636163fdd18581d7fdae816433f886d88213Mike Stump 6264c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (!CanThrow(C->getCallee())) 6274c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 6284c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 629fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (!NoReturn && !AddEHEdge) { 630fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (asc.asLValue()) 631fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu return VisitStmt(C, AddStmtChoice::AlwaysAddAsLValue); 632fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu else 633fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu return VisitStmt(C, AddStmtChoice::AlwaysAdd); 634fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 6351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 636079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 637079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 638d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 639079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 640079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 6411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 642079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Block = createBlock(!NoReturn); 643852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, C, asc); 6442455636163fdd18581d7fdae816433f886d88213Mike Stump 645079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (NoReturn) { 646079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Wire this to the exit block directly. 647079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, &cfg->getExit()); 648079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 6494c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 650079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 651079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 652079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, TryTerminatedBlock); 653079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 654079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, &cfg->getExit()); 655079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 6561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6572455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 658d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 659d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 660852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 661852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 6623fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 663852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, C, asc); 664d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 6653fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 6661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 667115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 668115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AlwaysAdd; 669115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 6703fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 6713fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 672df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* LHSBlock = Visit(C->getLHS(), asc); 673d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 6743fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 6751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6763fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 6773fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 678df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* RHSBlock = Visit(C->getRHS(), asc); 679d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 6803fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 6811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6823fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 68300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 684941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(C->getCond()); 685ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 686ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 6873fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 6881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 6893fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 6901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6921eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { 693079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump EndScope(C); 694079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 6951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CFGBlock* LastBlock = Block; 6964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 6974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 6984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 699334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 700334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 701334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 702334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 7031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 704e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 705e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 7061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 707079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 708079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump LastBlock = StartScope(C, LastBlock); 709079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 7104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 7114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 713852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, 714852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 715f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 716f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 717f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 718852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, C, asc); 719d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 720f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 7211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 722115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 723115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AlwaysAdd; 724115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 725f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 726f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 727f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 728f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 729f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 730f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 731f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek CFGBlock* LHSBlock = NULL; 732f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek if (C->getLHS()) { 733df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu LHSBlock = Visit(C->getLHS(), asc); 734d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 735f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 736f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 737f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 7381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 739f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 740f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 741df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* RHSBlock = Visit(C->getRHS(), asc); 742d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 743f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 745f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 746f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 7471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 74800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 749941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(C->getCond()); 750e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump if (LHSBlock) { 751ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 752e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } else { 753941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek if (KnownVal.isFalse()) { 754e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // If we know the condition is false, add NULL as the successor for 755e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // the block containing the condition. In this case, the confluence 756e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // block will have just one predecessor. 757ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, 0); 758941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(ConfluenceBlock->pred_size() == 1); 759e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } else { 760e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // If we have no LHS expression, add the ConfluenceBlock as a direct 761e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // successor for the block containing the condition. Moreover, we need to 762e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // reverse the order of the predecessors in the ConfluenceBlock because 763e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // the RHSBlock will have been added to the succcessors already, and we 764e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // want the first predecessor to the the block containing the expression 765e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // for the case when the ternary expression evaluates to true. 766ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, ConfluenceBlock); 767941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(ConfluenceBlock->pred_size() == 2); 768e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump std::reverse(ConfluenceBlock->pred_begin(), 769e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ConfluenceBlock->pred_end()); 770e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } 771f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 7721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 773ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 774f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 775f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return addStmt(C->getCond()); 776f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 777f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 7784f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 7794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 7806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 7814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (DS->isSingleDecl()) { 782ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, DS); 7834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclSubExpr(DS->getSingleDecl()); 784d34066c224f782056c18f154abe04ef590473fd9Ted Kremenek } 7851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 7871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy. 7894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek typedef llvm::SmallVector<Decl*,10> BufTy; 7904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BufTy Buf(DS->decl_begin(), DS->decl_end()); 7911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) { 7934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 7944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 7954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 7961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 7984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 7994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 8004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 8011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 8024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 8031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 805ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, DSNew); 8064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek B = VisitDeclSubExpr(D); 8074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 8081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 8104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 8134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// initializers in Decls. 8144f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclSubExpr(Decl* D) { 8154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(Block); 816d34066c224f782056c18f154abe04ef590473fd9Ted Kremenek 8174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VarDecl *VD = dyn_cast<VarDecl>(D); 8181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!VD) 8204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 8211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 8231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 8255ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek AddStmtChoice::Kind k = 8265ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek VD->getType()->isReferenceType() ? AddStmtChoice::AsLValueNotAlwaysAdd 8275ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek : AddStmtChoice::NotAlwaysAdd; 8285ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek Visit(Init, AddStmtChoice(k)); 8294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 8324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); VA != 0; 8334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA = FindVA(VA->getElementType().getTypePtr())) 8344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = addStmt(VA->getSizeExpr()); 8351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 837d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 838fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 839d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { 8406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 8416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 8426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 8436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 8446c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 8456c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 8466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 8476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The block we were proccessing is now finished. Make it the successor 8486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 8496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 850d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 851d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 8524e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 853c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 8546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 855b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 856d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ElseBlock = Succ; 8576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 858d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* Else = I->getElse()) { 859d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 8606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 861d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 8626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 863d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 8644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 8656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 866b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 867b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 8684e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 869d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 8704e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 8714e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 872c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 8736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 874b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 875d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ThenBlock; 876d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 877d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Stmt* Then = I->getThen(); 8786db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 879d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 8806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 8814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 8826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 883dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 884dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 885dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 886dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 887dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 888ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ThenBlock, sv.get()); 8896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 890d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 8914e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 8926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 8930cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 894d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 8956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 896d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 8976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 898d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 899d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 9006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 90100998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 902941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult &KnownVal = TryEvaluateBool(I->getCond()); 90300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 904d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 905ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 906ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 9076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 9096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 9106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 91161dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek Block = addStmt(I->getCond()); 912ad5a894df1841698c824381b414630799adc26caTed Kremenek 91361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 91461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 91561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 91661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 91761dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 91861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek AppendStmt(Block, I, AddStmtChoice::AlwaysAdd); 91961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek addStmt(Init); 92061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 92161dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 922ad5a894df1841698c824381b414630799adc26caTed Kremenek 92361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek return Block; 924d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 9256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 927d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) { 9286c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 929d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 9306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 9316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 9326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 9336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 934d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 935d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 936d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 9376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 938d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 939ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, &cfg->getExit()); 9406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 9426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 943852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 944d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 9450cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 946d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) { 947d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 9484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 9492677ea871a25aa79f9db360f6ed10584c02267adTed Kremenek CFGBlock* LabelBlock = Block; 9506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 9524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 9536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(LabelMap.find(L) == LabelMap.end() && "label already in map"); 955d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMap[ L ] = LabelBlock; 9566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 9586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 9596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 9606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 9619cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 962d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 9634e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 9646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 966d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 9676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 968d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 969d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 9706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 971d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 972d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 97331dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 974d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) { 9756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 9766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 9774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 978d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 979d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 9806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 982d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 9836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 984d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 985d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 986d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek BackpatchBlocks.push_back(Block); 987d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek else 988ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, I->second); 989d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 9906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 991d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 992d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 993d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { 994d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 9956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 996fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 997fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 998d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 999d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 10004e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1001d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 10024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 10034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 10046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10053f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 10063f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 10073f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek SaveAndRestore<CFGBlock*> save_break(BreakTargetBlock); 10083f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek BreakTargetBlock = LoopSuccessor; 10093f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 10106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 10116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 10126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 101349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 101449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 10156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 101649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 10176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(F); 10186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 10206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 102149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = F->getCond()) { 102249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 102349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 102458b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek assert(Block == EntryConditionBlock); 102558b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek 102658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // If this block contains a condition variable, add both the condition 102758b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // variable and initializer to the CFG. 102858b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (VarDecl *VD = F->getConditionVariable()) { 102958b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (Expr *Init = VD->getInit()) { 103058b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek autoCreateBlock(); 103158b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek AppendStmt(Block, F, AddStmtChoice::AlwaysAdd); 103258b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek EntryConditionBlock = addStmt(Init); 103358b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek assert(Block == EntryConditionBlock); 103458b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 103558b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 1036ad5a894df1841698c824381b414630799adc26caTed Kremenek 10374e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1038d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 10394e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 10404e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 104149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 1042d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 10436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 10446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 104549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 10466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 104700998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1048941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal(true); 10491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105000998a068e50945118f334c98af05ed44d7c22a6Mike Stump if (F->getCond()) 105100998a068e50945118f334c98af05ed44d7c22a6Mike Stump KnownVal = TryEvaluateBool(F->getCond()); 105200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1053d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1054d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 10556db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 10566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10573f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current values for Block, Succ, and continue targets. 10583f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ), 10593f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek save_continue(ContinueTargetBlock); 10606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1061af603f742491dc4707138c0293d295171fdd51baTed Kremenek // Create a new block to contain the (bottom) of the loop body. 1062af603f742491dc4707138c0293d295171fdd51baTed Kremenek Block = NULL; 10636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1064e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek if (Stmt* I = F->getInc()) { 10656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 10666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 10674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 10686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 10696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // No increment code. Create a special, empty, block that is used as the 10706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // target block for "looping back" to the start of the loop. 10713575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Succ == EntryConditionBlock); 10723575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Succ = createBlock(); 1073e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 10746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10753575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 10763575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 10773575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1078d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 10794e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 10803575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 10813575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 10826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10833575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek ContinueTargetBlock = Succ; 10846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10853575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // The starting block for the loop increment is the block that should 10863575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 10873575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek ContinueTargetBlock->setLoopTarget(F); 10883575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 10896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 10906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 10914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(F->getBody()); 1092af603f742491dc4707138c0293d295171fdd51baTed Kremenek 1093af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 10941d4b218fa55239f2a7350f48be14090d2753c22cZhongxing Xu BodyBlock = ContinueTargetBlock; // can happen for "for (...;...;...) ;" 1095d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 1096941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 10976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1098941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // This new body block is a successor to our "exit" condition block. 1099ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1100d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 11016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1102941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1103941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 1104ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 11056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1106d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 11076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 1108d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* I = F->getInit()) { 1109d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 111049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 11116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 11126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There is no loop initialization. We are thus basically a while loop. 11136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NULL out Block to force lazy block construction. 11142bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek Block = NULL; 11155482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 111649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 11172bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 1118d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1119d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1120115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 1121115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek if (asc.alwaysAdd()) { 1122115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 1123115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek AppendStmt(Block, M, asc); 1124115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 1125115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return Visit(M->getBase(), 1126115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek M->isArrow() ? AddStmtChoice::NotAlwaysAdd 1127115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AsLValueNotAlwaysAdd); 1128115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 1129115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1130514de5a21645900c92cf4f4f7313d6f66945d134Ted KremenekCFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 1131514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 1132514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 1133514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1134514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 1135514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1136514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1137514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1138514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 1139514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 1140514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1141514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 11424cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 1143514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 1144514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 1145514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 1146514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 1147514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1148514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 1149514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 1150514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1151514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 1152514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1153514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 1154514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 1155514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1156514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1157514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 11586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 11596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 11606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 1161514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 11626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1163514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek CFGBlock* LoopSuccessor = 0; 11646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1165514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 1166d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 11674e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1168514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 1169514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 11704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 11714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 11726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11734cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 11744cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 11754cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 11766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11774cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 11786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 11796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 11816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 11826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 1183ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(ExitConditionBlock, S); 11844cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 11856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11864cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 11876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // generate new blocks as necesary. We DON'T add the statement by default to 11886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 1189852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd); 11906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1191d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 11924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 11934e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 11944e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 11956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 11976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 11984cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 11996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12004cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 12016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 12024cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 12034cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek SaveAndRestore<CFGBlock*> save_Succ(Succ), 12046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump save_continue(ContinueTargetBlock), save_break(BreakTargetBlock); 12056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12064cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BreakTargetBlock = LoopSuccessor; 12076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ContinueTargetBlock = EntryConditionBlock; 12086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(S->getBody()); 12106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12114cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 12124cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" 12134e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1214d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12154e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 12164e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 12176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12184cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 1219ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, BodyBlock); 12204cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 12216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12224cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 12234cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 1224ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, LoopSuccessor); 12254cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 1226514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 12274cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 1228514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 12296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 12306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1231b3b0b3624e462c2940f65b86e773bfc300005203Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) { 1232b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 12336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1234b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 12354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 12366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1237da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 1238da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 1239da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 1240d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1241da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 12426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1243da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 1244fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 1245da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 12466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12474beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 12484beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 12494beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek AppendStmt(Block, S, AddStmtChoice::AlwaysAdd); 12504beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 1251b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 12524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 1253b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 12546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1255e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) { 12564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 125790658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 1258e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 1259514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 1260d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { 1261d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 12626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1263fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 1264fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1265d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1266d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12674e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1268d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 12694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 12704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 12716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 12736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 12746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 127549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 127649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 12776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 127849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 127949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek ExitConditionBlock->setTerminator(W); 12806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 12826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. Thus we update 12836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "Succ" after adding the condition. 128449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = W->getCond()) { 128549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 128649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 1287f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Block == EntryConditionBlock); 1288ad5a894df1841698c824381b414630799adc26caTed Kremenek 12894ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // If this block contains a condition variable, add both the condition 12904ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // variable and initializer to the CFG. 12914ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 12924ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (Expr *Init = VD->getInit()) { 12934ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek autoCreateBlock(); 12944ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek AppendStmt(Block, W, AddStmtChoice::AlwaysAdd); 12954ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek EntryConditionBlock = addStmt(Init); 12964ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek assert(Block == EntryConditionBlock); 12974ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 12984ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 12994ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek 13004e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1301d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13024e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 13034e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 130449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 13056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 13076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 130849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 13096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 131000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1311941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(W->getCond()); 131200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1313d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 1314d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 1315f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 1316d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1317d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 1318d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ), 1319d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek save_continue(ContinueTargetBlock), 1320d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek save_break(BreakTargetBlock); 1321f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 13226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 13236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 1324f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Block = 0; 1325f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Succ == EntryConditionBlock); 1326f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ = createBlock(); 1327f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ->setLoopTarget(W); 13286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ContinueTargetBlock = Succ; 13296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1330d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 1331d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek BreakTargetBlock = LoopSuccessor; 13326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1333d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 1334f752fcfae84fbf21b78383bf2461633382d51844Ted Kremenek Block = NULL; 13356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1336d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 13374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(W->getBody()); 13386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1339af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 1340d5c3b1339e842619fc3ae79482424f901aeb89f3Zhongxing Xu BodyBlock = ContinueTargetBlock; // can happen for "while(...) ;" 13414e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1342d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13434e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 13444e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 13456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1346941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 1347ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1348bf15b278a439d73b605ec00a8d3977ef305712f4Ted Kremenek } 13496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1350941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1351941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 1352ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 13536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 13556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 1356d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 13576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13584ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 13595482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 136049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 1361d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 13621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13644f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) { 13654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 13664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 13674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 13684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 13696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13702fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) { 13712fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 13722fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 13736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13746c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1375d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 13776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13782fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 13792fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 13806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13812fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 1382ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, &cfg->getExit()); 13836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 13856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 1386852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 13872fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 1388989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 13890979d80615df97c675423de631c1b884819f4712Mike StumpCFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) { 13906c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1391d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13920979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 13930979d80615df97c675423de631c1b884819f4712Mike Stump 13940979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 13950979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 13960979d80615df97c675423de631c1b884819f4712Mike Stump 13975d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 13985d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 13995d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump AddSuccessor(Block, TryTerminatedBlock); 1400ad5a894df1841698c824381b414630799adc26caTed Kremenek else 14015d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 14025d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump AddSuccessor(Block, &cfg->getExit()); 14030979d80615df97c675423de631c1b884819f4712Mike Stump 14040979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 14050979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 1406852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 14070979d80615df97c675423de631c1b884819f4712Mike Stump} 14080979d80615df97c675423de631c1b884819f4712Mike Stump 14094f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) { 1410d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 14116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14128f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 14138f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 1414d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1415d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14164e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1417d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 14184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 14194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 14206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 14226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 14236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 142449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 142549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 14266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 142749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 14286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 14296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 14316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 143249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = D->getCond()) { 143349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 143449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 14354e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1436d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14374e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 14384e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 143949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 14406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14415482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 144249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 144349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 144400998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1445941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult &KnownVal = TryEvaluateBool(D->getCond()); 144600998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1447d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 144849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* BodyBlock = NULL; 1449d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 14506db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 14516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1452d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 1453d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ), 14545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump save_continue(ContinueTargetBlock), 14555d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump save_break(BreakTargetBlock); 14566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1457d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 145849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek ContinueTargetBlock = EntryConditionBlock; 14596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1460d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 1461d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek BreakTargetBlock = LoopSuccessor; 14626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1463d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 1464b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 14656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1466d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 14674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 14686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1469af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 1470a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 14714e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1472d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14734e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 14744e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 14756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1476d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 1477d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 1478d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 1479d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 1480d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 1481d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 1482d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 1483d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 1484d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 1485d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 1486d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 1487d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 1488d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek AddSuccessor(ExitConditionBlock, LoopBackBlock); 1489d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 1490d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 1491d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek AddSuccessor(ExitConditionBlock, NULL); 1492b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 14936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1494941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 1495941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 1496ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 14976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 14996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 1500d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 15016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1502d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 15035482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 1504d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 1505d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1506d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1507d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) { 1508d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 1509d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 1510d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1511d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 15126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1513d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 1514d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1515d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 15166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1517d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 1518235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 1519235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek if (ContinueTargetBlock) 1520ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, ContinueTargetBlock); 1521235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek else 1522235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 15236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1524d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 1525d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 15261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152713fc08a323b29dd97a46def1e3a15bf082476efaTed KremenekCFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, 1528852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 152913fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 1530852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 153113fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 1532ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, E); 153313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 15341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 15364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 15374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr()); 15384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 15394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(VA->getSizeExpr()); 15404e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 15411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1543d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 15441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 15464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 1547852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 1548852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 154913fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 1550ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, SE); 155113fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 15524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 15534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1554d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1555411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { 15566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 15576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 1558d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* SwitchSuccessor = NULL; 15596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1560d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1561d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15624e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1563d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 15646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 1565d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1566d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 1567d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 1568eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_break(BreakTargetBlock), 1569eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 1570eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 15716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 15726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 15736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 1574eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 15756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1576d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 1577d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 15786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1579d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 1580d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 1581d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 1582d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek BreakTargetBlock = SwitchSuccessor; 15836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 15856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 15866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 15876db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 158849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 1589d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 15904e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1591d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 15934e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 159449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 15956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 15966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // following the switch body. 1597ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(SwitchTerminatedBlock, DefaultCaseBlock); 15986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 159949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 1600411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 16016db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 1602d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 16036b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek Block = addStmt(Terminator->getCond()); 1604ad5a894df1841698c824381b414630799adc26caTed Kremenek 16056b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 16066b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 16076b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 16086b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 16096b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 16106b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek AppendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd); 16116b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek addStmt(Init); 16126b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 16136b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 1614ad5a894df1841698c824381b414630799adc26caTed Kremenek 16156b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek return Block; 1616d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1617d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 16184f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) { 16196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 16206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 16210fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 16220fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 16230fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 16240fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 16250fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 16260fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 16270fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 16280fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *CurrentBlock = createBlock(false); 16290fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CurrentBlock->setLabel(CS); 16300fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 16310fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 16320fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(LastBlock, CurrentBlock); 16330fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 16340fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek TopBlock = CurrentBlock; 16350fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 16360fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(SwitchTerminatedBlock, CurrentBlock); 16370fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek LastBlock = CurrentBlock; 16380fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 16390fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 16400fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 16410fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 164229ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 16430fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 16440fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 16451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 164629ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek CFGBlock* CaseBlock = Block; 16474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 16484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 16496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 16516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 16524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 16534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1654d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16554e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 16566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 16586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 16594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 1660ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(SwitchTerminatedBlock, CaseBlock); 16616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1662d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 1663d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 16646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16650fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 16660fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(LastBlock, CaseBlock); 16670fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 16680fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 16690fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else { 16700fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 16710fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 16720fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 16736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16740fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 1675d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 16766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1677411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) { 16784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 16794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 16801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1681eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 16824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 16834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 16844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 16856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 16876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 1688411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 16891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1690d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16914e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1692eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 16936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 16946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 16956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 16966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 16976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 16986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1699eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 1700eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 17016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1702eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 1703eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 17046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 1706295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 1707d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 17085d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 17095d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 17105d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 17115d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* TrySuccessor = NULL; 17125d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17135d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 1714d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17155d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 17165d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 17175d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 17185d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 1719a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 17205d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17215d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 1722f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 17235d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 1724f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 17255d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 1726a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 17275d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 17285d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 17295d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 17305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 1731a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 1732a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 1733a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 17345d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 17355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 17365d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 17375d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 17385d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 17395d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 1740f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, CatchBlock); 17415d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 1742a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 1743a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 1744f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 1745a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 1746f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 1747a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 17485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 17505d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 17515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 1752f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 1753f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock); 1754f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump TryTerminatedBlock = NewTryTerminatedBlock; 1755f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 17566db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 17575d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 17583fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek Block = addStmt(Terminator->getTryBlock()); 17595d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return Block; 17605d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 17615d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17625d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) { 17635d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 17645d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 17655d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17665d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 17675d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 17685d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* CatchBlock = Block; 17705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 17715d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 17725d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17735d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 17745d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 1775d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17765d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 17775d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17785d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 17795d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 17805d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 17815d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 17825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 17835d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 1784ad5a894df1841698c824381b414630799adc26caTed KremenekCFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C, 1785c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu AddStmtChoice asc) { 1786ad5a894df1841698c824381b414630799adc26caTed Kremenek AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 178721f6d6ea71b89aeae6b9262c8cbdff7f6328e749Zhongxing Xu : AddStmtChoice::AlwaysAdd; 1788c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu autoCreateBlock(); 178921f6d6ea71b89aeae6b9262c8cbdff7f6328e749Zhongxing Xu AppendStmt(Block, C, AddStmtChoice(K)); 1790c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu return VisitChildren(C); 1791c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu} 1792c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu 179319bb356317952445b03ee341c02f6147083c9eeaTed KremenekCFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) { 17946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 179519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek CFGBlock* IBlock = cfg->getIndirectGotoBlock(); 17966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 179719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 179819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 179919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 180019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 18016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 180219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 180319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 1804d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 18064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 180719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 180819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 1809ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, IBlock); 181019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 181119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 181219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 1813befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 1814026473c2175424a039f51ca8949937268721b965Ted Kremenek 18156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 18166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 18176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 18189438252ad2ecae5338df565ca33c6969e4fbfa41Ted KremenekCFGBlock* CFG::createBlock() { 1819026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 1820026473c2175424a039f51ca8949937268721b965Ted Kremenek 1821026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 1822ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 1823ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek new (Mem) CFGBlock(NumBlockIDs++, BlkBVC); 1824ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 1825026473c2175424a039f51ca8949937268721b965Ted Kremenek 1826026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 1827ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 1828ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 1829026473c2175424a039f51ca8949937268721b965Ted Kremenek 1830026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 1831ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 1832026473c2175424a039f51ca8949937268721b965Ted Kremenek} 1833026473c2175424a039f51ca8949937268721b965Ted Kremenek 1834026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 1835026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 1836b978a441c7d8bf59e7fede938e1f3b672573b443Mike StumpCFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C, 1837ad5a894df1841698c824381b414630799adc26caTed Kremenek bool PruneTriviallyFalse, 18384c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdges, bool AddScopes) { 1839fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBuilder Builder; 1840ad5a894df1841698c824381b414630799adc26caTed Kremenek return Builder.buildCFG(D, Statement, C, PruneTriviallyFalse, 1841ad5a894df1841698c824381b414630799adc26caTed Kremenek AddEHEdges, AddScopes); 1842fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 1843fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 184463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 184563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek// CFG: Queries for BlkExprs. 184663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 184763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 184863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremeneknamespace { 184986946745225096243f6969dc745267b78fc211a6Ted Kremenek typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy; 185063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 185163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 18528a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenekstatic void FindSubExprAssignments(Stmt *S, 18538a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek llvm::SmallPtrSet<Expr*,50>& Set) { 18548a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!S) 185533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return; 18566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18578a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) { 1858ad5a894df1841698c824381b414630799adc26caTed Kremenek Stmt *child = *I; 18598a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!child) 18608a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek continue; 1861ad5a894df1841698c824381b414630799adc26caTed Kremenek 18628a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(child)) 186333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (B->isAssignmentOp()) Set.insert(B); 18646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18658a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek FindSubExprAssignments(child, Set); 186633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 186733d4aab80f31bd06257526fe2883ea920529456bTed Kremenek} 186833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek 186963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekstatic BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { 187063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = new BlkExprMapTy(); 18716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Look for assignments that are used as subexpressions. These are the only 18736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // assignments that we want to *possibly* register as a block-level 18746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression. Basically, if an assignment occurs both in a subexpression and 18756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // at the block-level, it is a block-level expression. 187633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek llvm::SmallPtrSet<Expr*,50> SubExprAssignments; 18776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 187863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) 1879ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 188033d4aab80f31bd06257526fe2883ea920529456bTed Kremenek FindSubExprAssignments(*BI, SubExprAssignments); 188186946745225096243f6969dc745267b78fc211a6Ted Kremenek 1882411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { 18836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Iterate over the statements again on identify the Expr* and Stmt* at the 18856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block-level that are block-level expressions. 1886411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 1887ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 1888411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (Expr* Exp = dyn_cast<Expr>(*BI)) { 18896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1890411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { 189133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek // Assignment expressions that are not nested within another 18926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression are really "statements" whose value is never used by 18936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // another expression. 1894411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) 189533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek continue; 18966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (const StmtExpr* Terminator = dyn_cast<StmtExpr>(Exp)) { 18976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Special handling for statement expressions. The last statement in 18986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the statement expression is also a block-level expr. 1899411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek const CompoundStmt* C = Terminator->getSubStmt(); 190086946745225096243f6969dc745267b78fc211a6Ted Kremenek if (!C->body_empty()) { 190133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 190286946745225096243f6969dc745267b78fc211a6Ted Kremenek (*M)[C->body_back()] = x; 190386946745225096243f6969dc745267b78fc211a6Ted Kremenek } 190486946745225096243f6969dc745267b78fc211a6Ted Kremenek } 1905e2dcd783a04f654c50bd8b13fb08a440afbd67e7Ted Kremenek 190633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 1907411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek (*M)[Exp] = x; 190833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 19096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1910411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek // Look at terminators. The condition is a block-level expression. 19116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1912ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Stmt* S = (*I)->getTerminatorCondition(); 19136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1914390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek if (S && M->find(S) == M->end()) { 1915411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek unsigned x = M->size(); 1916390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek (*M)[S] = x; 1917411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 1918411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 19196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 192086946745225096243f6969dc745267b78fc211a6Ted Kremenek return M; 192163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 192263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 192386946745225096243f6969dc745267b78fc211a6Ted KremenekCFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) { 192486946745225096243f6969dc745267b78fc211a6Ted Kremenek assert(S != NULL); 192563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } 19266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 192763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap); 192886946745225096243f6969dc745267b78fc211a6Ted Kremenek BlkExprMapTy::iterator I = M->find(S); 19293fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); 193063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 19317dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 193263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekunsigned CFG::getNumBlkExprs() { 193363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap)) 193463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return M->size(); 193563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek else { 193663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek // We assume callers interested in the number of BlkExprs will want 193763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek // the map constructed if it doesn't already exist. 193863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMap = (void*) PopulateBlkExprMap(*this); 193963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size(); 194063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek } 194163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 194263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 1943274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 1944ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 1945ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 1946ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 1947ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 1948be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 1949ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 1950ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (F.IgnoreDefaultsWithCoveredEnums) { 1951ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 1952ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 1953ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 1954be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator())) { 1955ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 1956be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const Stmt *L = To->getLabel(); 1957be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 1958be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek return true; 1959ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 1960ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 1961ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 1962ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 1963ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 1964ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 1965ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 1966ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 1967274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek// Cleanup: CFG dstor. 1968274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 1969274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek 197063f5887f316fb52d243fcbb3631c039de6c4b993Ted KremenekCFG::~CFG() { 197163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap); 197263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 19736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19747dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 19757dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 19767dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 19777dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 197842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 19792bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 1980ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 198142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 198242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 198342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek signed CurrentBlock; 198442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned CurrentStmt; 1985e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 198642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 19871c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 1988e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 1989e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner : CurrentBlock(0), CurrentStmt(0), LangOpts(LO) { 199042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 199142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 1992ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 199342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek BI != BEnd; ++BI, ++j ) 1994ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek StmtMap[*BI] = std::make_pair((*I)->getBlockID(),j); 199542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 1996fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 19976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 199842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 19996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2000e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 200142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek void setBlockID(signed i) { CurrentBlock = i; } 200242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek void setStmtID(unsigned i) { CurrentStmt = i; } 20036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2004a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek virtual bool handledStmt(Stmt* Terminator, llvm::raw_ostream& OS) { 20056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2006411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek StmtMapTy::iterator I = StmtMap.find(Terminator); 2007fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 200842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 200942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 20106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock 20123fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek && I->second.second == CurrentStmt) { 201342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 20143fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 20156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20163fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 20171c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 201842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 201942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 2020e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 2021e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 2022e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 2023e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 2024ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 20256fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 20266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2027a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_ostream& OS; 202842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 2029d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 2030d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 2031d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper, 2032e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 2033d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 20346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2035d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitIfStmt(IfStmt* I) { 2036d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 2037d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 2038d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 20396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2040d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 20416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump void VisitStmt(Stmt* Terminator) { 20426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 20436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 20446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2045d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitForStmt(ForStmt* F) { 2046d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 20473fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 20483fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 2049535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 20503fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = F->getCond()) 20513fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 2052535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 20533fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 20543fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 2055a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 2056d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 20576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2058d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitWhileStmt(WhileStmt* W) { 2059d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 20603fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = W->getCond()) 20613fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 2062d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 20636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2064d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitDoStmt(DoStmt* D) { 2065d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 20663fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = D->getCond()) 20673fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 20689da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 20696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2070411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek void VisitSwitchStmt(SwitchStmt* Terminator) { 20719da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 2072d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 20739da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 20746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20755d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump void VisitCXXTryStmt(CXXTryStmt* CS) { 20765d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 20775d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 20785d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2079805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitConditionalOperator(ConditionalOperator* C) { 2080d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 20816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 2082805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 20836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2084aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek void VisitChooseExpr(ChooseExpr* C) { 2085aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 2086d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 2087a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 2088aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 20896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20901c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt* I) { 20911c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 2092d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 20931c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 20946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2095805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 2096805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 2097805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 2098805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 2099805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 21006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2101d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 21026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2103805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 21042de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 2105a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 2106805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 21072de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 2108a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 2109805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 2110805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 2111805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek assert(false && "Invalid logical operator."); 21126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 2113805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 21146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21150b1d9b7557437176f9cea1283bfac2510812beceTed Kremenek void VisitExpr(Expr* E) { 2116d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 21176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 2118d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 2119e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 2120e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 21216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2122e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnerstatic void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, 2123079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 2124079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 2125079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (E.asStartScope()) { 2126079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump OS << "start scope\n"; 2127079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return; 2128079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 2129079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (E.asEndScope()) { 2130079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump OS << "end scope\n"; 2131079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return; 2132079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 2133079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 21344e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek Stmt *S = E; 21354e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 21361c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek if (Helper) { 21371c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek // special printing for statement-expressions. 21384e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) { 21391c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek CompoundStmt* Sub = SE->getSubStmt(); 21406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21411c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek if (Sub->child_begin() != Sub->child_end()) { 214260266e8a9a4cd941af5e0006a18377dc03f0421bTed Kremenek OS << "({ ... ; "; 21437a9d9d71fa208dc23fd67d03ce052d4ef60a8d04Ted Kremenek Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 214460266e8a9a4cd941af5e0006a18377dc03f0421bTed Kremenek OS << " })\n"; 21451c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return; 21461c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 21471c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 21486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21491c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek // special printing for comma expressions. 21504e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 21512de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_Comma) { 21521c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "... , "; 21531c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek Helper->handledStmt(B->getRHS(),OS); 21541c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << '\n'; 21551c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return; 21566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 21576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 21581c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 21596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21604e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 21614e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 21624e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek if (isa<CXXOperatorCallExpr>(S)) { 21634e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek OS << " (OperatorCall)"; 21644e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek } 21654e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek else if (isa<CXXBindTemporaryExpr>(S)) { 21664e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek OS << " (BindTemporary)"; 21674e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek } 21684e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 21696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21701c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek // Expressions need a newline. 21714e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek if (isa<Expr>(S)) 21724e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek OS << '\n'; 21731c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek} 21746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2175e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnerstatic void print_block(llvm::raw_ostream& OS, const CFG* cfg, 2176e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const CFGBlock& B, 2177e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper* Helper, bool print_edges) { 21786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 217942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(B.getBlockID()); 21806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21817dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 21826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << "\n [ B" << B.getBlockID(); 21836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 218442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 218542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (ENTRY) ]\n"; 218642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 218742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (EXIT) ]\n"; 218842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 21897dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OS << " (INDIRECT GOTO DISPATCH) ]\n"; 219042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 219142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " ]\n"; 21926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21939cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 2194079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) { 219542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 219642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 219742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 21986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2199079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (LabelStmt* L = dyn_cast<LabelStmt>(Label)) 22009cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 2201079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) { 22029cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 2203e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 2204e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 22059cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 22069cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 2207e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 2208e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 22099cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 2210079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 22119cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 2212079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 22135d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 2214a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 2215a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 2216a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 2217a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 2218a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 22195d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 22205d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22215d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 222242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek assert(false && "Invalid label statement in CFGBlock."); 22236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22249cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 22259cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 22266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2227fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 2228fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 22296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 223042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 223142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 22326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22339cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 223442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 223542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 22366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2237a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 22386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 223942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 224042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 22416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22421c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek print_stmt(OS,Helper,*I); 2243fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 22446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22459cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 224642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 224742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 224842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 22496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22509cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " T: "; 22516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 225242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 22536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2254e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, Helper, 2255e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 225642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek TPrinter.Visit(const_cast<Stmt*>(B.getTerminator())); 2257a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 2258fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 22596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22609cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 22619cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 226242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Predecessors (" << B.pred_size() << "):"; 22639cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek unsigned i = 0; 226442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 226542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 226642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 22676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 226842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) == 0) 22699cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 22706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22719cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " B" << (*I)->getBlockID(); 22729cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 22736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22749cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 22756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22769cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 227742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Successors (" << B.succ_size() << "):"; 22789cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek i = 0; 227942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 228042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 228142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 22826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 228342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) % 10 == 0) 22849cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 228542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 2286e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump if (*I) 2287e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " B" << (*I)->getBlockID(); 2288e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump else 2289e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " NULL"; 2290fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 22916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22929cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 2293fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 22946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 229542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 229642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 229742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 2298e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); } 229942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 230042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 2301e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const { 2302e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 23036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 230442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 230542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getEntry(), &Helper, true); 23066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 230742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 230842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 230942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 2310ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 231142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 23126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2313ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek print_block(OS, this, **I, &Helper, true); 231442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 23156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 231642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 231742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getExit(), &Helper, true); 2318d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 23196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 232042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 232142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 2322e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const { 2323e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner print(llvm::errs(), cfg, LO); 2324e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 232542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 232642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 232742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 2328e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg, 2329e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LO) const { 2330e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 233142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, cfg, *this, &Helper, true); 2332026473c2175424a039f51ca8949937268721b965Ted Kremenek} 23337dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 2334a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 2335e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::printTerminator(llvm::raw_ostream &OS, 23366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 2337e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 2338a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek TPrinter.Visit(const_cast<Stmt*>(getTerminator())); 2339a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 2340a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 2341390e48b15ad93f85bfd1e33b9992c198fa0db475Ted KremenekStmt* CFGBlock::getTerminatorCondition() { 23426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2343411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 2344411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 23456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2346411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek Expr* E = NULL; 23476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2348411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 2349411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 2350411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2352411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 2353411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 2354411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2356411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 2357411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 2358411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2360411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 2361411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 2362411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2364411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 2365411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 2366411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2368411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 2369411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 2370411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2372411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 2373411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 2374411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2376411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 2377411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 2378411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2380411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 2381411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 2382411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 23836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2384411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 2385411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 2386390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 23876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2388390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 23896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 2390411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 23916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2392411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 2393411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 2394411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 23959c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenekbool CFGBlock::hasBinaryBranchTerminator() const { 23966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23979c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek if (!Terminator) 23989c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return false; 23996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24009c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek Expr* E = NULL; 24016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24029c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek switch (Terminator->getStmtClass()) { 24039c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek default: 24049c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return false; 24056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump case Stmt::ForStmtClass: 24079c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::WhileStmtClass: 24089c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::DoStmtClass: 24099c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::IfStmtClass: 24109c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::ChooseExprClass: 24119c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::ConditionalOperatorClass: 24129c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::BinaryOperatorClass: 24136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return true; 24149c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek } 24156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24169c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return E ? E->IgnoreParens() : NULL; 24179c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek} 24189c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek 2419a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 24207dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 24217dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 24227dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 24237dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 242442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 242542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 24266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 242742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 242842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 2429e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 243042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 2431e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 243242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 243342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 243442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 243542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 243642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 243742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 24387dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 24397dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 24407dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 2441006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 2442006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 2443006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 2444006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) { 24457dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 2446bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 2447a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 2448a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 244942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(Out,Graph, *Node, GraphHelper, false); 2450a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 24517dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 24527dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 24537dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 24547dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 24557dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 24567dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 24577dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 24587dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 24597dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 24606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24617dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 2462bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 2463bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 2464bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 24657dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 24667dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 24677dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 2468