CFG.cpp revision e1667190dff025936a21e5eb43889ac93b570468
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 55f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope - Node in tree of local scopes created for C++ implicit 56f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// destructor calls generation. It contains list of automatic variables 57f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// declared in the scope and link to position in previous scope this scope 58f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// began in. 59f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 60f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// The process of creating local scopes is as follows: 61f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null), 62f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Before processing statements in scope (e.g. CompoundStmt) create 63f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope object using CFGBuilder::ScopePos as link to previous scope 64f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// and set CFGBuilder::ScopePos to the end of new scope, 6535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points 66f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// at this VarDecl, 67f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every normal (without jump) end of scope add to CFGBlock destructors 68f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// for objects in the current scope, 69f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every jump add to CFGBlock destructors for objects 70f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// between CFGBuilder::ScopePos and local scope position saved for jump 71f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// target. Thanks to C++ restrictions on goto jumps we can be sure that 72f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// jump target position will be on the path to root from CFGBuilder::ScopePos 73f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// (adding any variable that doesn't need constructor to be called to 74f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope can break this assumption), 75f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 76f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiclass LocalScope { 77f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 78f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef llvm::SmallVector<VarDecl*, 4> AutomaticVarsTy; 79f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 80f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// const_iterator - Iterates local scope backwards and jumps to previous 8135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski /// scope on reaching the beginning of currently iterated scope. 82f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski class const_iterator { 83f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const LocalScope* Scope; 84f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 85f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// VarIter is guaranteed to be greater then 0 for every valid iterator. 86f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Invalid iterator (with null Scope) has VarIter equal to 0. 87f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski unsigned VarIter; 88f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 89f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski public: 90f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create invalid iterator. Dereferencing invalid iterator is not allowed. 91f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Incrementing invalid iterator is allowed and will result in invalid 92f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// iterator. 93f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator() 94f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(NULL), VarIter(0) {} 95f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 96f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create valid iterator. In case when S.Prev is an invalid iterator and 97f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// I is equal to 0, this will create invalid iterator. 98f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator(const LocalScope& S, unsigned I) 99f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(&S), VarIter(I) { 100f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Iterator to "end" of scope is not allowed. Handle it by going up 101f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // in scopes tree possibly up to invalid iterator in the root. 102f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0 && Scope) 103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 104f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 105f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 106f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski VarDecl* const* operator->() const { 107f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (Scope && "Dereferencing invalid iterator is not allowed"); 108f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return &Scope->Vars[VarIter - 1]; 110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski VarDecl* operator*() const { 112f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this->operator->(); 113f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 115f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator& operator++() { 116f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (!Scope) 117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski --VarIter; 121f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0) 122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 124f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 12535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator operator++(int) { 12635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator P = *this; 12735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski ++*this; 12835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return P; 12935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 130f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 131f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski bool operator==(const const_iterator& rhs) const { 132f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return Scope == rhs.Scope && VarIter == rhs.VarIter; 133f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 134f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski bool operator!=(const const_iterator& rhs) const { 135f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return !(*this == rhs); 136f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 13735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 13835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski operator bool() const { 13935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return *this != const_iterator(); 14035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 14135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 14235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int distance(const_iterator L); 143f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski }; 144f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 145f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski friend class const_iterator; 146f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 147f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiprivate: 148f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Automatic variables in order of declaration. 149f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AutomaticVarsTy Vars; 150f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Iterator to variable in previous scope that was declared just before 151f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// begin of this scope. 152f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator Prev; 153f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 154f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 155f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Constructs empty scope linked to previous scope in specified place. 156f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope(const_iterator P) 157f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Vars() 158f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski , Prev(P) {} 159f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 160f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Begin of scope in direction of CFG building (backwards). 161f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator begin() const { return const_iterator(*this, Vars.size()); } 16235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 16335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski void addVar(VarDecl* VD) { 16435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski Vars.push_back(VD); 16535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 166f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 167f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 16835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// distance - Calculates distance from this to L. L must be reachable from this 16935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. 17035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// number of scopes between this and L. 17135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderskiint LocalScope::const_iterator::distance(LocalScope::const_iterator L) { 17235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int D = 0; 17335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator F = *this; 17435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski while (F.Scope != L.Scope) { 17535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski assert (F != const_iterator() 17635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski && "L iterator is not reachable from F iterator."); 17735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter; 17835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski F = F.Scope->Prev; 17935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 18035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter - L.VarIter; 18135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return D; 18235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski} 18335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 18435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// BlockScopePosPair - Structure for specifying position in CFG during its 18535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// build process. It consists of CFGBlock that specifies position in CFG graph 18635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// and LocalScope::const_iterator that specifies position in LocalScope graph. 187f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskistruct BlockScopePosPair { 188f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BlockScopePosPair() {} 189f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BlockScopePosPair(CFGBlock* B, LocalScope::const_iterator S) 190f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Block(B), ScopePos(S) {} 191f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 192f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski CFGBlock* Block; 193f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 194f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 195f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 196a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 197fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 198fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 199fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 200fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 201fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 202fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 203fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 204fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 2056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 2066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 2076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 2086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 209c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 210ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 211f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpTarget; 212f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpSource; 213f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 214e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 2150ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek llvm::OwningPtr<CFG> cfg; 216ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 217fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBlock* Block; 218fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBlock* Succ; 219f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget ContinueJumpTarget; 220f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget BreakJumpTarget; 221b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek CFGBlock* SwitchTerminatedBlock; 222eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek CFGBlock* DefaultCaseBlock; 2235d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* TryTerminatedBlock; 2246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 225f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Current position in local scope. 226f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 227f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 228f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // LabelMap records the mapping from Label expressions to their jump targets. 229f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef llvm::DenseMap<LabelStmt*, JumpTarget> LabelMapTy; 2300cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 2316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 2336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 234f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef std::vector<JumpSource> BackpatchBlocksTy; 2350cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 2366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 23819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek typedef llvm::SmallPtrSet<LabelStmt*,5> LabelSetTy; 23919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 2406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24149b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu bool badCFG; 24249b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu CFG::BuildOptions BuildOpts; 24349b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu 2446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 245ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG 246ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Block(NULL), Succ(NULL), 2475d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 24849b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu TryTerminatedBlock(NULL), badCFG(false) {} 2496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 250d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 251ad5a894df1841698c824381b414630799adc26caTed Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, 2526c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek CFG::BuildOptions BO); 2536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 2554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 256852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 257852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 258852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBlockExpr(BlockExpr* E, AddStmtChoice asc); 2594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 2607ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 2617ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 2627ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 263c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc); 264852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 2654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 266852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 2673fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 2687ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitConditionalOperator(ConditionalOperator *C, AddStmtChoice asc); 2693fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 2704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 2714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclSubExpr(Decl* D); 2723fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 2733fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 2743fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 2754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt* G); 2764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 2774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 2784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 279115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 2804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 2814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 2824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 2834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 2844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 2854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitReturnStmt(ReturnStmt* R); 286852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc); 287852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 2884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 2894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 2904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 291852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 292852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 2934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitChildren(Stmt* S); 294cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 295274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 296274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek CFGBlock* NYS() { 2974102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 2984102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 2994102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 3006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 3024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 303d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 304df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 305df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 306852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 30782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski CFGBlock *addInitializer(CXXBaseOrMemberInitializer *I); 3086a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 3096a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu LocalScope::const_iterator E, Stmt* S); 3107c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 311239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 312239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 313239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 314239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 31502acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu void addLocalScopeForStmt(Stmt* S); 316239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* addLocalScopeForDeclStmt(DeclStmt* DS, LocalScope* Scope = NULL); 317239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* addLocalScopeForVarDecl(VarDecl* VD, LocalScope* Scope = NULL); 318239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 319239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski void addLocalScopeAndDtors(Stmt* S); 320ad5a894df1841698c824381b414630799adc26caTed Kremenek 321239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 322852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek void AppendStmt(CFGBlock *B, Stmt *S, 323852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc = AddStmtChoice::AlwaysAdd) { 324852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue()); 325ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 32682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski void appendInitializer(CFGBlock *B, CXXBaseOrMemberInitializer *I) { 32782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 32882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 3297c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 3307c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 3317c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 3327c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 3337c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 3347c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 335ad5a894df1841698c824381b414630799adc26caTed Kremenek 33653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I, 33753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S); 33853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void appendAutomaticObjDtors(CFGBlock* Blk, LocalScope::const_iterator B, 33953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator E, Stmt* S); 34053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk, 34153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 34253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 343ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek void AddSuccessor(CFGBlock *B, CFGBlock *S) { 344ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 345ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 3461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 347fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// TryResult - a class representing a variant over the values 348fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// 'true', 'false', or 'unknown'. This is returned by TryEvaluateBool, 349fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// and is used by the CFGBuilder to decide if a branch condition 350fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// can be decided up front during CFG construction. 351941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek class TryResult { 352941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek int X; 353941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek public: 354941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 355941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult() : X(-1) {} 3561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 357941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isTrue() const { return X == 1; } 358941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isFalse() const { return X == 0; } 359941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isKnown() const { return X >= 0; } 360941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek void negate() { 361941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(isKnown()); 362941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek X ^= 0x1; 363941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek } 364941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek }; 3651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36600998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// TryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 36700998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 368941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult TryEvaluateBool(Expr *S) { 3696c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 370ad5a894df1841698c824381b414630799adc26caTed Kremenek return TryResult(); 371ad5a894df1841698c824381b414630799adc26caTed Kremenek 37200998a068e50945118f334c98af05ed44d7c22a6Mike Stump Expr::EvalResult Result; 3739983cc110422a2e976191a0ce6ac4f1d7b634cc0Douglas Gregor if (!S->isTypeDependent() && !S->isValueDependent() && 3749983cc110422a2e976191a0ce6ac4f1d7b634cc0Douglas Gregor S->Evaluate(Result, *Context) && Result.Val.isInt()) 375fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek return Result.Val.getInt().getBoolValue(); 376941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek 377941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return TryResult(); 37800998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 379d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 381898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 382898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 383610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenekstatic VariableArrayType* FindVA(Type* t) { 384610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek while (ArrayType* vt = dyn_cast<ArrayType>(t)) { 385610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt)) 386610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 387610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 3886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 389610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 390610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 3916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 392610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 393610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 3946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 3966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 3976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 3986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 3996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 400b978a441c7d8bf59e7fede938e1f3b672573b443Mike StumpCFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, 4016c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek CFG::BuildOptions BO) { 402ad5a894df1841698c824381b414630799adc26caTed Kremenek 403e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump Context = C; 4040ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 4054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 4064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 407d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 4086c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek BuildOpts = BO; 4096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 4116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 4126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 41349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 414ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 41549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 4166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4177c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 4187c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 4197c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 4207c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 421d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 4221b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 4231b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 4241b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 4251b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 4261b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 42782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 428b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 42982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 43082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 43182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 43282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 43382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 43482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 435b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 4366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 43782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 43882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 43982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 4401b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 4411b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 4421b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 4431b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 444c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 445f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski CFGBlock* B = I->Block; 4461b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu GotoStmt* G = cast<GotoStmt>(B->getTerminator()); 4471b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 4486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4491b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 4501b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 4511b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 452d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 453f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 454fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski prependAutomaticObjDtorsWithTerminator(B, I->ScopePos, JT.ScopePos); 455f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(B, JT.Block); 4561b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 4576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4581b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 4591b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (CFGBlock* B = cfg->getIndirectGotoBlock()) 4601b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 4611b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 4621b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 4631b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 4641b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 4651b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 4661b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 4671b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 4681b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 4691b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 470f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(B, LI->second.Block); 471c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 4726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 474322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 4756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4761b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 477d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 4786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 479d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 480d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 4816d9828c82c9321f042ab416fd2ffaa3034347d45Mike StumpCFGBlock* CFGBuilder::createBlock(bool add_successor) { 4829438252ad2ecae5338df565ca33c6969e4fbfa41Ted Kremenek CFGBlock* B = cfg->createBlock(); 4834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 484ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(B, Succ); 485d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 486d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 4876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 48882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 48982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin SwiderskiCFGBlock *CFGBuilder::addInitializer(CXXBaseOrMemberInitializer *I) { 49082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 49182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 49282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 49382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski autoCreateBlock(); 49482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski appendInitializer(Block, I); 49582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 49682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (Expr *Init = I->getInit()) { 49782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski AddStmtChoice::Kind K = AddStmtChoice::NotAlwaysAdd; 49882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (FieldDecl *FD = I->getMember()) 49982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (FD->getType()->isReferenceType()) 50082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski K = AddStmtChoice::AsLValueNotAlwaysAdd; 50182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 50282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Visit(Init, AddStmtChoice(K)); 50382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 50482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 50582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 50682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 50782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 508239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 509239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 510239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 5116a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 5126a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu LocalScope::const_iterator E, Stmt* S) { 513239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 5146a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 5156a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 516239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 5176a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 518239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 519239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski autoCreateBlock(); 520239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski appendAutomaticObjDtors(Block, B, E, S); 521239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 522239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 5237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 5247c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 5257c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 5267c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 5277c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 5287c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 5297c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 5307c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 5317c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 5327c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 5337c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 5347c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 5357c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 5367c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 5377c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5387c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5397c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 5407c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 5417c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 5427c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 5437c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!BI->isVirtual()) { 5447c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 5457c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 5467c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 5477c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, BI); 5487c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5497c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5507c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5517c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 5527c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 5537c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 5547c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 5557c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXRecordDecl *CD = FI->getType()->getAsCXXRecordDecl()) 5567c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 5577c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 5587c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendMemberDtor(Block, *FI); 5597c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5607c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5617c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 5627c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 563239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 564239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 565239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 566239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 567239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = cfg->getAllocator().Allocate<LocalScope>(); 568239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski new (Scope) LocalScope(ScopePos); 569239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 570239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 571239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 572239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 573239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 57402acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 57502acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xuvoid CFGBuilder::addLocalScopeForStmt(Stmt* S) { 576239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 57702acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 57802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 57902acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 580239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 581239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 582239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (CompoundStmt* CS = dyn_cast<CompoundStmt>(S)) { 583239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 584239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 585239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Stmt* SI = *BI; 586239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (LabelStmt* LS = dyn_cast<LabelStmt>(SI)) 587239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski SI = LS->getSubStmt(); 588239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (DeclStmt* DS = dyn_cast<DeclStmt>(SI)) 589239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 590239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 59102acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 592239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 593239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 594239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 595239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 596239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (LabelStmt* LS = dyn_cast<LabelStmt>(S)) 597239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski S = LS->getSubStmt(); 598239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) 599b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 600239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 601239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 602239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 603239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 604239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt* DS, 605b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 606239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 607239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 608239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 609239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 610239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 611239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (VarDecl* VD = dyn_cast<VarDecl>(*DI)) 612239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 613239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 614239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 615239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 616239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 617239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 618239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 619239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 620239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl* VD, 621b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 622239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 623239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 624239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 625239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 626239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 627239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 628239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 629239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 630239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 631239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 632239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 633239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 634239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 635239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 636239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (const ReferenceType* RT = QT.getTypePtr()->getAs<ReferenceType>()) { 637239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QT = RT->getPointeeType(); 638239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!QT.isConstQualified()) 639239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 640239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!VD->getInit() || !VD->getInit()->Classify(*Context).isRValue()) 641239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 642239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 643239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 644239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 6454e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 6464e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu if (const CXXRecordDecl* CD = QT->getAsCXXRecordDecl()) 6474e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu if (!CD->hasTrivialDestructor()) { 6484e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 6494e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 6504e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 6514e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 6524e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 653239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 654239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 655239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 656239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 657239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 658239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderskivoid CFGBuilder::addLocalScopeAndDtors(Stmt* S) { 659239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 660239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 661239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 662239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 66302acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 664239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 665239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 666239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 66753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// insertAutomaticObjDtors - Insert destructor CFGElements for variables with 66853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// automatic storage duration to CFGBlock's elements vector. Insertion will be 66953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// performed in place specified with iterator. 67053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I, 67153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) { 67253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski BumpVectorContext& C = cfg->getBumpVectorContext(); 67353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski I = Blk->beginAutomaticObjDtorsInsert(I, B.distance(E), C); 67453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski while (B != E) 67553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski I = Blk->insertAutomaticObjDtor(I, *B++, S); 67653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 67753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 67853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// appendAutomaticObjDtors - Append destructor CFGElements for variables with 67953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// automatic storage duration to CFGBlock's elements vector. Elements will be 68053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// appended to physical end of the vector which happens to be logical 68153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// beginning. 68253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::appendAutomaticObjDtors(CFGBlock* Blk, 68353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) { 68453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski insertAutomaticObjDtors(Blk, Blk->begin(), B, E, S); 68553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 68653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 68753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 68853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 68953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 69053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 69153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 69253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk, 69353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 69453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski insertAutomaticObjDtors(Blk, Blk->end(), B, E, Blk->getTerminator()); 69553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 69653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 6974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 6986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 6996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 700852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 7014f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenektryAgain: 702f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 703f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 704f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 705f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 7064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 7074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 708852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 7094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 7104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 711852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 7121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 714852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 7151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 717852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBlockExpr(cast<BlockExpr>(S), asc); 7184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 7194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 7204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 7211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 723a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 724852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 7251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 7274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 7284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 7294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 730852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 7311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 7334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 7341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 736852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 7371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 7394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 7401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 741021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 742021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 743021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 74447e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek case Stmt::CXXExprWithTemporariesClass: { 74547e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek // FIXME: Handle temporaries. For now, just visit the subexpression 74647e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek // so we don't artificially create extra blocks. 747a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek return Visit(cast<CXXExprWithTemporaries>(S)->getSubExpr(), asc); 74847e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek } 74947e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 750c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu case Stmt::CXXMemberCallExprClass: 751c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc); 752c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu 753021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 754021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 755ad5a894df1841698c824381b414630799adc26caTed Kremenek 756021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 757021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 758ad5a894df1841698c824381b414630799adc26caTed Kremenek 7594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 7604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 7611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 7634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 7641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 7664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 7671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 7694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 7701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 7724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 7731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 7754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 7761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 7784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 7791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 7814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 7821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 783115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 784115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 785115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 7864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 7871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 7881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 7904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 7911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 7934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 7941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 7964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 7971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 7994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 8001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ParenExprClass: 8024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek S = cast<ParenExpr>(S)->getSubExpr(); 8031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump goto tryAgain; 8041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::NullStmtClass: 8064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 8071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 8094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SizeOfAlignOfExprClass: 812852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), asc); 8131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 815852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 8161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 8184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 8191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 8214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 8224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 8234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 8241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 825852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 826852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 8274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 828852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, S, asc); 8296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 8324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 8336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 8344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 8354f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) { 8364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = Block; 8374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (Stmt::child_iterator I = Terminator->child_begin(), 8384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek E = Terminator->child_end(); I != E; ++I) { 8394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (*I) B = Visit(*I); 8406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 8414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return B; 8424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 8431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 844852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 845852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 8464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 8476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 848852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 8494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 850852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, A, asc); 8516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 8526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 8534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 8544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 8551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 856852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 857852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 8584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (B->isLogicalOp()) { // && or || 8594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 860852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, B, asc); 8611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 862d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 8634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 8641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the LHS 8664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* LHSBlock = createBlock(false); 8674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LHSBlock->setTerminator(B); 8681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the RHS 8704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = ConfluenceBlock; 8714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = NULL; 8724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* RHSBlock = addStmt(B->getRHS()); 873862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 874862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek if (RHSBlock) { 875d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 876862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek return 0; 877862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 878862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek else { 879862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // Create an empty block for cases where the RHS doesn't require 880862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // any explicit statements in the CFG. 881862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek RHSBlock = createBlock(); 882862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 8831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 88400998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 885941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal = TryEvaluateBool(B->getLHS()); 8862de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr)) 887941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek KnownVal.negate(); 88800998a068e50945118f334c98af05ed44d7c22a6Mike Stump 8894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now link the LHSBlock with RHSBlock. 8902de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LOr) { 891ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 892ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 8931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else { 8942de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LAnd); 895ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 896ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 89719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 8981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Generate the blocks for evaluating the LHS. 9004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = LHSBlock; 9014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 9021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 9032de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall else if (B->getOpcode() == BO_Comma) { // , 9046dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 905852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, B, asc); 9064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 9074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 9086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 909fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu else if (B->isAssignmentOp()) { 910fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (asc.alwaysAdd()) { 911fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 912fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu AppendStmt(Block, B, asc); 913fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 914ad5a894df1841698c824381b414630799adc26caTed Kremenek 915e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski Visit(B->getLHS(), AddStmtChoice::AsLValueNotAlwaysAdd); 916e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 917fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 9181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 919e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski if (asc.alwaysAdd()) { 920e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 921e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski AppendStmt(Block, B, asc); 922e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 923e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 924e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski Visit(B->getRHS()); 925e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getLHS()); 9264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 9276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 928852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { 929852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 930721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 931852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, E, asc); 932721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 933721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 9344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 935cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 9364f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 9374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 9384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 939d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 940d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 9411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 9434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 9444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 9451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 9474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 948f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (BreakJumpTarget.Block) { 949fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, BreakJumpTarget.ScopePos, B); 950f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(Block, BreakJumpTarget.Block); 951f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 9524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 9531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 9564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 9571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9584c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stumpstatic bool CanThrow(Expr *E) { 9594c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 9604c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 9614c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 9624c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 9634c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 964ad5a894df1841698c824381b414630799adc26caTed Kremenek 9654c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 9664c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 9674c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 9684c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Proto->hasEmptyExceptionSpec()) 9694c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 9704c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 9714c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 9724c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 9734c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 974852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 9754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If this is a call to a no-return function, this stops the block here. 9762455636163fdd18581d7fdae816433f886d88213Mike Stump bool NoReturn = false; 977264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) { 9782455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 9792455636163fdd18581d7fdae816433f886d88213Mike Stump } 9802455636163fdd18581d7fdae816433f886d88213Mike Stump 9814c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 982079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 983079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 984079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Context->getLangOptions().Exceptions) { 9856c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 9864c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 987079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 988079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 989079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 9902455636163fdd18581d7fdae816433f886d88213Mike Stump if (FD->hasAttr<NoReturnAttr>()) 9912455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 992079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 9934c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 994079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 9952455636163fdd18581d7fdae816433f886d88213Mike Stump 9964c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (!CanThrow(C->getCallee())) 9974c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 9984c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 999fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (!NoReturn && !AddEHEdge) { 1000fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (asc.asLValue()) 1001fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu return VisitStmt(C, AddStmtChoice::AlwaysAddAsLValue); 1002fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu else 1003fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu return VisitStmt(C, AddStmtChoice::AlwaysAdd); 1004fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 10051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1006079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1007079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1008d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1009079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1010079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 10111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1012079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Block = createBlock(!NoReturn); 1013852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, C, asc); 10142455636163fdd18581d7fdae816433f886d88213Mike Stump 1015079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (NoReturn) { 1016079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Wire this to the exit block directly. 1017079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, &cfg->getExit()); 1018079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 10194c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1020079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1021079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 1022079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, TryTerminatedBlock); 1023079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 1024079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, &cfg->getExit()); 1025079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 10261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10272455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1028d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1029d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1030852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1031852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 10323fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 1033852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, C, asc); 1034d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 10353fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 10361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1037115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 1038115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AlwaysAdd; 1039115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 10403fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 10413fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 1042df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* LHSBlock = Visit(C->getLHS(), asc); 1043d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 10443fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 10451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10463fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 10473fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 1048df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* RHSBlock = Visit(C->getRHS(), asc); 1049d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 10503fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 10511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10523fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 105300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1054941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(C->getCond()); 1055ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 1056ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 10573fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 10581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 10593fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10621eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { 1063fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 10641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CFGBlock* LastBlock = Block; 10654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 10674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1068334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1069334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1070334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1071334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 10721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1073e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1074e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 10751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1076079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 10774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 10784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1080852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, 1081852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 1082f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1083f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 1084f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 1085852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, C, asc); 1086d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1087f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 10881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1089115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 1090115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AlwaysAdd; 1091115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1092f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1093f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1094f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1095f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1096f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1097f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1098f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek CFGBlock* LHSBlock = NULL; 1099f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek if (C->getLHS()) { 1100df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu LHSBlock = Visit(C->getLHS(), asc); 1101d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1102f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1103f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1104f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 11051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1106f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1107f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1108df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* RHSBlock = Visit(C->getRHS(), asc); 1109d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1110f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 11111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1112f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1113f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 11141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111500998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1116941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(C->getCond()); 1117e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump if (LHSBlock) { 1118ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 1119e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } else { 1120941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek if (KnownVal.isFalse()) { 1121e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // If we know the condition is false, add NULL as the successor for 1122e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // the block containing the condition. In this case, the confluence 1123e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // block will have just one predecessor. 1124ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, 0); 1125941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(ConfluenceBlock->pred_size() == 1); 1126e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } else { 1127e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // If we have no LHS expression, add the ConfluenceBlock as a direct 1128e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // successor for the block containing the condition. Moreover, we need to 1129e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // reverse the order of the predecessors in the ConfluenceBlock because 1130e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // the RHSBlock will have been added to the succcessors already, and we 1131e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // want the first predecessor to the the block containing the expression 1132e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // for the case when the ternary expression evaluates to true. 1133ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, ConfluenceBlock); 1134941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(ConfluenceBlock->pred_size() == 2); 1135e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump std::reverse(ConfluenceBlock->pred_begin(), 1136e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ConfluenceBlock->pred_end()); 1137e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } 1138f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 11391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1140ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1141f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 1142f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return addStmt(C->getCond()); 1143f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1144f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 11454f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 11464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 11476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (DS->isSingleDecl()) { 1149ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, DS); 11504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclSubExpr(DS->getSingleDecl()); 1151d34066c224f782056c18f154abe04ef590473fd9Ted Kremenek } 11521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 11541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy. 11564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek typedef llvm::SmallVector<Decl*,10> BufTy; 11574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BufTy Buf(DS->decl_begin(), DS->decl_end()); 11581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) { 11604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 11614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 11624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 11631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 11654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 11664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 11674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 11681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 11694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 11701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 1172ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, DSNew); 11734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek B = VisitDeclSubExpr(D); 11744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 11751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 11774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 11804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// initializers in Decls. 11814f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclSubExpr(Decl* D) { 11824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(Block); 1183d34066c224f782056c18f154abe04ef590473fd9Ted Kremenek 11844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VarDecl *VD = dyn_cast<VarDecl>(D); 11851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!VD) 11874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 11901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 11925ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek AddStmtChoice::Kind k = 11935ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek VD->getType()->isReferenceType() ? AddStmtChoice::AsLValueNotAlwaysAdd 11945ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek : AddStmtChoice::NotAlwaysAdd; 11955ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek Visit(Init, AddStmtChoice(k)); 11964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 11971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 11994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); VA != 0; 12004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA = FindVA(VA->getElementType().getTypePtr())) 12014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = addStmt(VA->getSizeExpr()); 12021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1203fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1204fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1205fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1206fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 12074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 1208d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1209fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 1210d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { 12116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 12126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 12136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 12146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 12156c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 12166c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 12176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 121804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 121904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 122004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 122104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 122204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 122304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 122404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (VarDecl* VD = I->getConditionVariable()) { 122504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 122604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 122704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 122804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 122904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 12306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The block we were proccessing is now finished. Make it the successor 12316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 12326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1233d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1234d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12354e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1236c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 12376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1238b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 1239d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ElseBlock = Succ; 12406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1241d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* Else = I->getElse()) { 1242d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 12436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1244d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 12456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1246d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 124704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 124804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 124904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 125004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 125104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 125204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 12534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 12546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1255b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1256b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 12574e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1258d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12594e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 12604e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1261c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 12626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1263b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 1264d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ThenBlock; 1265d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 1266d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Stmt* Then = I->getThen(); 12676db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1268d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 12696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 127004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 127104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 127204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 127304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 127404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 127504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 12764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 12776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1278dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1279dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1280dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1281dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1282dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 1283ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ThenBlock, sv.get()); 12846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1285d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12864e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 12876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 12880cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1289d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 12906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1291d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 12926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1293d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1294d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 12956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 129600998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1297941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult &KnownVal = TryEvaluateBool(I->getCond()); 129800998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1299d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 1300ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 1301ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 13026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 13046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 13056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 130661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek Block = addStmt(I->getCond()); 1307ad5a894df1841698c824381b414630799adc26caTed Kremenek 130861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 130961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 131061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 131161dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 131261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 131361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek AppendStmt(Block, I, AddStmtChoice::AlwaysAdd); 131461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek addStmt(Init); 131561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 131661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1317ad5a894df1841698c824381b414630799adc26caTed Kremenek 131861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek return Block; 1319d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 13206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1322d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) { 13236c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1324d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 13256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 13266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 13276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 13286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1329d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1330d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1331d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 13326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1333d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 1334fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 1335ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, &cfg->getExit()); 13366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 13386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1339852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1340d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 13410cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 1342d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) { 1343d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 13444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 13452677ea871a25aa79f9db360f6ed10584c02267adTed Kremenek CFGBlock* LabelBlock = Block; 13466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 13484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 13496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(LabelMap.find(L) == LabelMap.end() && "label already in map"); 1351f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LabelMap[ L ] = JumpTarget(LabelBlock, ScopePos); 13526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 13546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 13556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 13566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 13579cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1358d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13594e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 13606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1362d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 13636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1364d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1365d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 13666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1367d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1368d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 136931dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 1370d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) { 13716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 13726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 13734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1374d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1375d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 13766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1378d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 13796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1380d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1381d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1382f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1383f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1384f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 1385fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, JT.ScopePos, G); 1386f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(Block, JT.Block); 1387f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1388d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 13896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1390d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1391d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1392d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { 1393d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 13946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 139547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 139647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 139747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 139847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 139947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 140047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 140147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 140247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (Stmt* Init = F->getInit()) 140347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1404f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1405f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 140647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (VarDecl* VD = F->getConditionVariable()) 140747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 140847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 140947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 141047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 141147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1412fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1413fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // 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 14213f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 14223f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 1423f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 142447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 14253f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 14266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 14276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 14286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 142949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 143049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 14316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 143249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 14336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(F); 14346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 14366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 143749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = F->getCond()) { 143849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 143949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 14408f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek assert(Block == EntryConditionBlock || 14418f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek (Block == 0 && EntryConditionBlock == Succ)); 144258b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek 144358b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // If this block contains a condition variable, add both the condition 144458b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // variable and initializer to the CFG. 144558b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (VarDecl *VD = F->getConditionVariable()) { 144658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (Expr *Init = VD->getInit()) { 144758b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek autoCreateBlock(); 144858b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek AppendStmt(Block, F, AddStmtChoice::AlwaysAdd); 144958b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek EntryConditionBlock = addStmt(Init); 145058b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek assert(Block == EntryConditionBlock); 145158b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 145258b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 1453ad5a894df1841698c824381b414630799adc26caTed Kremenek 14544e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1455d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14564e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 14574e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 145849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 1459d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 14606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 14616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 146249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 14636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 146400998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1465941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal(true); 14661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 146700998a068e50945118f334c98af05ed44d7c22a6Mike Stump if (F->getCond()) 146800998a068e50945118f334c98af05ed44d7c22a6Mike Stump KnownVal = TryEvaluateBool(F->getCond()); 146900998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1470d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1471d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 14726db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 14736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14743f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current values for Block, Succ, and continue targets. 1475f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1476f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 14776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1478af603f742491dc4707138c0293d295171fdd51baTed Kremenek // Create a new block to contain the (bottom) of the loop body. 1479af603f742491dc4707138c0293d295171fdd51baTed Kremenek Block = NULL; 148047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 148147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 148247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 14836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1484e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek if (Stmt* I = F->getInc()) { 14856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 14866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 14874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 14886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 14896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // No increment code. Create a special, empty, block that is used as the 14906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // target block for "looping back" to the start of the loop. 14913575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Succ == EntryConditionBlock); 149247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski Succ = Block ? Block : createBlock(); 1493e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 14946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14953575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 14963575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 14973575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1498d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14994e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 15003575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 15013575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 15026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 150347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 15046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15053575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // The starting block for the loop increment is the block that should 15063575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 1507f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget.Block->setLoopTarget(F); 15083575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 150947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 151047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 151147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 151247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 151347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 15146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 15156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 15164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(F->getBody()); 1517af603f742491dc4707138c0293d295171fdd51baTed Kremenek 1518af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 1519f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BodyBlock = ContinueJumpTarget.Block;//can happen for "for (...;...;...);" 1520d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 1521941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 15226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1523941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // This new body block is a successor to our "exit" condition block. 1524ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1525d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 15266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1527941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1528941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 1529ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 15306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1531d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 15326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 1533d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* I = F->getInit()) { 1534d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 153549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 15366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 15376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There is no loop initialization. We are thus basically a while loop. 15386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NULL out Block to force lazy block construction. 15392bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek Block = NULL; 15405482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 154149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 15422bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 1543d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1544d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1545115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 1546115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek if (asc.alwaysAdd()) { 1547115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 1548115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek AppendStmt(Block, M, asc); 1549115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 1550115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return Visit(M->getBase(), 1551115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek M->isArrow() ? AddStmtChoice::NotAlwaysAdd 1552115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AsLValueNotAlwaysAdd); 1553115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 1554115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1555514de5a21645900c92cf4f4f7313d6f66945d134Ted KremenekCFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 1556514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 1557514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 1558514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1559514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 1560514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1561514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1562514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1563514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 1564514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 1565514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1566514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 15674cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 1568514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 1569514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 1570514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 1571514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 1572514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1573514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 1574514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 1575514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1576514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 1577514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1578514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 1579514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 1580514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1581514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1582514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 15836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 15846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 15856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 1586514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 15876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1588514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek CFGBlock* LoopSuccessor = 0; 15896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1590514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 1591d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1593514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 1594514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 15954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 15964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 15976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15984cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 15994cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 16004cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 16016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16024cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 16036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 16046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 16066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 16076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 1608ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(ExitConditionBlock, S); 16094cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 16106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16114cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 16126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // generate new blocks as necesary. We DON'T add the statement by default to 16136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 1614852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd); 16156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1616d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16174e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 16184e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 16194e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 16206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 16226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 16234cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 16246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16254cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 16266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 16274cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 1628f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Succ(Succ); 1629f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1630f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 16316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1632f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 1633f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 16346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(S->getBody()); 16366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16374cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 16384cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" 16394e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1640d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16414e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 16424e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 16436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16444cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 1645ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, BodyBlock); 16464cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 16476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16484cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 16494cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 1650ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, LoopSuccessor); 16514cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 1652514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 16534cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 1654514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 16556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 16566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1657b3b0b3624e462c2940f65b86e773bfc300005203Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) { 1658b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 16596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1660b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 16614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 16626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1663da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 1664da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 1665da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 1666d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1667da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 16686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1669da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 1670fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 1671da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 16726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16734beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 16744beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 16754beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek AppendStmt(Block, S, AddStmtChoice::AlwaysAdd); 16764beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 1677b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 16784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 1679b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 16806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1681e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) { 16824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 168390658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 1684e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 1685514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 1686d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { 1687d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 16886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 168905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 169005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 169105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 169205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 169305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 169405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 1695f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 169605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (VarDecl* VD = W->getConditionVariable()) { 169705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 169805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 169905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 1700f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1701fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 1702fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1703d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1704d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17054e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1706d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 17074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 17084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 17096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 17116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 17126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 171349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 171449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 17156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 171649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 171749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek ExitConditionBlock->setTerminator(W); 17186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 17206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. Thus we update 17216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "Succ" after adding the condition. 172249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = W->getCond()) { 172349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 172449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 1725f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Block == EntryConditionBlock); 1726ad5a894df1841698c824381b414630799adc26caTed Kremenek 17274ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // If this block contains a condition variable, add both the condition 17284ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // variable and initializer to the CFG. 17294ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 17304ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (Expr *Init = VD->getInit()) { 17314ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek autoCreateBlock(); 17324ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek AppendStmt(Block, W, AddStmtChoice::AlwaysAdd); 17334ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek EntryConditionBlock = addStmt(Init); 17344ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek assert(Block == EntryConditionBlock); 17354ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 17364ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 17374ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek 17384e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1739d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17404e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17414e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 174249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 17436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 17456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 174649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 17476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 174800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1749941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(W->getCond()); 175000998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1751d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 1752d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 1753f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 1754d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1755d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 1756f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1757f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1758f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 1759f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 17606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 17616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 1762f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Block = 0; 1763f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Succ == EntryConditionBlock); 1764f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ = createBlock(); 1765f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ->setLoopTarget(W); 1766f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 17676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1768d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 176905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 17706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1771d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 1772f752fcfae84fbf21b78383bf2461633382d51844Ted Kremenek Block = NULL; 17736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 177405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 177505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 177605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 177705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 177805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 177905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 178005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 178105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 1782d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 17834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(W->getBody()); 17846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1785af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 1786f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BodyBlock = ContinueJumpTarget.Block; // can happen for "while(...) ;" 17874e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1788d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17894e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17904e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 17916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1792941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 1793ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1794bf15b278a439d73b605ec00a8d3977ef305712f4Ted Kremenek } 17956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1796941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1797941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 1798ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 17996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 18016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 1802d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 18036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18044ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 18055482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 180649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 1807d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 18081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18104f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) { 18114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 18124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 18134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 18144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 18156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18162fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) { 18172fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 18182fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 18196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18206c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1821d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 18236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18242fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 18252fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 18266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18272fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 1828ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, &cfg->getExit()); 18296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 18316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 1832852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 18332fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 1834989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 18350979d80615df97c675423de631c1b884819f4712Mike StumpCFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) { 18366c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1837d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18380979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 18390979d80615df97c675423de631c1b884819f4712Mike Stump 18400979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 18410979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 18420979d80615df97c675423de631c1b884819f4712Mike Stump 18435d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 18445d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 18455d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump AddSuccessor(Block, TryTerminatedBlock); 1846ad5a894df1841698c824381b414630799adc26caTed Kremenek else 18475d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 18485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump AddSuccessor(Block, &cfg->getExit()); 18490979d80615df97c675423de631c1b884819f4712Mike Stump 18500979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 18510979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 1852852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 18530979d80615df97c675423de631c1b884819f4712Mike Stump} 18540979d80615df97c675423de631c1b884819f4712Mike Stump 18554f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) { 1856d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 18576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18588f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 18598f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 1860d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1861d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18624e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1863d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 18644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 18654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 18666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 18686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 18696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 187049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 187149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 18726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 187349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 18746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 18756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 18776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 187849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = D->getCond()) { 187949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 188049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 18814e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1882d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18834e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18844e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 188549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 18866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18875482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 188849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 188949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 189000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1891941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult &KnownVal = TryEvaluateBool(D->getCond()); 189200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1893d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 189449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* BodyBlock = NULL; 1895d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 18966db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 18976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1898d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 1899f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1900f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1901f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 19026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1903d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 1904f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 19056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1906d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 1907f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 19086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1909d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 1910b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 19116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 191205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 191305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 191405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 191505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 191605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 1917d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 19184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 19196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1920af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 1921a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 19224e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1923d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19244e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19254e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 19266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1927d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 1928d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 1929d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 1930d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 1931d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 1932d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 1933d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 1934d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 1935d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 1936d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 1937d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 1938d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 1939d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek AddSuccessor(ExitConditionBlock, LoopBackBlock); 1940d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 1941d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 1942d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek AddSuccessor(ExitConditionBlock, NULL); 1943b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 19446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1945941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 1946941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 1947ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 19486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 19506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 1951d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 19526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1953d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 19545482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 1955d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 1956d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1957d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1958d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) { 1959d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 1960d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 1961d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1962d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 19636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1964d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 1965d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1966d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 19676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1968d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 1969235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 1970f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (ContinueJumpTarget.Block) { 1971fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, ContinueJumpTarget.ScopePos, C); 1972f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(Block, ContinueJumpTarget.Block); 1973f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 1974235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 19756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1976d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 1977d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 19781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 197913fc08a323b29dd97a46def1e3a15bf082476efaTed KremenekCFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, 1980852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 198113fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 1982852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 198313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 1984ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, E); 198513fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 19861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 19884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 19894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr()); 19904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 19914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(VA->getSizeExpr()); 19924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 19931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1995d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 19961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 19984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 1999852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 2000852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 200113fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2002ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, SE); 200313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 20044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 20054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2006d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2007411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { 20086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 20096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 2010d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* SwitchSuccessor = NULL; 20116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20128ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 20138ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 20148ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 20158ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 20168ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 20178ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 20188ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (VarDecl* VD = Terminator->getConditionVariable()) { 20198ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 20208ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 20218ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 20228ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 20238ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2024d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2025d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20264e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2027d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 20286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2029d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2030d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2031d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2032eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2033f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2034eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 20356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 20366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 20376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2038eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 20396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2040d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2041d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 20426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2043d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2044d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2045d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2046f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 20476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 20496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 20506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 20516db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 205249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 20538ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 20548ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 20558ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 20568ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 20578ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 20588ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2059d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 20604e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2061d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20624e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20634e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 206449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 20656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 20666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // following the switch body. 2067ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(SwitchTerminatedBlock, DefaultCaseBlock); 20686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 206949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2070411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 20716db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 2072d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 20736b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek Block = addStmt(Terminator->getCond()); 2074ad5a894df1841698c824381b414630799adc26caTed Kremenek 20756b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 20766b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 20776b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 20786b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 20796b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 20806b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek AppendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd); 20816b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek addStmt(Init); 20826b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 20836b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2084ad5a894df1841698c824381b414630799adc26caTed Kremenek 20856b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek return Block; 2086d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2087d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 20884f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) { 20896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 20906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 20910fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 20920fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 20930fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 20940fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 20950fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 20960fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 20970fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 20980fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *CurrentBlock = createBlock(false); 20990fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CurrentBlock->setLabel(CS); 21000fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 21010fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 21020fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(LastBlock, CurrentBlock); 21030fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 21040fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek TopBlock = CurrentBlock; 21050fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 21060fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(SwitchTerminatedBlock, CurrentBlock); 21070fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek LastBlock = CurrentBlock; 21080fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 21090fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 21100fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 21110fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 211229ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 21130fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 21140fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 21151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 211629ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek CFGBlock* CaseBlock = Block; 21174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 21184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 21196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 21216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 21224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 21234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2124d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21254e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 21286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 21294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2130ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(SwitchTerminatedBlock, CaseBlock); 21316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2132d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2133d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 21346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21350fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 21360fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(LastBlock, CaseBlock); 21370fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 21380fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 21390fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else { 21400fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 21410fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 21420fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 21436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21440fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2145d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 21466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2147411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) { 21484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 21494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 21501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2151eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 21524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 21534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 21544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 21556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 21576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2158411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 21591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2160d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21614e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2162eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 21636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 21646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 21656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 21666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 21676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 21686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2169eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2170eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 21716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2172eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2173eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 21746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2176295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2177d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 21785d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 21795d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 21805d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 21815d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* TrySuccessor = NULL; 21825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 21835d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2184d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21855d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 21865d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 21875d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 21885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2189a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 21905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 21915d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2192f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 21935d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2194f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 21955d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2196a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 21975d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 21985d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 21995d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 22005d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2201a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2202a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2203a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 22045d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 22055d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 22065d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 22075d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 22085d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 22095d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 2210f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, CatchBlock); 22115d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2212a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2213a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 2214f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2215a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 2216f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2217a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 22185d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22195d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 22205d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 22215d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2222f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2223f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock); 2224f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump TryTerminatedBlock = NewTryTerminatedBlock; 2225f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 22266db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 22275d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 22283fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek Block = addStmt(Terminator->getTryBlock()); 22295d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return Block; 22305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 22315d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22325d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) { 22335d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 22345d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 22355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22360e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 22370e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 22380e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 22390e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 22400e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 22410e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 22420e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski if (VarDecl* VD = CS->getExceptionDecl()) { 22430e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 22440e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 22450e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 22460e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 22470e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 22485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 22495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 22505d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* CatchBlock = Block; 22525d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 22535d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 22545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22555d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 22565d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2257d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22585d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 22595d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22605d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 22615d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 22625d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22635d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 22645d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 22655d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2266ad5a894df1841698c824381b414630799adc26caTed KremenekCFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C, 2267c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu AddStmtChoice asc) { 2268ad5a894df1841698c824381b414630799adc26caTed Kremenek AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 226921f6d6ea71b89aeae6b9262c8cbdff7f6328e749Zhongxing Xu : AddStmtChoice::AlwaysAdd; 2270c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu autoCreateBlock(); 227121f6d6ea71b89aeae6b9262c8cbdff7f6328e749Zhongxing Xu AppendStmt(Block, C, AddStmtChoice(K)); 2272c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu return VisitChildren(C); 2273c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu} 2274c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu 227519bb356317952445b03ee341c02f6147083c9eeaTed KremenekCFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) { 22766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 227719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek CFGBlock* IBlock = cfg->getIndirectGotoBlock(); 22786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 227919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 228019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 228119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 228219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 22836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 228419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 228519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 2286d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 22884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 228919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 229019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 2291ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, IBlock); 229219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 229319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 229419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 2295befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 2296026473c2175424a039f51ca8949937268721b965Ted Kremenek 22976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 22986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 22996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 23009438252ad2ecae5338df565ca33c6969e4fbfa41Ted KremenekCFGBlock* CFG::createBlock() { 2301026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 2302026473c2175424a039f51ca8949937268721b965Ted Kremenek 2303026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 2304ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 2305ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek new (Mem) CFGBlock(NumBlockIDs++, BlkBVC); 2306ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 2307026473c2175424a039f51ca8949937268721b965Ted Kremenek 2308026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 2309ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 2310ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 2311026473c2175424a039f51ca8949937268721b965Ted Kremenek 2312026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 2313ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 2314026473c2175424a039f51ca8949937268721b965Ted Kremenek} 2315026473c2175424a039f51ca8949937268721b965Ted Kremenek 2316026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 2317026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 2318b978a441c7d8bf59e7fede938e1f3b672573b443Mike StumpCFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C, 23196c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek BuildOptions BO) { 2320fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBuilder Builder; 23216c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek return Builder.buildCFG(D, Statement, C, BO); 2322fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 2323fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 232463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 232563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek// CFG: Queries for BlkExprs. 232663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 232763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 232863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremeneknamespace { 232986946745225096243f6969dc745267b78fc211a6Ted Kremenek typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy; 233063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 233163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 23328a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenekstatic void FindSubExprAssignments(Stmt *S, 23338a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek llvm::SmallPtrSet<Expr*,50>& Set) { 23348a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!S) 233533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return; 23366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23378a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) { 2338ad5a894df1841698c824381b414630799adc26caTed Kremenek Stmt *child = *I; 23398a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!child) 23408a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek continue; 2341ad5a894df1841698c824381b414630799adc26caTed Kremenek 23428a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(child)) 234333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (B->isAssignmentOp()) Set.insert(B); 23446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23458a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek FindSubExprAssignments(child, Set); 234633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 234733d4aab80f31bd06257526fe2883ea920529456bTed Kremenek} 234833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek 234963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekstatic BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { 235063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = new BlkExprMapTy(); 23516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Look for assignments that are used as subexpressions. These are the only 23536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // assignments that we want to *possibly* register as a block-level 23546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression. Basically, if an assignment occurs both in a subexpression and 23556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // at the block-level, it is a block-level expression. 235633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek llvm::SmallPtrSet<Expr*,50> SubExprAssignments; 23576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 235863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) 2359ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 2360b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (CFGStmt S = BI->getAs<CFGStmt>()) 2361b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu FindSubExprAssignments(S, SubExprAssignments); 236286946745225096243f6969dc745267b78fc211a6Ted Kremenek 2363411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { 23646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Iterate over the statements again on identify the Expr* and Stmt* at the 23666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block-level that are block-level expressions. 2367411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 2368b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { 2369b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu CFGStmt CS = BI->getAs<CFGStmt>(); 2370b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (!CS.isValid()) 2371b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu continue; 2372b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (Expr* Exp = dyn_cast<Expr>(CS.getStmt())) { 23736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2374411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { 237533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek // Assignment expressions that are not nested within another 23766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression are really "statements" whose value is never used by 23776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // another expression. 2378411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) 237933d4aab80f31bd06257526fe2883ea920529456bTed Kremenek continue; 23806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (const StmtExpr* Terminator = dyn_cast<StmtExpr>(Exp)) { 23816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Special handling for statement expressions. The last statement in 23826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the statement expression is also a block-level expr. 2383411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek const CompoundStmt* C = Terminator->getSubStmt(); 238486946745225096243f6969dc745267b78fc211a6Ted Kremenek if (!C->body_empty()) { 238533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 238686946745225096243f6969dc745267b78fc211a6Ted Kremenek (*M)[C->body_back()] = x; 238786946745225096243f6969dc745267b78fc211a6Ted Kremenek } 238886946745225096243f6969dc745267b78fc211a6Ted Kremenek } 2389e2dcd783a04f654c50bd8b13fb08a440afbd67e7Ted Kremenek 239033d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 2391411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek (*M)[Exp] = x; 239233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 2393b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 23946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2395411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek // Look at terminators. The condition is a block-level expression. 23966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2397ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Stmt* S = (*I)->getTerminatorCondition(); 23986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2399390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek if (S && M->find(S) == M->end()) { 2400411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek unsigned x = M->size(); 2401390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek (*M)[S] = x; 2402411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 2403411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 24046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 240586946745225096243f6969dc745267b78fc211a6Ted Kremenek return M; 240663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 240763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 240886946745225096243f6969dc745267b78fc211a6Ted KremenekCFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) { 240986946745225096243f6969dc745267b78fc211a6Ted Kremenek assert(S != NULL); 241063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } 24116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 241263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap); 241386946745225096243f6969dc745267b78fc211a6Ted Kremenek BlkExprMapTy::iterator I = M->find(S); 24143fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); 241563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 24167dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 241763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekunsigned CFG::getNumBlkExprs() { 241863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap)) 241963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return M->size(); 242063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek else { 242163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek // We assume callers interested in the number of BlkExprs will want 242263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek // the map constructed if it doesn't already exist. 242363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMap = (void*) PopulateBlkExprMap(*this); 242463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size(); 242563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek } 242663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 242763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 2428274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 2429ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 2430ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 2431ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2432ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 2433be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 2434ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2435ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (F.IgnoreDefaultsWithCoveredEnums) { 2436ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 2437ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 2438ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 2439be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator())) { 2440ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 2441be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const Stmt *L = To->getLabel(); 2442be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 2443be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek return true; 2444ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 2445ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 2446ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 2447ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2448ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 2449ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 2450ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2451ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 2452274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek// Cleanup: CFG dstor. 2453274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 2454274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek 245563f5887f316fb52d243fcbb3631c039de6c4b993Ted KremenekCFG::~CFG() { 245663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap); 245763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 24586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24597dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 24607dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 24617dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 24627dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 246342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 24642bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 2465ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 246642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 24671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski typedef llvm::DenseMap<Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 246842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 24691cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 247042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek signed CurrentBlock; 247142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned CurrentStmt; 2472e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 247342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 24741c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 2475e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 2476e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner : CurrentBlock(0), CurrentStmt(0), LangOpts(LO) { 247742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 247842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 2479ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 24801cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 24811cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (CFGStmt SE = BI->getAs<CFGStmt>()) { 24821cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 24831cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMap[SE] = P; 24841cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 24851cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (DeclStmt* DS = dyn_cast<DeclStmt>(SE.getStmt())) { 24861cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[DS->getSingleDecl()] = P; 24871cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 24881cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (IfStmt* IS = dyn_cast<IfStmt>(SE.getStmt())) { 24891cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = IS->getConditionVariable()) 24901cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 24911cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 24921cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (ForStmt* FS = dyn_cast<ForStmt>(SE.getStmt())) { 24931cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = FS->getConditionVariable()) 24941cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 24951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 24961cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (WhileStmt* WS = dyn_cast<WhileStmt>(SE.getStmt())) { 24971cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = WS->getConditionVariable()) 24981cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 24991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 25001cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (SwitchStmt* SS = dyn_cast<SwitchStmt>(SE.getStmt())) { 25011cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = SS->getConditionVariable()) 25021cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 25031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 25041cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (CXXCatchStmt* CS = dyn_cast<CXXCatchStmt>(SE.getStmt())) { 25051cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = CS->getExceptionDecl()) 25061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 25071cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 25081cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 250942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 2510b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 2511fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 25126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 251342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 25146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2515e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 251642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek void setBlockID(signed i) { CurrentBlock = i; } 251742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek void setStmtID(unsigned i) { CurrentStmt = i; } 25186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25191cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski virtual bool handledStmt(Stmt* S, llvm::raw_ostream& OS) { 25201cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 2521fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 252242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 252342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 25246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock 25263fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek && I->second.second == CurrentStmt) { 252742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 25283fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 25296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25303fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 25311c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 253242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 25331cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 25341cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski bool handleDecl(Decl* D, llvm::raw_ostream& OS) { 25351cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 25361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 25371cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 25381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 25391cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 25401cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock 25411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski && I->second.second == CurrentStmt) { 25421cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 25431cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 25441cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 25451cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 25461cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 25471cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 254842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 2549e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 2550e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 2551e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 2552e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 2553ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 25546fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 25556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2556a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_ostream& OS; 255742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 2558d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 2559d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 2560d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper, 2561e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 2562d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 25636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2564d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitIfStmt(IfStmt* I) { 2565d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 2566d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 2567d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 25686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2569d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 25706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump void VisitStmt(Stmt* Terminator) { 25716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 25726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 25736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2574d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitForStmt(ForStmt* F) { 2575d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 25763fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 25773fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 2578535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 25793fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = F->getCond()) 25803fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 2581535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 25823fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 25833fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 2584a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 2585d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 25866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2587d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitWhileStmt(WhileStmt* W) { 2588d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 25893fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = W->getCond()) 25903fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 2591d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 25926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2593d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitDoStmt(DoStmt* D) { 2594d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 25953fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = D->getCond()) 25963fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 25979da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 25986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2599411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek void VisitSwitchStmt(SwitchStmt* Terminator) { 26009da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 2601d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 26029da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 26036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26045d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump void VisitCXXTryStmt(CXXTryStmt* CS) { 26055d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 26065d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 26075d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2608805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitConditionalOperator(ConditionalOperator* C) { 2609d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 26106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 2611805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 26126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2613aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek void VisitChooseExpr(ChooseExpr* C) { 2614aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 2615d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 2616a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 2617aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 26186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26191c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt* I) { 26201c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 2621d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 26221c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 26236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2624805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 2625805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 2626805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 2627805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 2628805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 26296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2630d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 26316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2632805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 26332de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 2634a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 2635805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 26362de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 2637a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 2638805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 2639805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 2640805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek assert(false && "Invalid logical operator."); 26416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 2642805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 26436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26440b1d9b7557437176f9cea1283bfac2510812beceTed Kremenek void VisitExpr(Expr* E) { 2645d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 26466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 2647d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 2648e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 2649e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 26501cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderskistatic void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, 2651079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 26521cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (CFGStmt CS = E.getAs<CFGStmt>()) { 26531cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Stmt *S = CS; 26541cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 26551cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 26561cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 26571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 26581cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) { 26591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski CompoundStmt* Sub = SE->getSubStmt(); 26601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 26611cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Sub->child_begin() != Sub->child_end()) { 26621cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 26631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 26641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 26651cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 26661cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 26671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 26681cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 26691cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 26701cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 26711cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 26721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 26731cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 26741cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 26751cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 26761c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 26771c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 26781cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 26796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26801cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 26811cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (OperatorCall)"; 26821cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 26831cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else if (isa<CXXBindTemporaryExpr>(S)) { 26841cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (BindTemporary)"; 26856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 26866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26871cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 26881cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 26891cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 26904e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 26911cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (CFGInitializer IE = E.getAs<CFGInitializer>()) { 26921cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski CXXBaseOrMemberInitializer* I = IE; 26931cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 26941cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 26951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << I->getMember()->getName(); 26966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26971cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 26981cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Expr* IE = I->getInit()) 26991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 27001cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 27011cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 27021cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 27031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 27041cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 27051cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 27061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (CFGAutomaticObjDtor DE = E.getAs<CFGAutomaticObjDtor>()){ 27071cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski VarDecl* VD = DE.getVarDecl(); 27081cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 27091cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 27101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Type* T = VD->getType().getTypePtr(); 27111cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 27121cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 27131cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 27141cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 27151cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 27167c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 27177c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } else if (CFGBaseDtor BE = E.getAs<CFGBaseDtor>()) { 27187c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXBaseSpecifier *BS = BE.getBaseSpecifier(); 27197c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 27204e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 27217c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 27227c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } else if (CFGMemberDtor ME = E.getAs<CFGMemberDtor>()) { 27237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FieldDecl *FD = ME.getFieldDecl(); 27247c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 27257c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << ".~" << FD->getType()->getAsCXXRecordDecl()->getName() << "()"; 27264e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 27271cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 27281cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 27296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2730e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnerstatic void print_block(llvm::raw_ostream& OS, const CFG* cfg, 2731e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const CFGBlock& B, 2732e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper* Helper, bool print_edges) { 27336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 273442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(B.getBlockID()); 27356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27367dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 27376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << "\n [ B" << B.getBlockID(); 27386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 273942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 274042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (ENTRY) ]\n"; 274142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 274242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (EXIT) ]\n"; 274342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 27447dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OS << " (INDIRECT GOTO DISPATCH) ]\n"; 274542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 274642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " ]\n"; 27476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27489cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 2749079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) { 275042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 275142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 275242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 27536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2754079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (LabelStmt* L = dyn_cast<LabelStmt>(Label)) 27559cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 2756079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) { 27579cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 2758e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 2759e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 27609cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 27619cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 2762e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 2763e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 27649cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 2765079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 27669cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 2767079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 27685d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 2769a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 2770a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 2771a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 2772a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 2773a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 27745d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 27755d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 27765d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 277742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek assert(false && "Invalid label statement in CFGBlock."); 27786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27799cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 27809cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 27816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2782fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 2783fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 27846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 278542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 278642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 27876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27889cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 278942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 279042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 27916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2792a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 27936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 279442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 279542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 27966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27971cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski print_elem(OS,Helper,*I); 2798fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 27996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28009cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 280142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 280242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 280342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 28046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28059cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " T: "; 28066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 280742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 28086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2809e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, Helper, 2810e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 281142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek TPrinter.Visit(const_cast<Stmt*>(B.getTerminator())); 2812a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 2813fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 28146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28159cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 28169cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 281742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Predecessors (" << B.pred_size() << "):"; 28189cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek unsigned i = 0; 281942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 282042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 282142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 28226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 282342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) == 0) 28249cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 28256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28269cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " B" << (*I)->getBlockID(); 28279cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 28286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28299cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 28306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28319cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 283242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Successors (" << B.succ_size() << "):"; 28339cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek i = 0; 283442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 283542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 283642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 28376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 283842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) % 10 == 0) 28399cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 284042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 2841e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump if (*I) 2842e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " B" << (*I)->getBlockID(); 2843e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump else 2844e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " NULL"; 2845fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 28466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28479cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 2848fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 28496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 285042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 285142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 285242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 2853e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); } 285442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 285542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 2856e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const { 2857e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 28586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 285942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 286042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getEntry(), &Helper, true); 28616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 286242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 286342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 286442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 2865ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 286642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 28676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2868ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek print_block(OS, this, **I, &Helper, true); 286942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 28706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 287142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 287242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getExit(), &Helper, true); 2873d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 28746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 287542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 287642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 2877e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const { 2878e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner print(llvm::errs(), cfg, LO); 2879e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 288042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 288142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 288242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 2883e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg, 2884e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LO) const { 2885e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 288642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, cfg, *this, &Helper, true); 2887026473c2175424a039f51ca8949937268721b965Ted Kremenek} 28887dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 2889a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 2890e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::printTerminator(llvm::raw_ostream &OS, 28916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 2892e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 2893a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek TPrinter.Visit(const_cast<Stmt*>(getTerminator())); 2894a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 2895a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 2896390e48b15ad93f85bfd1e33b9992c198fa0db475Ted KremenekStmt* CFGBlock::getTerminatorCondition() { 28976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2898411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 2899411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 29006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2901411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek Expr* E = NULL; 29026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2903411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 2904411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 2905411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2907411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 2908411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 2909411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2911411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 2912411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 2913411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2915411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 2916411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 2917411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2919411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 2920411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 2921411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2923411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 2924411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 2925411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2927411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 2928411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 2929411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2931411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 2932411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 2933411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2935411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 2936411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 2937411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 29386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2939411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 2940411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 2941390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 29426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2943390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 29446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 2945411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 29466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2947411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 2948411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 2949411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 29509c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenekbool CFGBlock::hasBinaryBranchTerminator() const { 29516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 29529c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek if (!Terminator) 29539c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return false; 29546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 29559c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek Expr* E = NULL; 29566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 29579c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek switch (Terminator->getStmtClass()) { 29589c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek default: 29599c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return false; 29606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 29616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump case Stmt::ForStmtClass: 29629c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::WhileStmtClass: 29639c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::DoStmtClass: 29649c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::IfStmtClass: 29659c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::ChooseExprClass: 29669c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::ConditionalOperatorClass: 29679c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::BinaryOperatorClass: 29686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return true; 29699c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek } 29706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 29719c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return E ? E->IgnoreParens() : NULL; 29729c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek} 29739c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek 2974a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 29757dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 29767dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 29777dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 29787dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 297942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 298042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 29816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 298242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 298342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 2984e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 298542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 2986e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 298742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 298842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 298942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 299042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 299142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 299242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 29937dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 29947dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 29957dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 2996006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 2997006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 2998006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 2999006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) { 30007dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3001bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 3002a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 3003a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 300442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(Out,Graph, *Node, GraphHelper, false); 3005a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 30067dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 30077dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 30087dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 30097dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 30107dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 30117dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 30127dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 30137dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 30147dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 30156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30167dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 3017bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 3018bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 3019bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 30207dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 30217dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 30227dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 3023