CFG.cpp revision 8599e7677e067fd01d3b2ee4c0875747d367fd8e
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); 2618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E, 2628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc); 2637ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 2647ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 265a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 266a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 26781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); 268a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 269a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 27081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 27181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc); 272c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc); 273852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 2744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 275852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 2763fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 2777ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitConditionalOperator(ConditionalOperator *C, AddStmtChoice asc); 2783fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 2794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 2808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitDeclSubExpr(DeclStmt* DS); 2813fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 2823fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 2833fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 2844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt* G); 2854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 286a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); 2874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 2884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 289115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 2904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 2914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 2924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 2934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 2944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 2954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitReturnStmt(ReturnStmt* R); 296852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc); 297852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 2984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 2994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 3004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 301852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 302852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 3034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitChildren(Stmt* S); 304cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 3058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Visitors to walk an AST and generate destructors of temporaries in 3068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // full expression. 3078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false); 3088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E); 3098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); 3108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, 3118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 3128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitConditionalOperatorForTemporaryDtors(ConditionalOperator *E, 3138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 3148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 315274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 316274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek CFGBlock* NYS() { 3174102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 3184102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 3194102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 3206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 3224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 323d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 324df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 325df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 326852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 32782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski CFGBlock *addInitializer(CXXBaseOrMemberInitializer *I); 3286a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 3296a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu LocalScope::const_iterator E, Stmt* S); 3307c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 331239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 332239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 333239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 334239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 33502acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu void addLocalScopeForStmt(Stmt* S); 336239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* addLocalScopeForDeclStmt(DeclStmt* DS, LocalScope* Scope = NULL); 337239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* addLocalScopeForVarDecl(VarDecl* VD, LocalScope* Scope = NULL); 338239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 339239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski void addLocalScopeAndDtors(Stmt* S); 340ad5a894df1841698c824381b414630799adc26caTed Kremenek 341239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 342852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek void AppendStmt(CFGBlock *B, Stmt *S, 343852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc = AddStmtChoice::AlwaysAdd) { 344852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue()); 345ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 34682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski void appendInitializer(CFGBlock *B, CXXBaseOrMemberInitializer *I) { 34782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 34882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 3497c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 3507c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 3517c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 3527c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 3537c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 3547c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 3558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { 3568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); 3578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 358ad5a894df1841698c824381b414630799adc26caTed Kremenek 35953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I, 36053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S); 36153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void appendAutomaticObjDtors(CFGBlock* Blk, LocalScope::const_iterator B, 36253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator E, Stmt* S); 36353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk, 36453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 36553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 366ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek void AddSuccessor(CFGBlock *B, CFGBlock *S) { 367ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 368ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 370fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// TryResult - a class representing a variant over the values 371fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// 'true', 'false', or 'unknown'. This is returned by TryEvaluateBool, 372fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// and is used by the CFGBuilder to decide if a branch condition 373fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek /// can be decided up front during CFG construction. 374941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek class TryResult { 375941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek int X; 376941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek public: 377941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 378941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult() : X(-1) {} 3791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 380941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isTrue() const { return X == 1; } 381941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isFalse() const { return X == 0; } 382941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek bool isKnown() const { return X >= 0; } 383941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek void negate() { 384941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(isKnown()); 385941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek X ^= 0x1; 386941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek } 387941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek }; 3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38900998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// TryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 39000998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 391941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult TryEvaluateBool(Expr *S) { 3926c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 393ad5a894df1841698c824381b414630799adc26caTed Kremenek return TryResult(); 394ad5a894df1841698c824381b414630799adc26caTed Kremenek 39500998a068e50945118f334c98af05ed44d7c22a6Mike Stump Expr::EvalResult Result; 3969983cc110422a2e976191a0ce6ac4f1d7b634cc0Douglas Gregor if (!S->isTypeDependent() && !S->isValueDependent() && 3979983cc110422a2e976191a0ce6ac4f1d7b634cc0Douglas Gregor S->Evaluate(Result, *Context) && Result.Val.isInt()) 398fadc9eaeac18b470b6dfcf9efcf5c4f8caea89bcTed Kremenek return Result.Val.getInt().getBoolValue(); 399941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek 400941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return TryResult(); 40100998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 402d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 4036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 404898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 405898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 406610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenekstatic VariableArrayType* FindVA(Type* t) { 407610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek while (ArrayType* vt = dyn_cast<ArrayType>(t)) { 408610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt)) 409610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 410610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 4116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 412610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 413610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 4146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 415610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 416610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 4176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 4196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 4206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 4216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 4226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 423b978a441c7d8bf59e7fede938e1f3b672573b443Mike StumpCFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, 4246c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek CFG::BuildOptions BO) { 425ad5a894df1841698c824381b414630799adc26caTed Kremenek 426e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump Context = C; 4270ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 4284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 4294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 430d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 4316c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek BuildOpts = BO; 4326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 4346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 4356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 43649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 437ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 43849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 4396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4407c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 4417c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 4427c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 4437c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 444d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 4451b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 4461b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 4471b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 4481b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 4491b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 45082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 451b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 45282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 45382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 45482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 45582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 45682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 45782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 458b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 4596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 46082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 46182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 46282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 4631b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 4641b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 4651b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 4661b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 467c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 468f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski CFGBlock* B = I->Block; 4691b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu GotoStmt* G = cast<GotoStmt>(B->getTerminator()); 4701b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 4716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4721b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 4731b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 4741b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 475d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 476f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 477fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski prependAutomaticObjDtorsWithTerminator(B, I->ScopePos, JT.ScopePos); 478f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(B, JT.Block); 4791b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 4806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4811b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 4821b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (CFGBlock* B = cfg->getIndirectGotoBlock()) 4831b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 4841b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 4851b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 4861b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 4871b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 4881b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 4891b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 4901b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 4911b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 4921b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 493f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(B, LI->second.Block); 494c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 4956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 497322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 4986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4991b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 500d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 5016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 502d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 503d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 5046d9828c82c9321f042ab416fd2ffaa3034347d45Mike StumpCFGBlock* CFGBuilder::createBlock(bool add_successor) { 5059438252ad2ecae5338df565ca33c6969e4fbfa41Ted Kremenek CFGBlock* B = cfg->createBlock(); 5064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 507ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(B, Succ); 508d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 509d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 5106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 51182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 51282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin SwiderskiCFGBlock *CFGBuilder::addInitializer(CXXBaseOrMemberInitializer *I) { 51382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 51482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 51582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 5168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 5178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 51882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 5198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 5208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 5218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Expr *Init = I->getInit(); 5228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 52382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (FieldDecl *FD = I->getMember()) 5248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = FD->getType()->isReferenceType(); 5258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski HasTemporaries = isa<CXXExprWithTemporaries>(Init); 52682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 5278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 5288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 5298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(cast<CXXExprWithTemporaries>(Init)->getSubExpr(), 5308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 5318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 53282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 5338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 5348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 5358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendInitializer(Block, I); 5368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 5378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 5388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc = IsReference 5398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ? AddStmtChoice::AsLValueNotAlwaysAdd 5408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski : AddStmtChoice::NotAlwaysAdd; 5418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (HasTemporaries) 5428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 5438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 5448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(cast<CXXExprWithTemporaries>(Init)->getSubExpr(), asc); 5458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(Init, asc); 5468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 5478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 54882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 54982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 55082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 551239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 552239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 553239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 5546a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 5556a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu LocalScope::const_iterator E, Stmt* S) { 556239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 5576a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 5586a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 559239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 5606a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 561239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 562239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski autoCreateBlock(); 563239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski appendAutomaticObjDtors(Block, B, E, S); 564239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 565239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 5667c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 5677c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 5687c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 5697c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 5707c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 5717c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 5727c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 5737c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 5747c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 5757c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 5767c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 5777c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 5787c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 5797c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 5807c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5817c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5827c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 5837c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 5847c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 5857c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 5867c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!BI->isVirtual()) { 5877c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 5887c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 5897c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 5907c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, BI); 5917c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5927c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5937c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 5947c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 5957c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 5967c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 5977c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 5988c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski // Check for constant size array. Set type to array element type. 5998c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QualType QT = FI->getType(); 6008c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 6018c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (AT->getSize() == 0) 6028c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski continue; 6038c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QT = AT->getElementType(); 6048c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski } 6058c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 6068c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 6077c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 6087c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 6097c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendMemberDtor(Block, *FI); 6107c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6117c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6127c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 6137c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 614239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 615239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 616239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 617239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 618239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = cfg->getAllocator().Allocate<LocalScope>(); 619239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski new (Scope) LocalScope(ScopePos); 620239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 621239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 622239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 623239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 624239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 62502acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 62602acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xuvoid CFGBuilder::addLocalScopeForStmt(Stmt* S) { 627239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 62802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 62902acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 63002acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 631239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 632239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 633239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (CompoundStmt* CS = dyn_cast<CompoundStmt>(S)) { 634239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 635239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 636239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Stmt* SI = *BI; 637239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (LabelStmt* LS = dyn_cast<LabelStmt>(SI)) 638239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski SI = LS->getSubStmt(); 639239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (DeclStmt* DS = dyn_cast<DeclStmt>(SI)) 640239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 641239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 64202acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 643239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 644239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 645239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 646239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 647239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (LabelStmt* LS = dyn_cast<LabelStmt>(S)) 648239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski S = LS->getSubStmt(); 649239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) 650b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 651239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 652239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 653239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 654239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 655239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt* DS, 656b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 657239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 658239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 659239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 660239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 661239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 662239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (VarDecl* VD = dyn_cast<VarDecl>(*DI)) 663239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 664239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 665239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 666239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 667239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 668239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 669239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 670239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 671239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl* VD, 672b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 673239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 674239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 675239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 676239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 677239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 678239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 679239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 680239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 681239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 682239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 683239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 684239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 685239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 686239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 687239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (const ReferenceType* RT = QT.getTypePtr()->getAs<ReferenceType>()) { 688239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QT = RT->getPointeeType(); 689239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!QT.isConstQualified()) 690239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 691239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!VD->getInit() || !VD->getInit()->Classify(*Context).isRValue()) 692239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 693239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 694239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 695b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check for constant size array. Set type to array element type. 696b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 697b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (AT->getSize() == 0) 698b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski return Scope; 699b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski QT = AT->getElementType(); 700b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski } 7014e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 702b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 7034e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu if (const CXXRecordDecl* CD = QT->getAsCXXRecordDecl()) 7044e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu if (!CD->hasTrivialDestructor()) { 7054e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 7064e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 7074e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 7084e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 7094e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 710239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 711239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 712239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 713239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 714239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 715239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderskivoid CFGBuilder::addLocalScopeAndDtors(Stmt* S) { 716239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 717239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 718239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 719239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 72002acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 721239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 722239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 723239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 72453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// insertAutomaticObjDtors - Insert destructor CFGElements for variables with 72553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// automatic storage duration to CFGBlock's elements vector. Insertion will be 72653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// performed in place specified with iterator. 72753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I, 72853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) { 72953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski BumpVectorContext& C = cfg->getBumpVectorContext(); 73053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski I = Blk->beginAutomaticObjDtorsInsert(I, B.distance(E), C); 73153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski while (B != E) 73253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski I = Blk->insertAutomaticObjDtor(I, *B++, S); 73353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 73453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 73553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// appendAutomaticObjDtors - Append destructor CFGElements for variables with 73653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// automatic storage duration to CFGBlock's elements vector. Elements will be 73753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// appended to physical end of the vector which happens to be logical 73853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// beginning. 73953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::appendAutomaticObjDtors(CFGBlock* Blk, 74053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) { 74153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski insertAutomaticObjDtors(Blk, Blk->begin(), B, E, S); 74253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 74353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 74453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 74553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 74653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 74753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 74853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 74953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk, 75053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 75153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski insertAutomaticObjDtors(Blk, Blk->end(), B, E, Blk->getTerminator()); 75253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 75353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 7544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 7556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 7566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 757852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 7584f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenektryAgain: 759f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 760f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 761f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 762f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 7634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 7644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 765852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 7664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 7674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 768852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 7691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 771852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 7721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 774852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBlockExpr(cast<BlockExpr>(S), asc); 7754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 7764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 7774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 7781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 780a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 781852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 7821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 7844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 7854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 7864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 787852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 7881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 7904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 7911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 793852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 7941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 7964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 7971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 798021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 799021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 800021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 8018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXExprWithTemporariesClass: 8028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXExprWithTemporaries(cast<CXXExprWithTemporaries>(S), asc); 80347e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 804a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXBindTemporaryExprClass: 805a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); 806a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 80781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXConstructExprClass: 80881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); 80981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 810a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXFunctionalCastExprClass: 811a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); 812a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 81381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXTemporaryObjectExprClass: 81481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); 81581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 816c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu case Stmt::CXXMemberCallExprClass: 817c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc); 818c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu 819021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 820021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 821ad5a894df1841698c824381b414630799adc26caTed Kremenek 822021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 823021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 824ad5a894df1841698c824381b414630799adc26caTed Kremenek 8254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 8264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 8271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 8294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 8301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 8324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 8331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 8354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 8361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 8384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 8391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 8414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 8421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 843a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::ImplicitCastExprClass: 844a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); 845a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 8464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 8474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 8481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 8504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 8511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 852115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 853115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 854115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 8554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 8561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 8571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 8594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 8601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 8624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 8631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 8654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 8661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 8684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 8691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ParenExprClass: 8714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek S = cast<ParenExpr>(S)->getSubExpr(); 8721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump goto tryAgain; 8731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::NullStmtClass: 8754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 8761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 8784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 8791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SizeOfAlignOfExprClass: 881852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), asc); 8821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 884852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 8851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 8874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 8881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 8904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 8914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 8924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 8931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 894852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 895852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 8964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 897852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, S, asc); 8986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 8991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 9014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 9026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 9044f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) { 9054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = Block; 9064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (Stmt::child_iterator I = Terminator->child_begin(), 9074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek E = Terminator->child_end(); I != E; ++I) { 9084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (*I) B = Visit(*I); 9096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 9104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return B; 9114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 9121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 913852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 914852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 9154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 9166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 917852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 9184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 919852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, A, asc); 9206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 9216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 9234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 9241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 925852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 926852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 9274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (B->isLogicalOp()) { // && or || 9284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 929852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, B, asc); 9301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 931d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 9324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 9331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the LHS 9354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* LHSBlock = createBlock(false); 9364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LHSBlock->setTerminator(B); 9371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the RHS 9394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = ConfluenceBlock; 9404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = NULL; 9414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* RHSBlock = addStmt(B->getRHS()); 942862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 943862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek if (RHSBlock) { 944d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 945862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek return 0; 946862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 947862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek else { 948862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // Create an empty block for cases where the RHS doesn't require 949862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // any explicit statements in the CFG. 950862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek RHSBlock = createBlock(); 951862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 9521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 95300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 954941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal = TryEvaluateBool(B->getLHS()); 9552de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr)) 956941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek KnownVal.negate(); 95700998a068e50945118f334c98af05ed44d7c22a6Mike Stump 9584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now link the LHSBlock with RHSBlock. 9592de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LOr) { 960ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 961ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 9621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else { 9632de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LAnd); 964ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 965ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 96619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 9671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Generate the blocks for evaluating the LHS. 9694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = LHSBlock; 9704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 9711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 9722de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall else if (B->getOpcode() == BO_Comma) { // , 9736dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 974852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, B, asc); 9754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 9764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 9776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 978fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu else if (B->isAssignmentOp()) { 979fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (asc.alwaysAdd()) { 980fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 981fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu AppendStmt(Block, B, asc); 982fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 983ad5a894df1841698c824381b414630799adc26caTed Kremenek 984e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski Visit(B->getLHS(), AddStmtChoice::AsLValueNotAlwaysAdd); 985e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 986fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 9871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 988e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski if (asc.alwaysAdd()) { 989e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 990e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski AppendStmt(Block, B, asc); 991e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 992e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 993a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *RBlock = Visit(B->getRHS()); 994a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *LBlock = Visit(B->getLHS()); 995a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr 996a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // containing a DoStmt, and the LHS doesn't create a new block, then we should 997a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // return RBlock. Otherwise we'll incorrectly return NULL. 998a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu return (LBlock ? LBlock : RBlock); 9994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1001852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { 1002852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 1003721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 1004852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, E, asc); 1005721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 1006721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 10074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1008cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 10094f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 10104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 10114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 1012d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1013d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 10141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 10164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 10174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 10181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 10204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 1021f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (BreakJumpTarget.Block) { 1022fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, BreakJumpTarget.ScopePos, B); 1023f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(Block, BreakJumpTarget.Block); 1024f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 10254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 10261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 10294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10314c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stumpstatic bool CanThrow(Expr *E) { 10324c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 10334c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 10344c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 10354c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 10364c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 1037ad5a894df1841698c824381b414630799adc26caTed Kremenek 10384c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 10394c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 10404c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 10414c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Proto->hasEmptyExceptionSpec()) 10424c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 10434c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 10444c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 10454c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 10464c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1047852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 10484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If this is a call to a no-return function, this stops the block here. 10492455636163fdd18581d7fdae816433f886d88213Mike Stump bool NoReturn = false; 1050264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) { 10512455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 10522455636163fdd18581d7fdae816433f886d88213Mike Stump } 10532455636163fdd18581d7fdae816433f886d88213Mike Stump 10544c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 1055079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1056079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 1057079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Context->getLangOptions().Exceptions) { 10586c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 10594c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 1060079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 1061079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1062079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 10632455636163fdd18581d7fdae816433f886d88213Mike Stump if (FD->hasAttr<NoReturnAttr>()) 10642455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 1065079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 10664c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 1067079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 10682455636163fdd18581d7fdae816433f886d88213Mike Stump 10694c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (!CanThrow(C->getCallee())) 10704c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 10714c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1072fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (!NoReturn && !AddEHEdge) { 1073fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu if (asc.asLValue()) 1074fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu return VisitStmt(C, AddStmtChoice::AlwaysAddAsLValue); 1075fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu else 1076fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu return VisitStmt(C, AddStmtChoice::AlwaysAdd); 1077fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 10781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1079079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1080079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1081d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1082079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1083079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 10841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1085079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Block = createBlock(!NoReturn); 1086852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(Block, C, asc); 10872455636163fdd18581d7fdae816433f886d88213Mike Stump 1088079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (NoReturn) { 1089079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Wire this to the exit block directly. 1090079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, &cfg->getExit()); 1091079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 10924c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1093079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1094079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 1095079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, TryTerminatedBlock); 1096079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 1097079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump AddSuccessor(Block, &cfg->getExit()); 1098079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 10991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11002455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1101d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1102d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1103852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1104852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 11053fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 1106852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, C, asc); 1107d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 11083fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 11091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1110115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 1111115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AlwaysAdd; 1112115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 11133fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 11143fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 1115df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* LHSBlock = Visit(C->getLHS(), asc); 1116d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 11173fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 11181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11193fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 11203fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 1121df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* RHSBlock = Visit(C->getRHS(), asc); 1122d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 11233fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 11241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11253fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 112600998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1127941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(C->getCond()); 1128ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 1129ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 11303fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 11311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 11323fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 11331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11351eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { 1136fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 11371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CFGBlock* LastBlock = Block; 11384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 11394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 11404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1141334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1142334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1143334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1144334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 11451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1146e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1147e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 11481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1149079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 11504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 11514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1153852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C, 1154852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 1155f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1156f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 1157f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 1158852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AppendStmt(ConfluenceBlock, C, asc); 1159d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1160f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 11611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1162115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 1163115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AlwaysAdd; 1164115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1165f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1166f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1167f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1168f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1169f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1170f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1171f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek CFGBlock* LHSBlock = NULL; 1172f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek if (C->getLHS()) { 1173df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu LHSBlock = Visit(C->getLHS(), asc); 1174d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1175f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1176f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1177f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 11781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1179f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1180f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1181df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock* RHSBlock = Visit(C->getRHS(), asc); 1182d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1183f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 11841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1185f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1186f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 11871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 118800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1189941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(C->getCond()); 1190e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump if (LHSBlock) { 1191ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 1192e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } else { 1193941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek if (KnownVal.isFalse()) { 1194e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // If we know the condition is false, add NULL as the successor for 1195e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // the block containing the condition. In this case, the confluence 1196e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // block will have just one predecessor. 1197ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, 0); 1198941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(ConfluenceBlock->pred_size() == 1); 1199e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } else { 1200e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // If we have no LHS expression, add the ConfluenceBlock as a direct 1201e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // successor for the block containing the condition. Moreover, we need to 1202e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // reverse the order of the predecessors in the ConfluenceBlock because 1203e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // the RHSBlock will have been added to the succcessors already, and we 1204e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // want the first predecessor to the the block containing the expression 1205e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump // for the case when the ternary expression evaluates to true. 1206ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, ConfluenceBlock); 1207941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek assert(ConfluenceBlock->pred_size() == 2); 1208e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump std::reverse(ConfluenceBlock->pred_begin(), 1209e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ConfluenceBlock->pred_end()); 1210e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump } 1211f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 12121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1213ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1214f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 1215f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return addStmt(C->getCond()); 1216f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1217f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 12184f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 12198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (DS->isSingleDecl()) 12208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitDeclSubExpr(DS); 12211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 12231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy. 12254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek typedef llvm::SmallVector<Decl*,10> BufTy; 12264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BufTy Buf(DS->decl_begin(), DS->decl_end()); 12271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) { 12294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 12304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 12314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 12321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 12344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 12354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 12364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 12371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 12384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 12391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 12418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = VisitDeclSubExpr(DSNew); 12424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 12431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 12454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 12488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski/// DeclStmts and initializers in them. 12498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) { 12508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert(DS->isSingleDecl() && "Can handle single declarations only."); 1251d34066c224f782056c18f154abe04ef590473fd9Ted Kremenek 12528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 12531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!VD) { 12558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 12568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AppendStmt(Block, DS); 12574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 12588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 12591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 12618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 12628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 12638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 12648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 12654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 12668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 12678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = VD->getType()->isReferenceType(); 12688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski HasTemporaries = isa<CXXExprWithTemporaries>(Init); 12698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 12708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 12718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 12728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(cast<CXXExprWithTemporaries>(Init)->getSubExpr(), 12738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 12748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 12758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 12768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 12778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 12788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AppendStmt(Block, DS); 12791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 12818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc = IsReference 12828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ? AddStmtChoice::AsLValueNotAlwaysAdd 12838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski : AddStmtChoice::NotAlwaysAdd; 12848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (HasTemporaries) 12858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 12868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 12878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Visit(cast<CXXExprWithTemporaries>(Init)->getSubExpr(), asc); 12888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski else 12898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Visit(Init, asc); 12904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 12911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 12934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); VA != 0; 12944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA = FindVA(VA->getElementType().getTypePtr())) 12954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = addStmt(VA->getSizeExpr()); 12961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1297fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1298fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1299fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1300fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 13014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 1302d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1303fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 1304d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { 13056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 13066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 13076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 13086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 13096c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 13106c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 13116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 131204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 131304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 131404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 131504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 131604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 131704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 131804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (VarDecl* VD = I->getConditionVariable()) { 131904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 132004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 132104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 132204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 132304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 13246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The block we were proccessing is now finished. Make it the successor 13256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 13266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1327d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1328d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13294e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1330c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 13316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1332b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 1333d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ElseBlock = Succ; 13346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1335d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* Else = I->getElse()) { 1336d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 13376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1338d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 13396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1340d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 134104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 134204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 134304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 134404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 134504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 134604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 13474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 13486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1349b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1350b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 13514e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1352d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13534e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 13544e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1355c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 13566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1357b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 1358d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ThenBlock; 1359d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 1360d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Stmt* Then = I->getThen(); 13616db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1362d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 13636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 136404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 136504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 136604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 136704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 136804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 136904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 13704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 13716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1372dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1373dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1374dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1375dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1376dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 1377ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ThenBlock, sv.get()); 13786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1379d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13804e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 13816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 13820cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1383d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 13846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1385d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 13866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1387d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1388d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 13896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 139000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1391941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult &KnownVal = TryEvaluateBool(I->getCond()); 139200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1393d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 1394ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 1395ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 13966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 13976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 13986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 13996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 140061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek Block = addStmt(I->getCond()); 1401ad5a894df1841698c824381b414630799adc26caTed Kremenek 140261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 140361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 140461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 140561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 140661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 140761dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek AppendStmt(Block, I, AddStmtChoice::AlwaysAdd); 140861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek addStmt(Init); 140961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 141061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1411ad5a894df1841698c824381b414630799adc26caTed Kremenek 141261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek return Block; 1413d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 14146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1416d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) { 14176c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1418d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 14196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 14206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 14216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 14226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1423d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1424d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1425d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 14266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1427d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 1428fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 1429ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, &cfg->getExit()); 14306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 14326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1433852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1434d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 14350cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 1436d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) { 1437d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 14384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 14392677ea871a25aa79f9db360f6ed10584c02267adTed Kremenek CFGBlock* LabelBlock = Block; 14406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 14424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 14436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(LabelMap.find(L) == LabelMap.end() && "label already in map"); 1445f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LabelMap[ L ] = JumpTarget(LabelBlock, ScopePos); 14466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 14486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 14496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 14506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 14519cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1452d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14534e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 14546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1456d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 14576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1458d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1459d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 14606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1461d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1462d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 146331dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 1464d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) { 14656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 14666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 14674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1468d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1469d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 14706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 14716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1472d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 14736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1474d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1475d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1476f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1477f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1478f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 1479fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, JT.ScopePos, G); 1480f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(Block, JT.Block); 1481f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1482d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 14836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1484d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1485d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1486d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { 1487d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 14886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 148947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 149047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 149147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 149247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 149347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 149447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 149547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 149647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (Stmt* Init = F->getInit()) 149747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1498f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1499f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 150047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (VarDecl* VD = F->getConditionVariable()) 150147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 150247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 150347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 150447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 150547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1506fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1507fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1508d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1509d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15104e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1511d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 15124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 15134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 15146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15153f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 15163f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 1517f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 151847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 15193f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 15206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 15216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 15226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 152349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 152449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 15256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 152649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 15276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(F); 15286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 15306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 153149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = F->getCond()) { 153249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 153349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 15348f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek assert(Block == EntryConditionBlock || 15358f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek (Block == 0 && EntryConditionBlock == Succ)); 153658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek 153758b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // If this block contains a condition variable, add both the condition 153858b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // variable and initializer to the CFG. 153958b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (VarDecl *VD = F->getConditionVariable()) { 154058b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (Expr *Init = VD->getInit()) { 154158b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek autoCreateBlock(); 154258b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek AppendStmt(Block, F, AddStmtChoice::AlwaysAdd); 154358b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek EntryConditionBlock = addStmt(Init); 154458b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek assert(Block == EntryConditionBlock); 154558b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 154658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 1547ad5a894df1841698c824381b414630799adc26caTed Kremenek 15484e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1549d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15504e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 15514e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 155249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 1553d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 15546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 15556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 155649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 15576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 155800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1559941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal(true); 15601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 156100998a068e50945118f334c98af05ed44d7c22a6Mike Stump if (F->getCond()) 156200998a068e50945118f334c98af05ed44d7c22a6Mike Stump KnownVal = TryEvaluateBool(F->getCond()); 156300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1564d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1565d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 15666db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 15676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15683f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current values for Block, Succ, and continue targets. 1569f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1570f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 15716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1572af603f742491dc4707138c0293d295171fdd51baTed Kremenek // Create a new block to contain the (bottom) of the loop body. 1573af603f742491dc4707138c0293d295171fdd51baTed Kremenek Block = NULL; 157447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 157547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 157647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 15776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1578e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek if (Stmt* I = F->getInc()) { 15796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 15806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 15814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 15826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 15836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // No increment code. Create a special, empty, block that is used as the 15846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // target block for "looping back" to the start of the loop. 15853575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Succ == EntryConditionBlock); 158647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski Succ = Block ? Block : createBlock(); 1587e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 15886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15893575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 15903575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 15913575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1592d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15934e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 15943575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 15953575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 15966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 159747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 15986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15993575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // The starting block for the loop increment is the block that should 16003575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 1601f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget.Block->setLoopTarget(F); 16023575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 160347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 160447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 160547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 160647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 160747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 16086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 16096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 16104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(F->getBody()); 1611af603f742491dc4707138c0293d295171fdd51baTed Kremenek 1612af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 1613f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BodyBlock = ContinueJumpTarget.Block;//can happen for "for (...;...;...);" 1614d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 1615941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 16166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1617941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // This new body block is a successor to our "exit" condition block. 1618ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1619d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 16206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1621941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1622941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 1623ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 16246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1625d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 16266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 1627d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* I = F->getInit()) { 1628d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 162949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 16306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 16316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There is no loop initialization. We are thus basically a while loop. 16326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NULL out Block to force lazy block construction. 16332bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek Block = NULL; 16345482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 163549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 16362bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 1637d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1638d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1639115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 1640115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek if (asc.alwaysAdd()) { 1641115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 1642115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek AppendStmt(Block, M, asc); 1643115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 1644115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return Visit(M->getBase(), 1645115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek M->isArrow() ? AddStmtChoice::NotAlwaysAdd 1646115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek : AddStmtChoice::AsLValueNotAlwaysAdd); 1647115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 1648115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1649514de5a21645900c92cf4f4f7313d6f66945d134Ted KremenekCFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 1650514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 1651514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 1652514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1653514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 1654514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1655514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1656514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1657514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 1658514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 1659514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1660514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 16614cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 1662514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 1663514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 1664514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 1665514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 1666514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1667514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 1668514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 1669514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1670514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 1671514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1672514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 1673514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 1674514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1675514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1676514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 16776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 16786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 16796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 1680514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 16816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1682514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek CFGBlock* LoopSuccessor = 0; 16836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1684514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 1685d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16864e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1687514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 1688514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 16894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 16904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 16916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16924cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 16934cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 16944cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 16956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16964cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 16976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 16986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 17006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 17016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 1702ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(ExitConditionBlock, S); 17034cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 17046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17054cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 17066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // generate new blocks as necesary. We DON'T add the statement by default to 17076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 1708852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd); 17096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1710d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17114e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17124e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 17134e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 17146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 17166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 17174cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 17186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17194cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 17206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 17214cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 1722f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Succ(Succ); 1723f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1724f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 17256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1726f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 1727f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 17286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(S->getBody()); 17306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17314cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 17324cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" 17334e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1734d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17354e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17364e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 17376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17384cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 1739ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, BodyBlock); 17404cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 17416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17424cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 17434cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 1744ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, LoopSuccessor); 17454cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 1746514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 17474cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 1748514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 17496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 17506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1751b3b0b3624e462c2940f65b86e773bfc300005203Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) { 1752b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 17536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1754b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 17554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 17566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1757da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 1758da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 1759da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 1760d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1761da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 17626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1763da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 1764fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 1765da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 17666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17674beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 17684beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 17694beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek AppendStmt(Block, S, AddStmtChoice::AlwaysAdd); 17704beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 1771b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 17724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 1773b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 17746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1775e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) { 17764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 177790658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 1778e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 1779514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 1780d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { 1781d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 17826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 178305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 178405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 178505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 178605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 178705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 178805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 1789f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 179005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (VarDecl* VD = W->getConditionVariable()) { 179105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 179205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 179305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 1794f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1795fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 1796fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1797d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1798d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17994e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1800d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 18014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 18024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 18036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 18056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 18066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 180749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 180849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 18096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 181049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 181149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek ExitConditionBlock->setTerminator(W); 18126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 18146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. Thus we update 18156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "Succ" after adding the condition. 181649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = W->getCond()) { 181749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 181849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 1819a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // The condition might finish the current 'Block'. 1820a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu Block = EntryConditionBlock; 1821ad5a894df1841698c824381b414630799adc26caTed Kremenek 18224ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // If this block contains a condition variable, add both the condition 18234ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // variable and initializer to the CFG. 18244ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 18254ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (Expr *Init = VD->getInit()) { 18264ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek autoCreateBlock(); 18274ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek AppendStmt(Block, W, AddStmtChoice::AlwaysAdd); 18284ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek EntryConditionBlock = addStmt(Init); 18294ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek assert(Block == EntryConditionBlock); 18304ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 18314ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 18324ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek 18334e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1834d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18354e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18364e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 183749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 18386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 18406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 184149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 18426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 184300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1844941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult& KnownVal = TryEvaluateBool(W->getCond()); 184500998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1846d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 1847d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 1848f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 1849d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1850d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 1851f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1852f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1853f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 1854f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 18556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 18566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 1857f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Block = 0; 1858f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Succ == EntryConditionBlock); 1859f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ = createBlock(); 1860f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ->setLoopTarget(W); 1861f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 18626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1863d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 186405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 18656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1866d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 1867f752fcfae84fbf21b78383bf2461633382d51844Ted Kremenek Block = NULL; 18686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 186905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 187005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 187105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 187205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 187305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 187405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 187505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 187605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 1877d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 18784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(W->getBody()); 18796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1880af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 1881f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BodyBlock = ContinueJumpTarget.Block; // can happen for "while(...) ;" 18824e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1883d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18844e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18854e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 18866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1887941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 1888ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1889bf15b278a439d73b605ec00a8d3977ef305712f4Ted Kremenek } 18906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1891941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1892941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 1893ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 18946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 18966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 1897d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 18986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18994ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 19005482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 190149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 1902d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 19031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19054f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) { 19064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 19074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 19084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 19094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 19106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19112fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) { 19122fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 19132fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 19146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19156c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1916d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 19186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19192fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 19202fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 19216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19222fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 1923ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, &cfg->getExit()); 19246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 19266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 1927852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 19282fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 1929989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 19300979d80615df97c675423de631c1b884819f4712Mike StumpCFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) { 19316c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1932d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19330979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 19340979d80615df97c675423de631c1b884819f4712Mike Stump 19350979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 19360979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 19370979d80615df97c675423de631c1b884819f4712Mike Stump 19385d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 19395d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 19405d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump AddSuccessor(Block, TryTerminatedBlock); 1941ad5a894df1841698c824381b414630799adc26caTed Kremenek else 19425d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 19435d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump AddSuccessor(Block, &cfg->getExit()); 19440979d80615df97c675423de631c1b884819f4712Mike Stump 19450979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 19460979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 1947852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 19480979d80615df97c675423de631c1b884819f4712Mike Stump} 19490979d80615df97c675423de631c1b884819f4712Mike Stump 19504f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) { 1951d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 19526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19538f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 19548f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 1955d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1956d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19574e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1958d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 19594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 19604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 19616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 19636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 19646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 196549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 196649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 19676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 196849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 19696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 19706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 19726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 197349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = D->getCond()) { 197449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 197549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 19764e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1977d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19784e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19794e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 198049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 19816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19825482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 198349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 198449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 198500998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1986941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek const TryResult &KnownVal = TryEvaluateBool(D->getCond()); 198700998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1988d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 198949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* BodyBlock = NULL; 1990d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 19916db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 19926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1993d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 1994f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1995f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1996f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 19976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1998d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 1999f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 20006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2001d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 2002f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 20036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2004d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2005b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 20066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 200705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 200805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 200905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 201005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 201105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2012d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 20134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 20146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2015af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 2016a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 20174e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2018d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20194e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20204e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 20216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2022d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 2023d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 2024d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 2025d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 2026d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 2027d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 2028d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 2029d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 2030d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 2031d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 2032d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 2033d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 2034d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek AddSuccessor(ExitConditionBlock, LoopBackBlock); 2035d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 2036d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 2037d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek AddSuccessor(ExitConditionBlock, NULL); 2038b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 20396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2040941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 2041941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 2042ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 20436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 20456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 2046d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 20476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2048d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 20495482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 2050d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 2051d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2052d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2053d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) { 2054d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 2055d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 2056d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2057d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 20586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2059d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 2060d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 2061d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 20626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2063d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 2064235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 2065f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (ContinueJumpTarget.Block) { 2066fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, ContinueJumpTarget.ScopePos, C); 2067f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AddSuccessor(Block, ContinueJumpTarget.Block); 2068f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 2069235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 20706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2071d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 2072d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 20731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 207413fc08a323b29dd97a46def1e3a15bf082476efaTed KremenekCFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, 2075852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 207613fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 2077852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 207813fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2079ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, E); 208013fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 20811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 20834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 20844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr()); 20854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 20864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(VA->getSizeExpr()); 20874e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 20881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 2090d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 20911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 20934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 2094852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 2095852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek if (asc.alwaysAdd()) { 209613fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2097ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AppendStmt(Block, SE); 209813fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 20994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 21004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2101d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2102411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { 21036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 21046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 2105d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* SwitchSuccessor = NULL; 21066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21078ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 21088ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 21098ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 21108ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 21118ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 21128ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 21138ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (VarDecl* VD = Terminator->getConditionVariable()) { 21148ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 21158ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 21168ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 21178ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 21188ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2119d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2120d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21214e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2122d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 21236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2124d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2125d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2126d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2127eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2128f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2129eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 21306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 21316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 21326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2133eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 21346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2135d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2136d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 21376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2138d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2139d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2140d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2141f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 21426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 21446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 21456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 21466db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 214749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 21488ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 21498ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 21508ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 21518ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 21528ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 21538ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2154d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 21554e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2156d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21574e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21584e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 215949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 21606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 21616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // following the switch body. 2162ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(SwitchTerminatedBlock, DefaultCaseBlock); 21636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 216449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2165411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 21666db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 2167d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 21686b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek Block = addStmt(Terminator->getCond()); 2169ad5a894df1841698c824381b414630799adc26caTed Kremenek 21706b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 21716b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 21726b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 21736b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 21746b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 21756b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek AppendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd); 21766b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek addStmt(Init); 21776b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 21786b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2179ad5a894df1841698c824381b414630799adc26caTed Kremenek 21806b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek return Block; 2181d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2182d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 21834f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) { 21846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 21856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 21860fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 21870fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 21880fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 21890fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 21900fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 21910fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 21920fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 21930fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *CurrentBlock = createBlock(false); 21940fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CurrentBlock->setLabel(CS); 21950fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 21960fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 21970fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(LastBlock, CurrentBlock); 21980fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 21990fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek TopBlock = CurrentBlock; 22000fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 22010fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(SwitchTerminatedBlock, CurrentBlock); 22020fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek LastBlock = CurrentBlock; 22030fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 22040fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 22050fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 22060fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 220729ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 22080fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 22090fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 22101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 221129ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek CFGBlock* CaseBlock = Block; 22124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 22134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 22146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 22166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 22174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 22184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2219d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22204e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 22216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 22236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 22244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2225ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(SwitchTerminatedBlock, CaseBlock); 22266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2227d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2228d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 22296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22300fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 22310fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek AddSuccessor(LastBlock, CaseBlock); 22320fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 22330fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 22340fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else { 22350fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 22360fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 22370fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 22386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22390fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2240d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 22416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2242411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) { 22434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 22444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 22451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2246eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 22474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 22484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 22494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 22506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 22526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2253411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 22541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2255d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22564e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2257eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 22586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 22596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 22606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 22616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 22626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 22636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2264eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2265eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 22666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2267eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2268eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 22696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2271295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2272d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 22735d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 22745d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 22755d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 22765d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* TrySuccessor = NULL; 22775d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22785d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2279d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22805d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 22815d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 22825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 22835d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2284a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 22855d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 22865d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2287f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 22885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2289f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 22905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2291a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 22925d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 22935d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 22945d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 22955d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2296a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2297a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2298a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 22995d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 23005d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 23015d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 23025d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 23035d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 23045d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 2305f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, CatchBlock); 23065d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2307a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2308a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 2309f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2310a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 2311f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump AddSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2312a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 23135d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23145d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 23155d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 23165d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2317f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2318f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock); 2319f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump TryTerminatedBlock = NewTryTerminatedBlock; 2320f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 23216db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 23225d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 23233fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek Block = addStmt(Terminator->getTryBlock()); 23245d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return Block; 23255d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 23265d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23275d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) { 23285d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 23295d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 23305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23310e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 23320e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 23330e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 23340e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 23350e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 23360e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 23370e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski if (VarDecl* VD = CS->getExceptionDecl()) { 23380e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 23390e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 23400e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 23410e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 23420e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 23435d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 23445d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 23455d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23465d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* CatchBlock = Block; 23475d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 23485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 23495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23505d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 23515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2352d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23535d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 23545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23555d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 23565d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 23575d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23585d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 23595d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 23605d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 23618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E, 23628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc) { 23638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors) { 23648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If adding implicit destructors visit the full expression for adding 23658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // destructors of temporaries. 23668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(E->getSubExpr()); 23678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 23688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Full expression has to be added as CFGStmt so it will be sequenced 23698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before destructors of it's temporaries. 23708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski asc = asc.asLValue() 23718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ? AddStmtChoice::AlwaysAddAsLValue 23728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski : AddStmtChoice::AlwaysAdd; 23738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 23748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(E->getSubExpr(), asc); 23758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 23768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 2377a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 2378a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 2379a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu if (asc.alwaysAdd()) { 2380a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2381a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AppendStmt(Block, E, asc); 2382a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 2383a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 2384a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu asc = AddStmtChoice(asc.asLValue() ? AddStmtChoice::AsLValueNotAlwaysAdd 2385a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu : AddStmtChoice::NotAlwaysAdd); 2386a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2387a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2388a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2389a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 239081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, 239181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 239281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 239381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu : AddStmtChoice::AlwaysAdd; 239481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 239581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AppendStmt(Block, C, AddStmtChoice(K)); 239681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 239781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 239881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2399a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 2400a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 2401a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu if (asc.alwaysAdd()) { 2402a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2403a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AppendStmt(Block, E, asc); 2404a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 2405a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu asc = AddStmtChoice(asc.asLValue() ? AddStmtChoice::AsLValueNotAlwaysAdd 2406a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu : AddStmtChoice::NotAlwaysAdd); 2407a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2408a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2409a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2410a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 241181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 241281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 241381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 241481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu : AddStmtChoice::AlwaysAdd; 241581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 241681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AppendStmt(Block, C, AddStmtChoice(K)); 241781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 241881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 241981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2420ad5a894df1841698c824381b414630799adc26caTed KremenekCFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C, 2421c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu AddStmtChoice asc) { 2422ad5a894df1841698c824381b414630799adc26caTed Kremenek AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue 242321f6d6ea71b89aeae6b9262c8cbdff7f6328e749Zhongxing Xu : AddStmtChoice::AlwaysAdd; 2424c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu autoCreateBlock(); 242521f6d6ea71b89aeae6b9262c8cbdff7f6328e749Zhongxing Xu AppendStmt(Block, C, AddStmtChoice(K)); 2426c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu return VisitChildren(C); 2427c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu} 2428c5354a2ecd9fdd7f2c0eb784f7932fb5126e2a01Zhongxing Xu 2429a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, 2430a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 2431a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu if (asc.alwaysAdd()) { 2432a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2433a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AppendStmt(Block, E, asc); 2434a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 2435a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu asc = AddStmtChoice(asc.asLValue() ? AddStmtChoice::AsLValueNotAlwaysAdd 2436a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu : AddStmtChoice::NotAlwaysAdd); 2437a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2438a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2439a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2440a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 244119bb356317952445b03ee341c02f6147083c9eeaTed KremenekCFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) { 24426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 244319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek CFGBlock* IBlock = cfg->getIndirectGotoBlock(); 24446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 244519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 244619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 244719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 244819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 24496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 245019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 245119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 2452d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 24544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 245519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 245619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 2457ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek AddSuccessor(Block, IBlock); 245819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 245919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 246019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 24618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) { 24628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskitryAgain: 24638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!E) { 24648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski badCFG = true; 24658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 24668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 24678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski switch (E->getStmtClass()) { 24688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski default: 24698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitChildrenForTemporaryDtors(E); 24708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 24718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::BinaryOperatorClass: 24728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E)); 24738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 24748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXBindTemporaryExprClass: 24758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXBindTemporaryExprForTemporaryDtors( 24768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<CXXBindTemporaryExpr>(E), BindToTemporary); 24778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 24788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ConditionalOperatorClass: 24798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitConditionalOperatorForTemporaryDtors( 24808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<ConditionalOperator>(E), BindToTemporary); 24818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 24828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ImplicitCastExprClass: 24838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For implicit cast we want BindToTemporary to be passed further. 24848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<CastExpr>(E)->getSubExpr(); 24858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 24868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 24878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ParenExprClass: 24888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<ParenExpr>(E)->getSubExpr(); 24898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 24908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 24918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 24928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 24938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { 24948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // When visiting children for destructors we want to visit them in reverse 24958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. Because there's no reverse iterator for children must to reverse 24968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // them in helper vector. 24978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski typedef llvm::SmallVector<Stmt *, 4> ChildrenVect; 24988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ChildrenVect ChildrenRev; 24998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski for (Stmt::child_iterator I = E->child_begin(), L = E->child_end(); 25008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski I != L; ++I) { 25018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (*I) ChildrenRev.push_back(*I); 25028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 25038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = Block; 25058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(), 25068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski L = ChildrenRev.rend(); I != L; ++I) { 25078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (CFGBlock *R = VisitForTemporaryDtors(*I)) 25088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = R; 25098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 25108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 25118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 25128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { 25148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->isLogicalOp()) { 25158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors for temporaries in LHS expression should be called after 25168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // those for RHS expression. Even if this will unnecessarily create a block, 25178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // this block will be used at least by the full expression. 25188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 25198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); 25208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 25218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 25228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 25248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 25258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 25268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (RHSBlock) { 25288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 25298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 25308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If RHS expression did produce destructors we need to connect created 25328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // blocks to CFG in same manner as for binary operator itself. 25338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = createBlock(false); 25348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock->setTerminator(CFGTerminator(E, true)); 25358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For binary operator LHS block is before RHS in list of predecessors 25378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // of ConfluenceBlock. 25388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), 25398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConfluenceBlock->pred_end()); 25408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 25428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski TryResult KnownVal = TryEvaluateBool(E->getLHS()); 25438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) 25448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski KnownVal.negate(); 25458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Link LHSBlock with RHSBlock exactly the same way as for binary operator 25478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // itself. 25488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getOpcode() == BO_LOr) { 25498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 25508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 25518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 25528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert (E->getOpcode() == BO_LAnd); 25538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 25548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 25558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 25568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = LHSBlock; 25588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock; 25598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 25608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 25628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return ConfluenceBlock; 25638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 25648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski else if (E->isAssignmentOp()) { 25668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For assignment operator (=) LHS expression is visited 25678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before RHS expression. For destructors visit them in reverse order. 25688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 25698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 25708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock ? LHSBlock : RHSBlock; 25718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 25728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For any other binary operator RHS expression is visited before 25748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // LHS expression (order of children). For destructors visit them in reverse 25758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. 25768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 25778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 25788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return RHSBlock ? RHSBlock : LHSBlock; 25798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 25808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( 25828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *E, bool BindToTemporary) { 25838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for temporaries in subexpression. 25848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr()); 25858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!BindToTemporary) { 25868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If lifetime of temporary is not prolonged (by assigning to constant 25878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // reference) add destructor for it. 25888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 25898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendTemporaryDtor(Block, E); 25908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = Block; 25918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 25928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 25938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 25948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 25958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( 25968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConditionalOperator *E, bool BindToTemporary) { 25978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for condition expression. Even if this will 25988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // unnecessarily create a block, this block will be used at least by the full 25998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // expression. 26008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 26018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); 26028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 26038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 26048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for LHS expression. 26068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = NULL; 26078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getLHS()) { 26088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 26098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 26108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock = VisitForTemporaryDtors(E->getLHS(), BindToTemporary); 26118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 26128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 26138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 26148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for RHS expression; 26168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 26178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 26188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS(), BindToTemporary); 26198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 26208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 26218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock && !LHSBlock) { 26238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If neither LHS nor RHS expression had temporaries to destroy don't create 26248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // more blocks. 26258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 26268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 26278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 26288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = createBlock(false); 26308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block->setTerminator(CFGTerminator(E, true)); 26318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 26338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski const TryResult &KnownVal = TryEvaluateBool(E->getCond()); 26348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (LHSBlock) { 26368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 26378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (KnownVal.isFalse()) { 26388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(Block, NULL); 26398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 26408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(Block, ConfluenceBlock); 26418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); 26428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 26438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock) 26458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski RHSBlock = ConfluenceBlock; 26468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 26478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 26498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 26508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 2651befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 2652026473c2175424a039f51ca8949937268721b965Ted Kremenek 26536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 26546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 26556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 26569438252ad2ecae5338df565ca33c6969e4fbfa41Ted KremenekCFGBlock* CFG::createBlock() { 2657026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 2658026473c2175424a039f51ca8949937268721b965Ted Kremenek 2659026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 2660ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 2661ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek new (Mem) CFGBlock(NumBlockIDs++, BlkBVC); 2662ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 2663026473c2175424a039f51ca8949937268721b965Ted Kremenek 2664026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 2665ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 2666ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 2667026473c2175424a039f51ca8949937268721b965Ted Kremenek 2668026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 2669ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 2670026473c2175424a039f51ca8949937268721b965Ted Kremenek} 2671026473c2175424a039f51ca8949937268721b965Ted Kremenek 2672026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 2673026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 2674b978a441c7d8bf59e7fede938e1f3b672573b443Mike StumpCFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C, 26756c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek BuildOptions BO) { 2676fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBuilder Builder; 26776c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek return Builder.buildCFG(D, Statement, C, BO); 2678fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 2679fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 268063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 268163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek// CFG: Queries for BlkExprs. 268263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 268363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 268463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremeneknamespace { 268586946745225096243f6969dc745267b78fc211a6Ted Kremenek typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy; 268663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 268763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 26888a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenekstatic void FindSubExprAssignments(Stmt *S, 26898a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek llvm::SmallPtrSet<Expr*,50>& Set) { 26908a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!S) 269133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return; 26926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26938a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) { 2694ad5a894df1841698c824381b414630799adc26caTed Kremenek Stmt *child = *I; 26958a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!child) 26968a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek continue; 2697ad5a894df1841698c824381b414630799adc26caTed Kremenek 26988a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(child)) 269933d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (B->isAssignmentOp()) Set.insert(B); 27006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27018a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek FindSubExprAssignments(child, Set); 270233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 270333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek} 270433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek 270563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekstatic BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { 270663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = new BlkExprMapTy(); 27076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Look for assignments that are used as subexpressions. These are the only 27096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // assignments that we want to *possibly* register as a block-level 27106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression. Basically, if an assignment occurs both in a subexpression and 27116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // at the block-level, it is a block-level expression. 271233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek llvm::SmallPtrSet<Expr*,50> SubExprAssignments; 27136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 271463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) 2715ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 2716b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (CFGStmt S = BI->getAs<CFGStmt>()) 2717b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu FindSubExprAssignments(S, SubExprAssignments); 271886946745225096243f6969dc745267b78fc211a6Ted Kremenek 2719411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { 27206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Iterate over the statements again on identify the Expr* and Stmt* at the 27226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block-level that are block-level expressions. 2723411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 2724b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { 2725b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu CFGStmt CS = BI->getAs<CFGStmt>(); 2726b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (!CS.isValid()) 2727b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu continue; 2728b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (Expr* Exp = dyn_cast<Expr>(CS.getStmt())) { 27296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2730411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { 273133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek // Assignment expressions that are not nested within another 27326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression are really "statements" whose value is never used by 27336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // another expression. 2734411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) 273533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek continue; 27366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (const StmtExpr* Terminator = dyn_cast<StmtExpr>(Exp)) { 27376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Special handling for statement expressions. The last statement in 27386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the statement expression is also a block-level expr. 2739411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek const CompoundStmt* C = Terminator->getSubStmt(); 274086946745225096243f6969dc745267b78fc211a6Ted Kremenek if (!C->body_empty()) { 274133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 274286946745225096243f6969dc745267b78fc211a6Ted Kremenek (*M)[C->body_back()] = x; 274386946745225096243f6969dc745267b78fc211a6Ted Kremenek } 274486946745225096243f6969dc745267b78fc211a6Ted Kremenek } 2745e2dcd783a04f654c50bd8b13fb08a440afbd67e7Ted Kremenek 274633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 2747411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek (*M)[Exp] = x; 274833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 2749b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 27506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2751411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek // Look at terminators. The condition is a block-level expression. 27526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2753ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Stmt* S = (*I)->getTerminatorCondition(); 27546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2755390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek if (S && M->find(S) == M->end()) { 2756411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek unsigned x = M->size(); 2757390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek (*M)[S] = x; 2758411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 2759411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 27606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 276186946745225096243f6969dc745267b78fc211a6Ted Kremenek return M; 276263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 276363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 276486946745225096243f6969dc745267b78fc211a6Ted KremenekCFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) { 276586946745225096243f6969dc745267b78fc211a6Ted Kremenek assert(S != NULL); 276663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } 27676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 276863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap); 276986946745225096243f6969dc745267b78fc211a6Ted Kremenek BlkExprMapTy::iterator I = M->find(S); 27703fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); 277163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 27727dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 277363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekunsigned CFG::getNumBlkExprs() { 277463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap)) 277563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return M->size(); 277663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek else { 277763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek // We assume callers interested in the number of BlkExprs will want 277863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek // the map constructed if it doesn't already exist. 277963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMap = (void*) PopulateBlkExprMap(*this); 278063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size(); 278163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek } 278263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 278363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 2784274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 2785ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 2786ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 2787ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2788ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 2789be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 2790ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2791ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (F.IgnoreDefaultsWithCoveredEnums) { 2792ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 2793ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 2794ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 27954ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { 2796ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 2797be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const Stmt *L = To->getLabel(); 2798be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 2799be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek return true; 2800ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 2801ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 2802ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 2803ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2804ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 2805ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 2806ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 2807ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 2808274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek// Cleanup: CFG dstor. 2809274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 2810274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek 281163f5887f316fb52d243fcbb3631c039de6c4b993Ted KremenekCFG::~CFG() { 281263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap); 281363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 28146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28157dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 28167dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 28177dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 28187dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 281942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 28202bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 2821ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 282242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 28231cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski typedef llvm::DenseMap<Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 282442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 28251cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 282642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek signed CurrentBlock; 282742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned CurrentStmt; 2828e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 282942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 28301c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 2831e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 2832e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner : CurrentBlock(0), CurrentStmt(0), LangOpts(LO) { 283342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 283442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 2835ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 28361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 28371cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (CFGStmt SE = BI->getAs<CFGStmt>()) { 28381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 28391cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMap[SE] = P; 28401cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (DeclStmt* DS = dyn_cast<DeclStmt>(SE.getStmt())) { 28421cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[DS->getSingleDecl()] = P; 28431cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28441cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (IfStmt* IS = dyn_cast<IfStmt>(SE.getStmt())) { 28451cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = IS->getConditionVariable()) 28461cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 28471cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28481cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (ForStmt* FS = dyn_cast<ForStmt>(SE.getStmt())) { 28491cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = FS->getConditionVariable()) 28501cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 28511cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28521cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (WhileStmt* WS = dyn_cast<WhileStmt>(SE.getStmt())) { 28531cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = WS->getConditionVariable()) 28541cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 28551cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28561cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (SwitchStmt* SS = dyn_cast<SwitchStmt>(SE.getStmt())) { 28571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = SS->getConditionVariable()) 28581cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 28591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (CXXCatchStmt* CS = dyn_cast<CXXCatchStmt>(SE.getStmt())) { 28611cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (VarDecl* VD = CS->getExceptionDecl()) 28621cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMap[VD] = P; 28631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 28641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 286542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 2866b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 2867fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 28686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 286942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 28706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2871e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 287242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek void setBlockID(signed i) { CurrentBlock = i; } 287342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek void setStmtID(unsigned i) { CurrentStmt = i; } 28746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28751cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski virtual bool handledStmt(Stmt* S, llvm::raw_ostream& OS) { 28761cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 2877fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 287842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 287942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 28806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock 28823fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek && I->second.second == CurrentStmt) { 288342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 28843fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 28856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28863fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 28871c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 288842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 28891cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28901cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski bool handleDecl(Decl* D, llvm::raw_ostream& OS) { 28911cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 28921cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28931cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 28941cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 28951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 28961cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock 28971cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski && I->second.second == CurrentStmt) { 28981cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 28991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 29001cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 29011cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 29021cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 29031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 290442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 2905e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 2906e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 2907e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 2908e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 2909ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 29106fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 29116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2912a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_ostream& OS; 291342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 2914d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 2915d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 2916d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper, 2917e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 2918d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 29196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2920d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitIfStmt(IfStmt* I) { 2921d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 2922d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 2923d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 29246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2925d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 29266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump void VisitStmt(Stmt* Terminator) { 29276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 29286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 29296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2930d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitForStmt(ForStmt* F) { 2931d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 29323fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 29333fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 2934535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 29353fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = F->getCond()) 29363fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 2937535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 29383fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 29393fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 2940a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 2941d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 29426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2943d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitWhileStmt(WhileStmt* W) { 2944d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 29453fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = W->getCond()) 29463fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 2947d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 29486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2949d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitDoStmt(DoStmt* D) { 2950d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 29513fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = D->getCond()) 29523fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 29539da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 29546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2955411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek void VisitSwitchStmt(SwitchStmt* Terminator) { 29569da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 2957d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 29589da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 29596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 29605d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump void VisitCXXTryStmt(CXXTryStmt* CS) { 29615d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 29625d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 29635d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2964805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitConditionalOperator(ConditionalOperator* C) { 2965d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 29666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 2967805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 29686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2969aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek void VisitChooseExpr(ChooseExpr* C) { 2970aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 2971d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 2972a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 2973aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 29746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 29751c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt* I) { 29761c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 2977d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 29781c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 29796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2980805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 2981805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 2982805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 2983805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 2984805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 29856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2986d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 29876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2988805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 29892de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 2990a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 2991805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 29922de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 2993a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 2994805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 2995805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 2996805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek assert(false && "Invalid logical operator."); 29976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 2998805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 29996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30000b1d9b7557437176f9cea1283bfac2510812beceTed Kremenek void VisitExpr(Expr* E) { 3001d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 30026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3003d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3004e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3005e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 30061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderskistatic void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, 3007079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 30081cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (CFGStmt CS = E.getAs<CFGStmt>()) { 30091cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Stmt *S = CS; 30101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 30111cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 30121cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 30131cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 30141cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) { 30151cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski CompoundStmt* Sub = SE->getSubStmt(); 30161cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 30171cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Sub->child_begin() != Sub->child_end()) { 30181cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 30191cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 30201cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 30211cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 30221cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 30231cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 30241cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 30251cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 30261cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 30271cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 30281cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 30291cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 30301cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 30311cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 30321c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 30331c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 30341cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 30356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 30371cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (OperatorCall)"; 30381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 30391cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else if (isa<CXXBindTemporaryExpr>(S)) { 30401cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (BindTemporary)"; 30416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 30426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30431cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 30441cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 30451cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 30464e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 30471cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (CFGInitializer IE = E.getAs<CFGInitializer>()) { 30481cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski CXXBaseOrMemberInitializer* I = IE; 30491cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 30501cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 30511cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << I->getMember()->getName(); 30526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30531cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 30541cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Expr* IE = I->getInit()) 30551cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 30561cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 30571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 30581cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 30591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 30601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 30611cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 30621cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } else if (CFGAutomaticObjDtor DE = E.getAs<CFGAutomaticObjDtor>()){ 30631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski VarDecl* VD = DE.getVarDecl(); 30641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 30651cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3066b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski const Type* T = VD->getType().getTypePtr(); 30671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 30681cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 3069b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski else if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 3070b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski T = ET; 30711cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 30721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 30731cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 30747c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 30757c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } else if (CFGBaseDtor BE = E.getAs<CFGBaseDtor>()) { 30767c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXBaseSpecifier *BS = BE.getBaseSpecifier(); 30777c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 30784e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 30797c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 30807c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } else if (CFGMemberDtor ME = E.getAs<CFGMemberDtor>()) { 30817c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FieldDecl *FD = ME.getFieldDecl(); 30828c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 30838c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski const Type *T = FD->getType().getTypePtr(); 30848c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 30858c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski T = ET; 30868c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 30877c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 30888c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; 30894e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 30908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (CFGTemporaryDtor TE = E.getAs<CFGTemporaryDtor>()) { 30928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *BT = TE.getBindTemporaryExpr(); 30938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()"; 30948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << " (Temporary object destructor)\n"; 30951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 309681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 30976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3098e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnerstatic void print_block(llvm::raw_ostream& OS, const CFG* cfg, 3099e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const CFGBlock& B, 3100e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper* Helper, bool print_edges) { 31016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 310242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(B.getBlockID()); 31036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31047dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 31056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << "\n [ B" << B.getBlockID(); 31066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 310742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 310842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (ENTRY) ]\n"; 310942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 311042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (EXIT) ]\n"; 311142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 31127dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OS << " (INDIRECT GOTO DISPATCH) ]\n"; 311342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 311442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " ]\n"; 31156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31169cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 3117079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) { 311842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 311942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 312042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 31216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3122079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (LabelStmt* L = dyn_cast<LabelStmt>(Label)) 31239cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 3124079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) { 31259cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 3126e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 3127e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 31289cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 31299cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 3130e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 3131e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 31329cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 3133079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 31349cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 3135079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 31365d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 3137a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 3138a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 3139a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 3140a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 3141a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 31425d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 31435d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 31445d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 314542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek assert(false && "Invalid label statement in CFGBlock."); 31466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31479cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 31489cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 31496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3150fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 3151fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 31526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 315342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 315442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 31556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31569cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 315742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 315842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 31596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3160a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 31616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 316242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 316342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 31646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31651cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski print_elem(OS,Helper,*I); 3166fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 31676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31689cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 316942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 317042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 317142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 31726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31739cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " T: "; 31746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 317542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 31766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3177e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, Helper, 3178e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 31794ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt())); 3180a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 3181fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 31826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31839cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 31849cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 318542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Predecessors (" << B.pred_size() << "):"; 31869cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek unsigned i = 0; 318742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 318842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 318942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 31906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 319142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) == 0) 31929cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 31936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31949cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " B" << (*I)->getBlockID(); 31959cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 31966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31979cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 31986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31999cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 320042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Successors (" << B.succ_size() << "):"; 32019cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek i = 0; 320242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 320342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 320442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 32056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 320642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) % 10 == 0) 32079cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 320842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3209e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump if (*I) 3210e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " B" << (*I)->getBlockID(); 3211e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump else 3212e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " NULL"; 3213fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 32146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32159cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 3216fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 32176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 321842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 321942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 322042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 3221e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); } 322242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 322342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 3224e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const { 3225e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 32266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 322742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 322842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getEntry(), &Helper, true); 32296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 323042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 323142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 323242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 3233ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 323442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 32356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3236ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek print_block(OS, this, **I, &Helper, true); 323742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 32386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 323942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 324042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getExit(), &Helper, true); 3241d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 32426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 324342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 324442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 3245e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const { 3246e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner print(llvm::errs(), cfg, LO); 3247e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 324842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 324942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 325042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 3251e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg, 3252e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LO) const { 3253e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 325442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, cfg, *this, &Helper, true); 3255026473c2175424a039f51ca8949937268721b965Ted Kremenek} 32567dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3257a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 3258e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::printTerminator(llvm::raw_ostream &OS, 32596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 3260e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 32614ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt())); 3262a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 3263a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 3264390e48b15ad93f85bfd1e33b9992c198fa0db475Ted KremenekStmt* CFGBlock::getTerminatorCondition() { 32654ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski Stmt *Terminator = this->Terminator; 3266411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 3267411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 32686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3269411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek Expr* E = NULL; 32706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3271411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 3272411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 3273411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 32746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3275411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 3276411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 3277411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 32786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3279411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 3280411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 3281411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 32826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3283411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 3284411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 3285411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 32866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3287411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 3288411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 3289411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 32906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3291411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 3292411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 3293411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 32946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3295411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 3296411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 3297411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 32986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3299411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 3300411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 3301411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 33026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3303411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 3304411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 3305411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 33066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3307411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 3308411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 3309390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 33106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3311390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 33126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 3313411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 33146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3315411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 3316411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 3317411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 33189c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenekbool CFGBlock::hasBinaryBranchTerminator() const { 33194ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski const Stmt *Terminator = this->Terminator; 33209c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek if (!Terminator) 33219c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return false; 33226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33239c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek Expr* E = NULL; 33246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33259c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek switch (Terminator->getStmtClass()) { 33269c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek default: 33279c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return false; 33286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump case Stmt::ForStmtClass: 33309c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::WhileStmtClass: 33319c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::DoStmtClass: 33329c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::IfStmtClass: 33339c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::ChooseExprClass: 33349c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::ConditionalOperatorClass: 33359c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek case Stmt::BinaryOperatorClass: 33366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return true; 33379c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek } 33386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33399c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek return E ? E->IgnoreParens() : NULL; 33409c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek} 33419c2535a35db35b3a821a0d0c36a01a16f52f1ad0Ted Kremenek 3342a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 33437dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 33447dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 33457dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 33467dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 334742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 334842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 33496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 335042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 335142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3352e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 335342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 3354e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 335542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 335642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 335742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 335842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 335942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 336042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 33617dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 33627dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 33637dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 3364006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 3365006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 3366006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 3367006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) { 33687dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3369bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 3370a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 3371a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 337242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(Out,Graph, *Node, GraphHelper, false); 3373a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 33747dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 33757dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 33767dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 33777dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 33787dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 33797dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 33807dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 33817dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 33827dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 33836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33847dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 3385bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 3386bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 3387bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 33887dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 33897dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 33907dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 3391