CFG.cpp revision ac73ea8c12772fd0dcec71b83c193a2837de7f8b
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" 20c56c004e0b8030e8ca8614e7febe581221938b75Ted Kremenek#include "clang/AST/CharUnits.h" 217dba8607e59096014b7139ff20ef00870041d518Ted Kremenek#include "llvm/Support/GraphWriter.h" 226cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Allocator.h" 236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Format.h" 246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/DenseMap.h" 256cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/SmallPtrSet.h" 260ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek#include "llvm/ADT/OwningPtr.h" 2783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 28fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenekusing namespace clang; 29fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 30fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremeneknamespace { 31fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 324afa39deaa245592977136d367251ee2c173dd8dDouglas Gregorstatic SourceLocation GetEndLoc(Decl* D) { 33c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek if (VarDecl* VD = dyn_cast<VarDecl>(D)) 34c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek if (Expr* Ex = VD->getInit()) 35c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek return Ex->getSourceRange().getEnd(); 366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return D->getLocation(); 37c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek} 38ad5a894df1841698c824381b414630799adc26caTed Kremenek 393179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenekclass CFGBuilder; 403179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 4194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// The CFG builder uses a recursive algorithm to build the CFG. When 4294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// we process an expression, sometimes we know that we must add the 4394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// subexpressions as block-level expressions. For example: 4494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// exp1 || exp2 4694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// When processing the '||' expression, we know that exp1 and exp2 4894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// need to be added as block-level expressions, even though they 4994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// might not normally need to be. AddStmtChoice records this 5094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then 5194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// the builder has an option not to add a subexpression as a 5294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// block-level expression. 5394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 54852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekclass AddStmtChoice { 55852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekpublic: 56892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; 575ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 5894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} 595ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 603179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek bool alwaysAdd(CFGBuilder &builder, 613179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek const Stmt *stmt) const; 6294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 6394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// Return a copy of this object, except with the 'always-add' bit 6494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// set as specified. 6594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { 663179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); 6794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan } 6894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 69852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekprivate: 7094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan Kind kind; 71852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek}; 726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 73f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope - Node in tree of local scopes created for C++ implicit 74f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// destructor calls generation. It contains list of automatic variables 75f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// declared in the scope and link to position in previous scope this scope 76f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// began in. 77f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 78f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// The process of creating local scopes is as follows: 79f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null), 80f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Before processing statements in scope (e.g. CompoundStmt) create 81f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope object using CFGBuilder::ScopePos as link to previous scope 82f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// and set CFGBuilder::ScopePos to the end of new scope, 8335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points 84f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// at this VarDecl, 85f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every normal (without jump) end of scope add to CFGBlock destructors 86f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// for objects in the current scope, 87f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every jump add to CFGBlock destructors for objects 88f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// between CFGBuilder::ScopePos and local scope position saved for jump 89f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// target. Thanks to C++ restrictions on goto jumps we can be sure that 90f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// jump target position will be on the path to root from CFGBuilder::ScopePos 91f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// (adding any variable that doesn't need constructor to be called to 92f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope can break this assumption), 93f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 94f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiclass LocalScope { 95f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 96fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek typedef BumpVector<VarDecl*> AutomaticVarsTy; 97f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 98f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// const_iterator - Iterates local scope backwards and jumps to previous 9935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski /// scope on reaching the beginning of currently iterated scope. 100f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski class const_iterator { 101f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const LocalScope* Scope; 102f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// VarIter is guaranteed to be greater then 0 for every valid iterator. 104f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Invalid iterator (with null Scope) has VarIter equal to 0. 105f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski unsigned VarIter; 106f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 107f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski public: 108f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create invalid iterator. Dereferencing invalid iterator is not allowed. 109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Incrementing invalid iterator is allowed and will result in invalid 110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// iterator. 111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator() 112f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(NULL), VarIter(0) {} 113f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create valid iterator. In case when S.Prev is an invalid iterator and 115f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// I is equal to 0, this will create invalid iterator. 116f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator(const LocalScope& S, unsigned I) 117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(&S), VarIter(I) { 118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Iterator to "end" of scope is not allowed. Handle it by going up 119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // in scopes tree possibly up to invalid iterator in the root. 120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0 && Scope) 121f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 124f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski VarDecl* const* operator->() const { 125f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (Scope && "Dereferencing invalid iterator is not allowed"); 126f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 127f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return &Scope->Vars[VarIter - 1]; 128f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 129f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski VarDecl* operator*() const { 130f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this->operator->(); 131f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 132f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 133f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator& operator++() { 134f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (!Scope) 135f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 136f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 137f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 138f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski --VarIter; 139f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0) 140f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 141f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 142f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 14335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator operator++(int) { 14435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator P = *this; 14535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski ++*this; 14635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return P; 14735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 148f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 149f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski bool operator==(const const_iterator& rhs) const { 150f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return Scope == rhs.Scope && VarIter == rhs.VarIter; 151f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 152f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski bool operator!=(const const_iterator& rhs) const { 153f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return !(*this == rhs); 154f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 15535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 15635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski operator bool() const { 15735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return *this != const_iterator(); 15835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 15935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 16035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int distance(const_iterator L); 161f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski }; 162f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 163f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski friend class const_iterator; 164f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 165f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiprivate: 166fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx; 167fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek 168f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Automatic variables in order of declaration. 169f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AutomaticVarsTy Vars; 170f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Iterator to variable in previous scope that was declared just before 171f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// begin of this scope. 172f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator Prev; 173f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 174f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 175f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Constructs empty scope linked to previous scope in specified place. 176fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek LocalScope(BumpVectorContext &ctx, const_iterator P) 177fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek : ctx(ctx), Vars(ctx, 4), Prev(P) {} 178f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 179f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Begin of scope in direction of CFG building (backwards). 180f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator begin() const { return const_iterator(*this, Vars.size()); } 18135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 18235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski void addVar(VarDecl* VD) { 183fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Vars.push_back(VD, ctx); 18435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 185f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 186f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 18735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// distance - Calculates distance from this to L. L must be reachable from this 18835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. 18935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// number of scopes between this and L. 19035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderskiint LocalScope::const_iterator::distance(LocalScope::const_iterator L) { 19135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int D = 0; 19235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator F = *this; 19335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski while (F.Scope != L.Scope) { 19435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski assert (F != const_iterator() 19535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski && "L iterator is not reachable from F iterator."); 19635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter; 19735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski F = F.Scope->Prev; 19835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 19935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter - L.VarIter; 20035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return D; 20135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski} 20235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 20335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// BlockScopePosPair - Structure for specifying position in CFG during its 20435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// build process. It consists of CFGBlock that specifies position in CFG graph 20535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// and LocalScope::const_iterator that specifies position in LocalScope graph. 206f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskistruct BlockScopePosPair { 2079ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BlockScopePosPair() : block(0) {} 2089ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BlockScopePosPair(CFGBlock* b, LocalScope::const_iterator scopePos) 2099ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek : block(b), scopePosition(scopePos) {} 210f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2119ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek CFGBlock *block; 2129ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek LocalScope::const_iterator scopePosition; 213f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 214f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 215e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// TryResult - a class representing a variant over the values 216e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, 217e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// and is used by the CFGBuilder to decide if a branch condition 218e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// can be decided up front during CFG construction. 219e71f3d587844110d836c82250830b27b1651afdbTed Kremenekclass TryResult { 220e71f3d587844110d836c82250830b27b1651afdbTed Kremenek int X; 221e71f3d587844110d836c82250830b27b1651afdbTed Kremenekpublic: 222e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 223e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult() : X(-1) {} 224e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 225e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isTrue() const { return X == 1; } 226e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isFalse() const { return X == 0; } 227e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isKnown() const { return X >= 0; } 228e71f3d587844110d836c82250830b27b1651afdbTed Kremenek void negate() { 229e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(isKnown()); 230e71f3d587844110d836c82250830b27b1651afdbTed Kremenek X ^= 0x1; 231e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 232e71f3d587844110d836c82250830b27b1651afdbTed Kremenek}; 233e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 234a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 235fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 236fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 237fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 238fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 239fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 240fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 241fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 242fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 2436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 2446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 2456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 2466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 247c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 248ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 249f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpTarget; 250f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpSource; 251f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 252e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 2530ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek llvm::OwningPtr<CFG> cfg; 254ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 255fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBlock* Block; 256fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek CFGBlock* Succ; 257f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget ContinueJumpTarget; 258f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget BreakJumpTarget; 259b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek CFGBlock* SwitchTerminatedBlock; 260eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek CFGBlock* DefaultCaseBlock; 2615d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* TryTerminatedBlock; 262e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 263f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Current position in local scope. 264f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 265f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 266f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // LabelMap records the mapping from Label expressions to their jump targets. 267ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy; 2680cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 2696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 2716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 272f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef std::vector<JumpSource> BackpatchBlocksTy; 2730cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 2746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 276ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy; 27719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 2786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27949b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu bool badCFG; 280b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &BuildOpts; 281e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 282e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // State to track for building switch statements. 283e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool switchExclusivelyCovered; 2840498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult *switchCond; 2850d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 2860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; 287a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek const Stmt *lastLookup; 28849b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu 2896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 290b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek explicit CFGBuilder(ASTContext *astContext, 291b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &buildOpts) 292b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek : Context(astContext), cfg(new CFG()), // crew a new CFG 293b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek Block(NULL), Succ(NULL), 294b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 295b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), 2960d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek switchExclusivelyCovered(false), switchCond(0), 297a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry(0), lastLookup(0) {} 2986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 299d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 300b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement); 3016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3020d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool alwaysAdd(const Stmt *stmt); 3030d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 3054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 306852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 307852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 308852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBlockExpr(BlockExpr* E, AddStmtChoice asc); 3094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 3107ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 3114765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, 3128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc); 3137ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 3147ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 315ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); 316a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 317a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 31881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); 319a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 320a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 32181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 32281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc); 323852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 3244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 325852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 3263fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 32756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, 32856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AddStmtChoice asc); 3293fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 3304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 3318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitDeclSubExpr(DeclStmt* DS); 3323fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 3333fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 3343fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 3354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt* G); 3364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 337a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); 3384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 3394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 340115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 3414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 3424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 3444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 3454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 3464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitReturnStmt(ReturnStmt* R); 347f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 348f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc); 349852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 3504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 35199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); 3524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 3534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 354852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 355852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 3564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitChildren(Stmt* S); 357cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 3588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Visitors to walk an AST and generate destructors of temporaries in 3598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // full expression. 3608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false); 3618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E); 3628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); 3638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, 3648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 36556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock * 36656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E, 36756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool BindToTemporary); 3688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 369274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 370274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek CFGBlock* NYS() { 3714102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 3724102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 3734102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 3746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 3764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 377d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 378df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 379df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 380852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 381cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt CFGBlock *addInitializer(CXXCtorInitializer *I); 3826a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 3836a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu LocalScope::const_iterator E, Stmt* S); 3847c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 385239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 386239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 387239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 388239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 38902acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu void addLocalScopeForStmt(Stmt* S); 390239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* addLocalScopeForDeclStmt(DeclStmt* DS, LocalScope* Scope = NULL); 391239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* addLocalScopeForVarDecl(VarDecl* VD, LocalScope* Scope = NULL); 392239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 393239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski void addLocalScopeAndDtors(Stmt* S); 394ad5a894df1841698c824381b414630799adc26caTed Kremenek 395239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 396d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek void appendStmt(CFGBlock *B, const Stmt *S) { 397a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (alwaysAdd(S)) 3980d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry->second = B; 3990d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 400ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose // All block-level expressions should have already been IgnoreParens()ed. 401ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); 402d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); 403ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 404cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { 40582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 40682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 4077c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 4087c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 4097c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4107c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 4117c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 4127c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { 4148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); 4158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 416ad5a894df1841698c824381b414630799adc26caTed Kremenek 41753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I, 41853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S); 41953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void appendAutomaticObjDtors(CFGBlock* Blk, LocalScope::const_iterator B, 42053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator E, Stmt* S); 42153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski void prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk, 42253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 42353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 4240a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void addSuccessor(CFGBlock *B, CFGBlock *S) { 425ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 426ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 4271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 428e71f3d587844110d836c82250830b27b1651afdbTed Kremenek /// Try and evaluate an expression to an integer constant. 429e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { 430e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 431e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return false; 432e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return !S->isTypeDependent() && 433f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek !S->isValueDependent() && 434f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek S->Evaluate(outResult, *Context); 435e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 4361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4370a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 43800998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 4390a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult tryEvaluateBool(Expr *S) { 44000998a068e50945118f334c98af05ed44d7c22a6Mike Stump Expr::EvalResult Result; 441e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!tryEvaluate(S, Result)) 442e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return TryResult(); 443e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 444e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (Result.Val.isInt()) 445e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return Result.Val.getInt().getBoolValue(); 446e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 447e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (Result.Val.isLValue()) { 4488cad3046be06ea73ff8892d947697a21d7a440d3Peter Collingbourne const Expr *e = Result.Val.getLValueBase(); 449e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const CharUnits &c = Result.Val.getLValueOffset(); 450e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!e && c.isZero()) 451e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return false; 452c56c004e0b8030e8ca8614e7febe581221938b75Ted Kremenek } 453941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return TryResult(); 45400998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 455e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 456d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 4576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4580d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekinline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, 4590d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const Stmt *stmt) const { 4600d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return builder.alwaysAdd(stmt) || kind == AlwaysAdd; 4610d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek} 462a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 4630d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekbool CFGBuilder::alwaysAdd(const Stmt *stmt) { 4640d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!BuildOpts.forcedBlkExprs) 4650d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return false; 466a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 467a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (lastLookup == stmt) { 468a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (cachedEntry) { 469a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry->first == stmt); 470a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek return true; 471a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 472a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek return false; 473a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 4740d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 475a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek lastLookup = stmt; 476a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 477a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // Perform the lookup! 4780d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; 4790d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 480a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (!fb) { 481a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // No need to update 'cachedEntry', since it will always be null. 482a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry == 0); 4830d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return false; 484a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 4850d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 4860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); 487a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (itr == fb->end()) { 488a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry = 0; 4890d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return false; 490a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 491a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 4920d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry = &*itr; 4930d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return true; 4943179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek} 4953179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 496898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 497898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 498f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCallstatic const VariableArrayType *FindVA(const Type *t) { 499f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { 500f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) 501610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 502610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 5036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 504610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 505610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 5066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 507610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 508610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 5096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 5116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 5126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 5136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 5146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 515b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted KremenekCFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement) { 5160ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 5174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 5184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 519d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 5206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 5216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 5226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 52349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 524ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 52549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 5266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5277c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 5287c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 5297c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 5307c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 531d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 5321b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 5331b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5341b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 5351b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 5361b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 53782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 538b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 53982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 54082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 54182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 54282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 54382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 54482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 545b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 5466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 54782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 54882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 54982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 5501b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 5511b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 5521b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 5531b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 554c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 5559ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek CFGBlock* B = I->block; 5561b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu GotoStmt* G = cast<GotoStmt>(B->getTerminator()); 5571b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 5586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5591b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 5601b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 5611b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 562d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 563f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 5649ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, 5659ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek JT.scopePosition); 5669ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, JT.block); 5671b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 5686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5691b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 5701b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (CFGBlock* B = cfg->getIndirectGotoBlock()) 5711b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 5721b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 5731b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5741b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 5751b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 5761b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5771b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 5781b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 5791b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 5801b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5819ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, LI->second.block); 582c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 5836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 585322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 5866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5871b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 588d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 5896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 590d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 591d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 5926d9828c82c9321f042ab416fd2ffaa3034347d45Mike StumpCFGBlock* CFGBuilder::createBlock(bool add_successor) { 5939438252ad2ecae5338df565ca33c6969e4fbfa41Ted Kremenek CFGBlock* B = cfg->createBlock(); 5944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 5950a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(B, Succ); 596d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 597d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 5986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 59982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 600cbb67480094b3bcb5b715acd827cbad55e2a204cSean HuntCFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { 60182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 60282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 60382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 6058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 60682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 6088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 6098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Expr *Init = I->getInit(); 6108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 61100eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet if (FieldDecl *FD = I->getAnyMember()) 6128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = FD->getType()->isReferenceType(); 6134765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 61482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 6168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 6174765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 6188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 6198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 62082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 6218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 6228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 6238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendInitializer(Block, I); 6248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 6258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 626892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek if (HasTemporaries) { 6278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 6288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 629892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 630892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek } 631892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(Init); 6328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 6338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 63482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 63582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 63682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 637239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 638239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 639239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 6406a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 6416a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu LocalScope::const_iterator E, Stmt* S) { 642239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 6436a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 6446a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 645239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 6466a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 647239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 648239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski autoCreateBlock(); 649239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski appendAutomaticObjDtors(Block, B, E, S); 650239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 651239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 6527c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 6537c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 6547c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 6557c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 6567c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 6577c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 6587c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 6597c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 6607c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 6617c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 6627c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 6637c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 6647c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 6657c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 6667c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6677c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6687c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 6697c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 6707c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 6717c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 6727c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!BI->isVirtual()) { 6737c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 6747c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 6757c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 6767c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, BI); 6777c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6787c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6797c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6807c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 6817c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 6827c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 6837c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 6848c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski // Check for constant size array. Set type to array element type. 6858c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QualType QT = FI->getType(); 6868c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 6878c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (AT->getSize() == 0) 6888c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski continue; 6898c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QT = AT->getElementType(); 6908c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski } 6918c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 6928c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 6937c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 6947c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 6957c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendMemberDtor(Block, *FI); 6967c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6977c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 6987c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 6997c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 700239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 701239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 702239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 703239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 704fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); 705fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Scope = alloc.Allocate<LocalScope>(); 706fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx(alloc); 707fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek new (Scope) LocalScope(ctx, ScopePos); 708239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 709239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 710239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 711239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 712239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 71302acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 71402acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xuvoid CFGBuilder::addLocalScopeForStmt(Stmt* S) { 715239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 71602acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 71702acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 71802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 719239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 720239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 721ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { 722239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 723239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 724ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner Stmt *SI = *BI; 725ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (LabelStmt *LS = dyn_cast<LabelStmt>(SI)) 726239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski SI = LS->getSubStmt(); 727ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) 728239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 729239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 73002acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 731239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 732239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 733239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 734239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 735ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (LabelStmt *LS = dyn_cast<LabelStmt>(S)) 736239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski S = LS->getSubStmt(); 737ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) 738b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 739239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 740239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 741239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 742239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 743239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt* DS, 744b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 745239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 746239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 747239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 748239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 749239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 750239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (VarDecl* VD = dyn_cast<VarDecl>(*DI)) 751239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 752239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 753239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 754239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 755239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 756239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 757239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 758239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 759239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl* VD, 760b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 761239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 762239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 763239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 764239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 765239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 766239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 767239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 768239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 769239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 770239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 771239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 772239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 773239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 774239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 775239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (const ReferenceType* RT = QT.getTypePtr()->getAs<ReferenceType>()) { 776239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QT = RT->getPointeeType(); 777239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!QT.isConstQualified()) 778239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 779239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!VD->getInit() || !VD->getInit()->Classify(*Context).isRValue()) 780239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 781239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 782239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 783b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check for constant size array. Set type to array element type. 784b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 785b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (AT->getSize() == 0) 786b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski return Scope; 787b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski QT = AT->getElementType(); 788b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski } 7894e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 790b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 7914e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu if (const CXXRecordDecl* CD = QT->getAsCXXRecordDecl()) 7924e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu if (!CD->hasTrivialDestructor()) { 7934e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 7944e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 7954e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 7964e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 7974e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 798239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 799239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 800239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 801239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 802239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 803239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderskivoid CFGBuilder::addLocalScopeAndDtors(Stmt* S) { 804239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 805239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 806239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 807239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 80802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 809239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 810239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 811239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 81253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// insertAutomaticObjDtors - Insert destructor CFGElements for variables with 81353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// automatic storage duration to CFGBlock's elements vector. Insertion will be 81453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// performed in place specified with iterator. 81553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::insertAutomaticObjDtors(CFGBlock* Blk, CFGBlock::iterator I, 81653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) { 81753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski BumpVectorContext& C = cfg->getBumpVectorContext(); 81853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski I = Blk->beginAutomaticObjDtorsInsert(I, B.distance(E), C); 81953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski while (B != E) 82053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski I = Blk->insertAutomaticObjDtor(I, *B++, S); 82153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 82253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 82353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// appendAutomaticObjDtors - Append destructor CFGElements for variables with 82453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// automatic storage duration to CFGBlock's elements vector. Elements will be 82553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// appended to physical end of the vector which happens to be logical 82653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// beginning. 82753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::appendAutomaticObjDtors(CFGBlock* Blk, 82853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt* S) { 82953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski insertAutomaticObjDtors(Blk, Blk->begin(), B, E, S); 83053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 83153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 83253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 83353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 83453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 83553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 83653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 83753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderskivoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock* Blk, 83853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 83953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski insertAutomaticObjDtors(Blk, Blk->end(), B, E, Blk->getTerminator()); 84053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 84153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 8424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 8436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 8446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 845852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 846f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 847f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 848f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 849f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 850ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 851ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (Expr *E = dyn_cast<Expr>(S)) 852ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose S = E->IgnoreParens(); 853ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 8544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 8554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 856852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 8574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 8584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 859852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 8601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 86156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 86256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); 86356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 8644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 865852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 8661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 868852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBlockExpr(cast<BlockExpr>(S), asc); 8694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 8704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 8714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 8721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 874a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 8751de85338543dd6228eb518185e385d94d377f4cbJohn McCall case Stmt::CXXMemberCallExprClass: 876852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 8771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 8794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 8804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 8814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 882852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 8831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 8854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 8861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 888852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 8891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 8904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 8914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 8921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 893021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 894021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 895021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 8964765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall case Stmt::ExprWithCleanupsClass: 8974765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc); 89847e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 899a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXBindTemporaryExprClass: 900a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); 901a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 90281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXConstructExprClass: 90381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); 90481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 905a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXFunctionalCastExprClass: 906a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); 907a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 90881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXTemporaryObjectExprClass: 90981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); 91081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 911021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 912021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 913ad5a894df1841698c824381b414630799adc26caTed Kremenek 914021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 915021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 916ad5a894df1841698c824381b414630799adc26caTed Kremenek 917ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith case Stmt::CXXForRangeStmtClass: 918ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); 919ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 9204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 9214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 9221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 9244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 9251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 9274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 9281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 9304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 9311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 9334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 9341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 9364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 9371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 938892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek case Stmt::ImplicitCastExprClass: 939892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); 940a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 9414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 9424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 9431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 9454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 9461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 947115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 948115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 949115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 9504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 9511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 9521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 9544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 9551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 9574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 9581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 9604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 9611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 9634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 9641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::NullStmtClass: 9664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 9671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 9694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 9701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 971f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne case Stmt::UnaryExprOrTypeTraitExprClass: 972f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), 973f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne asc); 9741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 976852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 9771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 9794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan case Stmt::UnaryOperatorClass: 98299cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan return VisitUnaryOperator(cast<UnaryOperator>(S), asc); 98399cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 9844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 9854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 9864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 9874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 989852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 9903179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, S)) { 9914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 992247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 9936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 9941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 9964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 9976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 9984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 9994f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) { 10006b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek CFGBlock *lastBlock = Block; 10016b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek for (Stmt::child_range I = Terminator->children(); I; ++I) 10026b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (Stmt *child = *I) 10036b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (CFGBlock *b = Visit(child)) 10046b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek lastBlock = b; 10056b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek 10066b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek return lastBlock; 10074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1009852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 1010852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 10114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 10126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10133179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, A)) { 10144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1015247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, A); 10166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 10176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 10194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 102199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong WanCFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, 1022892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek AddStmtChoice asc) { 10233179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, U)) { 102499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan autoCreateBlock(); 1025247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, U); 102699cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan } 102799cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1028892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(U->getSubExpr(), AddStmtChoice()); 102999cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan} 103099cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1031852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 1032852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 10334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (B->isLogicalOp()) { // && or || 10344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 1035247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, B); 10361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1037d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 10384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 10391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the LHS 10414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* LHSBlock = createBlock(false); 10424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LHSBlock->setTerminator(B); 10431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the RHS 10454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = ConfluenceBlock; 10464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = NULL; 10474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* RHSBlock = addStmt(B->getRHS()); 1048862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 1049862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek if (RHSBlock) { 1050d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1051862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek return 0; 105236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 1053862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // Create an empty block for cases where the RHS doesn't require 1054862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // any explicit statements in the CFG. 1055862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek RHSBlock = createBlock(); 1056862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 10571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 10590a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(B->getLHS()); 10602de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr)) 1061941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek KnownVal.negate(); 106200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 10634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now link the LHSBlock with RHSBlock. 10642de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LOr) { 10650a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 10660a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 10671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else { 10682de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LAnd); 10690a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 10700a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 107119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 10721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Generate the blocks for evaluating the LHS. 10744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = LHSBlock; 10754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 10761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 107736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 107836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->getOpcode() == BO_Comma) { // , 10796dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 1080247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 10814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 10824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 10836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 108436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 108536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->isAssignmentOp()) { 10863179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1087fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 1088247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1089fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 1090892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(B->getLHS()); 1091e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 1092fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 10931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10943179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1095e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 1096247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1097e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 1098e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 1099a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *RBlock = Visit(B->getRHS()); 1100a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *LBlock = Visit(B->getLHS()); 1101a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr 1102a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // containing a DoStmt, and the LHS doesn't create a new block, then we should 1103a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // return RBlock. Otherwise we'll incorrectly return NULL. 1104a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu return (LBlock ? LBlock : RBlock); 11054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1107852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { 11083179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 1109721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 1110247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 1111721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 1112721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 11134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1114cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 11154f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 11164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 11174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 1118d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1119d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 11201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 11224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 11234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 11241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 11264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 11279ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (BreakJumpTarget.block) { 11289ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B); 11299ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, BreakJumpTarget.block); 1130f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 11314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 11321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11378026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redlstatic bool CanThrow(Expr *E, ASTContext &Ctx) { 11384c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 11394c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 11404c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 11414c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 11424c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 1143ad5a894df1841698c824381b414630799adc26caTed Kremenek 11444c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 11454c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 11464c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 11478026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (Proto->isNothrow(Ctx)) 11484c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 11494c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 11504c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 11514c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 11524c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1153852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 11541de85338543dd6228eb518185e385d94d377f4cbJohn McCall // Compute the callee type. 11551de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType calleeType = C->getCallee()->getType(); 11561de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (calleeType == Context->BoundMemberTy) { 11571de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType boundType = Expr::findBoundMemberType(C->getCallee()); 11581de85338543dd6228eb518185e385d94d377f4cbJohn McCall 11591de85338543dd6228eb518185e385d94d377f4cbJohn McCall // We should only get a null bound type if processing a dependent 11601de85338543dd6228eb518185e385d94d377f4cbJohn McCall // CFG. Recover by assuming nothing. 11611de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (!boundType.isNull()) calleeType = boundType; 11622455636163fdd18581d7fdae816433f886d88213Mike Stump } 11632455636163fdd18581d7fdae816433f886d88213Mike Stump 11641de85338543dd6228eb518185e385d94d377f4cbJohn McCall // If this is a call to a no-return function, this stops the block here. 11651de85338543dd6228eb518185e385d94d377f4cbJohn McCall bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); 11661de85338543dd6228eb518185e385d94d377f4cbJohn McCall 11674c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 1168079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1169079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 11707a17851eee37f933eb57a5af7e1a0eb455443f6aAnders Carlsson if (Context->getLangOptions().Exceptions) { 11716c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 11724c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 1173079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 1174079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1175079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 11762455636163fdd18581d7fdae816433f886d88213Mike Stump if (FD->hasAttr<NoReturnAttr>()) 11772455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 1178079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 11794c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 1180079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 11812455636163fdd18581d7fdae816433f886d88213Mike Stump 11828026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (!CanThrow(C->getCallee(), *Context)) 11834c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 11844c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 118594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan if (!NoReturn && !AddEHEdge) 118694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan return VisitStmt(C, asc.withAlwaysAdd(true)); 11871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1188079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1189079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1190d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1191079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1192079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 11931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1194079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Block = createBlock(!NoReturn); 1195247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 11962455636163fdd18581d7fdae816433f886d88213Mike Stump 1197079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (NoReturn) { 1198079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Wire this to the exit block directly. 11990a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 1200079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 12014c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1202079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1203079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 12040a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 1205079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 12060a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 1207079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 12081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12092455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1210d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1211d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1212852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1213852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 12143fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 1215247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1216d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12173fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 12181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 121994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 12203fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 12213fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 122294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan CFGBlock* LHSBlock = Visit(C->getLHS(), alwaysAdd); 1223d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12243fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 12251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12263fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 12273fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 122894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan CFGBlock* RHSBlock = Visit(C->getRHS(), alwaysAdd); 1229d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12303fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 12311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12323fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 123300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 12340a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 12350a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 12360a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 12373fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 12381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 12393fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 12401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12421eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { 1243fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 12441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CFGBlock* LastBlock = Block; 12454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 12464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 12474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1248334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1249334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1250334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1251334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 12521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1253e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1254e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 12551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1256079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 12574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 12584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 126056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallCFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, 1261852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 126256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); 126356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL); 126456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 1265f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1266f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 1267f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek CFGBlock* ConfluenceBlock = Block ? Block : createBlock(); 1268247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1269d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1270f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 12711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 127294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 1273115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1274f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1275f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1276f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1277f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1278f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1279f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 128056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock* LHSBlock = 0; 128156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const Expr *trueExpr = C->getTrueExpr(); 128256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (trueExpr != opaqueValue) { 128356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); 1284d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1285f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1286f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1287f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 1288f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek else 1289f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek LHSBlock = ConfluenceBlock; 12901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1291f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1292f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 129356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock* RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); 1294d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1295f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 12961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1297f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1298f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 12991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 130000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 13010a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 1302f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 13030a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1304f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 130556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Expr *condExpr = C->getCond(); 1306d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1307f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (opaqueValue) { 1308f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Run the condition expression if it's not trivially expressed in 1309f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // terms of the opaque value (or if there is no opaque value). 1310f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (condExpr != opaqueValue) 1311f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addStmt(condExpr); 1312d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1313f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Before that, run the common subexpression if there was one. 1314f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // At least one of this or the above will be run. 1315f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(BCO->getCommon()); 1316f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek } 1317f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek 1318f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(condExpr); 1319f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1320f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 13214f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 1322bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // Check if the Decl is for an __label__. If so, elide it from the 1323bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // CFG entirely. 1324bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek if (isa<LabelDecl>(*DS->decl_begin())) 1325bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek return Block; 1326bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek 132729c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // This case also handles static_asserts. 13288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (DS->isSingleDecl()) 13298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitDeclSubExpr(DS); 13301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 13321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy. 13344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek typedef llvm::SmallVector<Decl*,10> BufTy; 13354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BufTy Buf(DS->decl_begin(), DS->decl_end()); 13361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) { 13384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 13394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 13404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 13411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 13434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 13444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 13454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 13461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 13474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 13481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 13508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = VisitDeclSubExpr(DSNew); 13514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 13521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 13544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 13551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 13578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski/// DeclStmts and initializers in them. 13588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt* DS) { 13598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert(DS->isSingleDecl() && "Can handle single declarations only."); 136029c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek Decl *D = DS->getSingleDecl(); 136129c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 136229c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek if (isa<StaticAssertDecl>(D)) { 136329c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // static_asserts aren't added to the CFG because they do not impact 136429c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // runtime semantics. 136529c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek return Block; 136629c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek } 136729c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 13688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 13691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!VD) { 13718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1372892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 13734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 13748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 13751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 13778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 13788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 13798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 13808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 13814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 13828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 13838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = VD->getType()->isReferenceType(); 13844765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 13858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 13868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 13878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 13884765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 13898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 13908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 13918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 13928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 13938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1394892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 13951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 13978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (HasTemporaries) 13988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 13998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 1400892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 14018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski else 1402892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(Init); 14034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 14041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 1406f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); 1407f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 14084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = addStmt(VA->getSizeExpr()); 14091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1410fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1411fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1412fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1413fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 14144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 1415d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1416fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 1417d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) { 14186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 14196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 14206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 14216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 14226c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 14236c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 14246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 142504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 142604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 142704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 142804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 142904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 143004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 143104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (VarDecl* VD = I->getConditionVariable()) { 143204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 143304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 143404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 143504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 143604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 1437fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // The block we were processing is now finished. Make it the successor 14386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 14396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1440d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1441d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14424e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1443c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 14446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1445b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 1446d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ElseBlock = Succ; 14476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1448d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* Else = I->getElse()) { 1449d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 14506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1451d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 14526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1453d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 145404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 145504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 145604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 145704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 145804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 145904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 14604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 14616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1462b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1463b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 14644e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1465d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14664e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 14674e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1468c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 14696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1470b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 1471d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* ThenBlock; 1472d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 1473d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Stmt* Then = I->getThen(); 14746db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1475d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 14766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 147704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 147804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 147904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 148004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 148104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 148204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 14834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 14846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1485dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1486dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1487dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1488dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1489dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 14900a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ThenBlock, sv.get()); 14916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1492d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14934e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 14946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 14950cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1496d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 14976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1498d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 14996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1500d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1501d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 15026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 150300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 15040a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(I->getCond()); 150500998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1506d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 15070a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 15080a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 15096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 15116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 15126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 151361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek Block = addStmt(I->getCond()); 1514ad5a894df1841698c824381b414630799adc26caTed Kremenek 151561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 151661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 151761dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 151861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 151961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 1520d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, I->getConditionVariableDeclStmt()); 152161dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek addStmt(Init); 152261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 152361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1524ad5a894df1841698c824381b414630799adc26caTed Kremenek 152561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek return Block; 1526d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 15276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1529d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) { 15306c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1531d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 15326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 15336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 15346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 15356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1536d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1537d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1538d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 15396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1540d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 1541fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 15420a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 15436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 15456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1546852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1547d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 15480cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 1549ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris LattnerCFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt *L) { 1550d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 15514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 1552ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner CFGBlock *LabelBlock = Block; 15536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 15554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 15566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1557ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner assert(LabelMap.find(L->getDecl()) == LabelMap.end() && 1558ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner "label already in map"); 1559ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); 15606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 15626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 15636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 15646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 15659cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1566d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15674e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 15686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1570d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 15716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1572d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1573d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 15746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1575d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1576d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 157731dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 1578d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) { 15796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 15806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 15814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1582d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1583d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 15846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1586d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 15876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1588d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1589d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1590f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1591f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1592f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 15939ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, JT.scopePosition, G); 15949ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, JT.block); 1595f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1596d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 15976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1598d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1599d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1600d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { 1601d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 16026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 160347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 160447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 160547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 160647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 160747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 160847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 160947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 161047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (Stmt* Init = F->getInit()) 161147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1612f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1613f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 161447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (VarDecl* VD = F->getConditionVariable()) 161547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 161647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 161747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 161847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 161947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1620fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1621fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1622d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1623d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16244e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1625d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 16264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 16274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 16286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16293f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 16303f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 1631f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 163247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 16333f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 16346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 16356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 16366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 163749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 163849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 16396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 164049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 16416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(F); 16426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 16446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 164549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = F->getCond()) { 164649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 164749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 16489ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (badCFG) 16499ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek return 0; 16508f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek assert(Block == EntryConditionBlock || 16518f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek (Block == 0 && EntryConditionBlock == Succ)); 165258b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek 165358b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // If this block contains a condition variable, add both the condition 165458b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // variable and initializer to the CFG. 165558b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (VarDecl *VD = F->getConditionVariable()) { 165658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (Expr *Init = VD->getInit()) { 165758b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek autoCreateBlock(); 1658d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, F->getConditionVariableDeclStmt()); 165958b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek EntryConditionBlock = addStmt(Init); 166058b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek assert(Block == EntryConditionBlock); 166158b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 166258b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 1663ad5a894df1841698c824381b414630799adc26caTed Kremenek 16644e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1665d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16664e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 16674e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 166849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 1669d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 16706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 16716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 167249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 16736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 167400998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1675941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal(true); 16761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 167700998a068e50945118f334c98af05ed44d7c22a6Mike Stump if (F->getCond()) 16780a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek KnownVal = tryEvaluateBool(F->getCond()); 167900998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1680d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1681d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 16826db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 16836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16843f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current values for Block, Succ, and continue targets. 1685f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1686f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 16876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1688af603f742491dc4707138c0293d295171fdd51baTed Kremenek // Create a new block to contain the (bottom) of the loop body. 1689af603f742491dc4707138c0293d295171fdd51baTed Kremenek Block = NULL; 169047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 169147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 169247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 16936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1694e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek if (Stmt* I = F->getInc()) { 16956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 16966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 16974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 16986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 16996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // No increment code. Create a special, empty, block that is used as the 17006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // target block for "looping back" to the start of the loop. 17013575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Succ == EntryConditionBlock); 170247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski Succ = Block ? Block : createBlock(); 1703e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 17046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17053575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 17063575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 17073575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1708d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17094e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17103575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 17113575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 17126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 171347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 17146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17153575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // The starting block for the loop increment is the block that should 17163575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 17179ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek ContinueJumpTarget.block->setLoopTarget(F); 17183575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 171947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 172047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 172147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 172247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 172347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 17246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 17256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 17264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(F->getBody()); 1727af603f742491dc4707138c0293d295171fdd51baTed Kremenek 1728af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 17299ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block;//can happen for "for (...;...;...);" 1730d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 1731941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 17326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1733941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // This new body block is a successor to our "exit" condition block. 17340a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1735d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 17366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1737941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1738941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 17390a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 17406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1741d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 17426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 1743d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Stmt* I = F->getInit()) { 1744d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 174549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 17462bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 174736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 174836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // There is no loop initialization. We are thus basically a while loop. 174936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // NULL out Block to force lazy block construction. 175036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Block = NULL; 175136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Succ = EntryConditionBlock; 175236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return EntryConditionBlock; 1753d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1754d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1755115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 17563179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, M)) { 1757115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 1758247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, M); 1759115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 1760892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(M->getBase()); 1761115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 1762115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1763514de5a21645900c92cf4f4f7313d6f66945d134Ted KremenekCFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 1764514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 1765514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 1766514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1767514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 1768514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1769514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1770514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1771514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 1772514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 1773514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1774514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 17754cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 1776514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 1777514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 1778514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 1779514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 1780514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1781514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 1782514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 1783514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1784514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 1785514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1786514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 1787514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 1788514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1789514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1790514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 17916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 17926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 17936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 1794514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 17956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1796514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek CFGBlock* LoopSuccessor = 0; 17976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1798514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 1799d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18004e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1801514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 1802514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 18034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 18044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 18056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18064cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 18074cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 18084cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 18096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18104cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 18116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 18126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 18146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 18156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 1816892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(ExitConditionBlock, S); 18174cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 18186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18194cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 1820fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // generate new blocks as necessary. We DON'T add the statement by default to 18216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 1822852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd); 18236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1824d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18254e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18264e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 18274e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 18286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 18306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 18314cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 18326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18334cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 18346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 18354cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 1836f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Succ(Succ); 1837f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1838f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 18396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1840f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 1841f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 18426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(S->getBody()); 18446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18454cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 18464cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" 18474e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1848d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18494e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18504e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 18516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18524cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 18530a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, BodyBlock); 18544cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 18556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18564cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 18574cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 18580a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopSuccessor); 18594cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 1860514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 18614cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 1862514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 18636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 18646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1865b3b0b3624e462c2940f65b86e773bfc300005203Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) { 1866b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 18676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1868b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 18694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 18706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1871da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 1872da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 1873da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 1874d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1875da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 18766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1877da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 1878fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 1879da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 18806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18814beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 18824beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 1883247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 18844beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 1885b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 18864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 1887b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 18886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1889e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) { 18904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 189190658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 1892e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 1893514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 1894d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { 1895d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 18966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 189705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 189805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 189905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 190005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 190105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 190205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 1903f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 190405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (VarDecl* VD = W->getConditionVariable()) { 190505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 190605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 190705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 1908f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1909fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 1910fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1911d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1912d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19134e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1914d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 19156b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek Block = 0; 19164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 19174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 19186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 19206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 19216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 192249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 192349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 19246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 192549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 192649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek ExitConditionBlock->setTerminator(W); 19276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 19296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. Thus we update 19306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "Succ" after adding the condition. 193149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = W->getCond()) { 193249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 193349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 1934a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // The condition might finish the current 'Block'. 1935a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu Block = EntryConditionBlock; 1936ad5a894df1841698c824381b414630799adc26caTed Kremenek 19374ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // If this block contains a condition variable, add both the condition 19384ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // variable and initializer to the CFG. 19394ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 19404ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (Expr *Init = VD->getInit()) { 19414ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek autoCreateBlock(); 1942d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, W->getConditionVariableDeclStmt()); 19434ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek EntryConditionBlock = addStmt(Init); 19444ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek assert(Block == EntryConditionBlock); 19454ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 19464ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 19474ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek 19484e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1949d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19504e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19514e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 195249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 19536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 19556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 195649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 19576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 195800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 19590a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(W->getCond()); 196000998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1961d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 1962d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 1963f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 1964d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1965d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 1966f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1967f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1968f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 1969f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 19706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 19716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 1972f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Block = 0; 1973f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Succ == EntryConditionBlock); 1974f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ = createBlock(); 1975f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ->setLoopTarget(W); 1976f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 19776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1978d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 197905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 19806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1981d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 1982f752fcfae84fbf21b78383bf2461633382d51844Ted Kremenek Block = NULL; 19836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 198405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 198505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 198605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 198705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 198805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 198905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 199005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 199105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 1992d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 19934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock* BodyBlock = addStmt(W->getBody()); 19946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1995af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 19969ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;" 19974e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1998d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19994e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20004e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 20016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2002941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 20030a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 2004bf15b278a439d73b605ec00a8d3977ef305712f4Ted Kremenek } 20056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2006941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 2007941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 20080a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 20096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 20116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 2012d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 20136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20144ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 20155482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 201649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 2017d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 20181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20204f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) { 20214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 20224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 20234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 20244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 20256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20262fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted KremenekCFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) { 20272fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 20282fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 20296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20306c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2031d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 20336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20342fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 20352fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 20366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20372fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 20380a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 20396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 20416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 2042852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 20432fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 2044989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 20450979d80615df97c675423de631c1b884819f4712Mike StumpCFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) { 20466c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2047d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20480979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 20490979d80615df97c675423de631c1b884819f4712Mike Stump 20500979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 20510979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 20520979d80615df97c675423de631c1b884819f4712Mike Stump 20535d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 20545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 20550a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 2056ad5a894df1841698c824381b414630799adc26caTed Kremenek else 20575d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 20580a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 20590979d80615df97c675423de631c1b884819f4712Mike Stump 20600979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 20610979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 2062852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 20630979d80615df97c675423de631c1b884819f4712Mike Stump} 20640979d80615df97c675423de631c1b884819f4712Mike Stump 20654f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) { 2066d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* LoopSuccessor = NULL; 20676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20688f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 20698f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 2070d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2071d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20724e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2073d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 20744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 20754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 20766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 20786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 20796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 208049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* ExitConditionBlock = createBlock(false); 208149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* EntryConditionBlock = ExitConditionBlock; 20826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 208349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 20846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 20856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 20876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 208849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek if (Stmt* C = D->getCond()) { 208949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 209049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 20914e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2092d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20934e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20944e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 209549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 20966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20975482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 209849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 209949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 210000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 21010a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(D->getCond()); 210200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2103d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 210449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek CFGBlock* BodyBlock = NULL; 2105d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 21066db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 21076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2108d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 21126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2113d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 2114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 21156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2116d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 2117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 21186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2119d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2120b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 21216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 212205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 212305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 212405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 212505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 212605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2127d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 21284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 21296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2130af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 2131a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 21324e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2133d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21344e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21354e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 21366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2137d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 2138d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 2139d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 2140d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 2141d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 2142d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 2143d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 2144d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 2145d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 2146d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 2147d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 2148d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 21490a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopBackBlock); 2150d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 2151d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 21520a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, NULL); 2153b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 21546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2155941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 2156941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 21570a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 21586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 21606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 2161d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 21626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2163d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 21645482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 2165d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 2166d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2167d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2168d4fdee35477e439759eea5f67ea03ff0c570fabaTed KremenekCFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) { 2169d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 2170d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 2171d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2172d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 21736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2174d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 2175d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 2176d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 21776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2178d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 2179235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 21809ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (ContinueJumpTarget.block) { 21819ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C); 21829ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, ContinueJumpTarget.block); 2183f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 2184235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 21856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2186d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 2187d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 21881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2189f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter CollingbourneCFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 2190f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc) { 219113fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 21923179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 219313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2194892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, E); 219513fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 21961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 219897e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek CFGBlock *lastBlock = Block; 219997e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek 22004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 2201f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); 22024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 220397e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek lastBlock = addStmt(VA->getSizeExpr()); 22044e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 22051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 220697e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek return lastBlock; 2207d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 22081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 22104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 2211852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 22123179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, SE)) { 221313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2214892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, SE); 221513fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 22164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 22174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2218d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2219411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { 22206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 22216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 2222d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek CFGBlock* SwitchSuccessor = NULL; 22236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22248ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 22258ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 22268ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 22278ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 22288ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 22298ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 22308ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (VarDecl* VD = Terminator->getConditionVariable()) { 22318ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 22328ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 22338ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 22348ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 22358ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2236d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2237d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22384e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2239d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 22406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2241d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2242d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2243d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2244eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2245f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2246eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 22476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 22486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 22496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2250eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 22516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2252d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2253d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 22546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2255d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2256d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2257d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2258f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 22596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 22616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 22626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 22636db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 226449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 22658ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2266e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // For pruning unreachable case statements, save the current state 2267e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // for tracking the condition value. 2268e71f3d587844110d836c82250830b27b1651afdbTed Kremenek SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered, 2269e71f3d587844110d836c82250830b27b1651afdbTed Kremenek false); 22700498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2271e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Determine if the switch condition can be explicitly evaluated. 2272e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 22730498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult result; 2274e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek bool b = tryEvaluate(Terminator->getCond(), result); 2275e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, 2276e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek b ? &result : 0); 22770498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 22788ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 22798ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 22808ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 22818ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 22828ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2283d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 22844e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2285d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22864e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 22874e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 228849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 22896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 2290432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // following the switch body. Moreover, take into account if all the 2291432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // cases of a switch are covered (e.g., switching on an enum value). 2292e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2293432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek switchExclusivelyCovered || Terminator->isAllEnumCasesCovered() 2294432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek ? 0 : DefaultCaseBlock); 22956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 229649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2297411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 2298d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 22996b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek Block = addStmt(Terminator->getCond()); 2300ad5a894df1841698c824381b414630799adc26caTed Kremenek 23016b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 23026b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 23036b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 23046b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 23056b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 2306d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, Terminator->getConditionVariableDeclStmt()); 23076b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek addStmt(Init); 23086b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 23096b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2310ad5a894df1841698c824381b414630799adc26caTed Kremenek 23116b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek return Block; 2312d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2313e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2314e71f3d587844110d836c82250830b27b1651afdbTed Kremenekstatic bool shouldAddCase(bool &switchExclusivelyCovered, 2315e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const Expr::EvalResult *switchCond, 2316e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const CaseStmt *CS, 2317e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ASTContext &Ctx) { 2318e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (!switchCond) 2319e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek return true; 2320e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek 2321e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool addCase = false; 23220498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2323e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!switchExclusivelyCovered) { 2324e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (switchCond->Val.isInt()) { 2325e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the LHS of the case value. 2326e71f3d587844110d836c82250830b27b1651afdbTed Kremenek Expr::EvalResult V1; 2327e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS->getLHS()->Evaluate(V1, Ctx); 2328e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(V1.Val.isInt()); 2329e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const llvm::APSInt &condInt = switchCond->Val.getInt(); 2330e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const llvm::APSInt &lhsInt = V1.Val.getInt(); 2331e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2332e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (condInt == lhsInt) { 2333e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2334e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2335e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2336e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else if (condInt < lhsInt) { 2337e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (const Expr *RHS = CS->getRHS()) { 2338e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the RHS of the case value. 2339e71f3d587844110d836c82250830b27b1651afdbTed Kremenek Expr::EvalResult V2; 2340e71f3d587844110d836c82250830b27b1651afdbTed Kremenek RHS->Evaluate(V2, Ctx); 2341e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(V2.Val.isInt()); 2342e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (V2.Val.getInt() <= condInt) { 2343e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2344e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2345e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2346e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2347e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2348e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2349e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else 2350e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2351e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2352e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return addCase; 2353e71f3d587844110d836c82250830b27b1651afdbTed Kremenek} 2354d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 23554f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) { 23566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 23576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 23580fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 23590498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 23600fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 23610fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 23620fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 23630fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 23640fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 23650a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek CFGBlock *currentBlock = createBlock(false); 23660a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek currentBlock->setLabel(CS); 23670fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 23680fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 23690a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, currentBlock); 23700fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 23710a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TopBlock = currentBlock; 23720fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2373e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2374e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2375e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2376e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? currentBlock : 0); 23770fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2378e71f3d587844110d836c82250830b27b1651afdbTed Kremenek LastBlock = currentBlock; 23790fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 23800fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 23810fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 238229ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 23830fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 23840fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 23851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 238629ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek CFGBlock* CaseBlock = Block; 23874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 23884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 23896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 23916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 23924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 23934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2394d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23954e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 23966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 23986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 23994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2400e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2401e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2402e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2403e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? CaseBlock : 0); 24046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2405d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2406d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 24076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24080fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 24090a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, CaseBlock); 24100fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 241136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 24120fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 24130fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 24140fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 24156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24160fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2417d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 24186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2419411cdee0b490f79428c9eb977f25199eb7d21cd8Ted KremenekCFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) { 24204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 24214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 24221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2423eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 24244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 24254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 24264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 24276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 24296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2430411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 24311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2432d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24334e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2434eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 24356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 24366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 24376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 24386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 24396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 24406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2441eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2442eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 24436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2444eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2445eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 24466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2448295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2449d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 24505d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 24515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 24525d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 24535d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* TrySuccessor = NULL; 24545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 24555d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2456d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24575d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 24585d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 24595d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 24605d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2461a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 24625d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 24635d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2464f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 24655d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2466f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 24675d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2468a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 24695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 24705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 24715d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 24725d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2473a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2474a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2475a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 24765d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 24775d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 24785d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 24795d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 24805d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 24815d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 24820a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, CatchBlock); 24835d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2484a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2485a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 24860a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2487a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 24880a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2489a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 24905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 24915d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 24925d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 24935d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2494f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2495f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock); 2496f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump TryTerminatedBlock = NewTryTerminatedBlock; 2497f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 24986db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 24995d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 25003fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek Block = addStmt(Terminator->getTryBlock()); 25015d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return Block; 25025d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 25035d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25045d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) { 25055d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 25065d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 25075d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25080e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 25090e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 25100e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 25110e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 25120e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 25130e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 25140e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski if (VarDecl* VD = CS->getExceptionDecl()) { 25150e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 25160e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 25170e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 25180e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 25190e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 25205d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 25215d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 25225d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25235d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock* CatchBlock = Block; 25245d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 25255d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 25265d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25275d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 25285d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2529d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 25315d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25325d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 25335d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 25345d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 25365d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 25375d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2538ad762fcdc16b9e4705b12b09d92b8c026212b906Richard SmithCFGBlock* CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt* S) { 2539ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // C++0x for-range statements are specified as [stmt.ranged]: 2540ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // 2541ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // { 2542ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // auto && __range = range-init; 2543ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for ( auto __begin = begin-expr, 2544ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __end = end-expr; 2545ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __begin != __end; 2546ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // ++__begin ) { 2547ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for-range-declaration = *__begin; 2548ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // statement 2549ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2550ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2551ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2552ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save local scope position before the addition of the implicit variables. 2553ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 2554ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2555ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Create local scopes and destructors for range, begin and end variables. 2556ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *Range = S->getRangeStmt()) 2557ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(Range); 2558ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *BeginEnd = S->getBeginEndStmt()) 2559ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(BeginEnd); 2560ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S); 2561ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2562ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LocalScope::const_iterator ContinueScopePos = ScopePos; 2563ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2564ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // "for" is a control-flow statement. Thus we stop processing the current 2565ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // block. 2566ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock* LoopSuccessor = NULL; 2567ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Block) { 2568ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2569ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2570ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Block; 2571ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } else 2572ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Succ; 2573ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2574ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current value for the break targets. 2575ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // All breaks should go to the code following the loop. 2576ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2577ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 2578ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2579ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The block for the __begin != __end expression. 2580ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock* ConditionBlock = createBlock(false); 2581ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ConditionBlock->setTerminator(S); 2582ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2583ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now add the actual condition to the condition block. 2584ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Expr *C = S->getCond()) { 2585ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = ConditionBlock; 2586ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *BeginConditionBlock = addStmt(C); 2587ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2588ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2589ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(BeginConditionBlock == ConditionBlock && 2590ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith "condition block in for-range was unexpectedly complex"); 2591ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith (void)BeginConditionBlock; 2592ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2593ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2594ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The condition block is the implicit successor for the loop body as well as 2595ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // any code above the loop. 2596ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = ConditionBlock; 2597ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2598ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // See if this is a known constant. 2599ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith TryResult KnownVal(true); 2600ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2601ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (S->getCond()) 2602ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith KnownVal = tryEvaluateBool(S->getCond()); 2603ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2604ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now create the loop body. 2605ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith { 2606ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(S->getBody()); 2607ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2608ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current values for Block, Succ, and continue targets. 2609ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2610ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 2611ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2612ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Generate increment code in its own basic block. This is the target of 2613ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // continue statements. 2614ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2615ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = addStmt(S->getInc()); 2616ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 2617ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2618ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The starting block for the loop increment is the block that should 2619ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // represent the 'loop target' for looping back to the start of the loop. 2620ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget.block->setLoopTarget(S); 2621ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2622ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Finish up the increment block and prepare to start the loop body. 2623ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(Block); 2624ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2625ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2626ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2627ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2628ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2629ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add implicit scope and dtors for loop variable. 2630ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeAndDtors(S->getLoopVarStmt()); 2631ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2632ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Populate a new block to contain the loop body and loop variable. 2633ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getBody()); 2634ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2635ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2636ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getLoopVarStmt()); 2637ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2638ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2639ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2640ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // This new body block is a successor to our condition block. 2641ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : Block); 2642ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2643ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2644ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Link up the condition block with the code that follows the loop (the 2645ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // false branch). 2646ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor); 2647ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2648ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add the initialization statements. 2649ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = createBlock(); 2650b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith addStmt(S->getBeginEndStmt()); 2651b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith return addStmt(S->getRangeStmt()); 2652ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith} 2653ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 26544765fa05b5652fcc4356371c2f481d0ea9a1b007John McCallCFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, 26558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc) { 26568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors) { 26578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If adding implicit destructors visit the full expression for adding 26588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // destructors of temporaries. 26598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(E->getSubExpr()); 26608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 26618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Full expression has to be added as CFGStmt so it will be sequenced 26628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before destructors of it's temporaries. 266394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(true); 26648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 26658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(E->getSubExpr(), asc); 26668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 26678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 2668a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 2669a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 26703179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2671a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2672247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2673a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 2674a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 267594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 2676a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2677a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2678a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2679a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 268081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, 268181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 268281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 26833ff5b26ddd5857a50db4bfacdd198fb32eaebdacZhongxing Xu if (!C->isElidable()) 2684247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 268594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 268681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 268781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 268881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2689a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 2690a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 26913179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2692a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2693247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2694a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 269594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 2696a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2697a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2698a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2699a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 270081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 270181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 270281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 2703247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 270481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 270581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 270681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2707a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, 2708a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 27093179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2710a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2711247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2712a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2713892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(E->getSubExpr(), AddStmtChoice()); 2714a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2715a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 271619bb356317952445b03ee341c02f6147083c9eeaTed KremenekCFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) { 27176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 271819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek CFGBlock* IBlock = cfg->getIndirectGotoBlock(); 27196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 272019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 272119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 272219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 272319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 27246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 272519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 272619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 2727d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 27284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 27294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 273019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 273119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 27320a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, IBlock); 273319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 273419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 273519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 27368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) { 27378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskitryAgain: 27388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!E) { 27398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski badCFG = true; 27408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 27418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 27428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski switch (E->getStmtClass()) { 27438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski default: 27448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitChildrenForTemporaryDtors(E); 27458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::BinaryOperatorClass: 27478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E)); 27488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXBindTemporaryExprClass: 27508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXBindTemporaryExprForTemporaryDtors( 27518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<CXXBindTemporaryExpr>(E), BindToTemporary); 27528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 275356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 27548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ConditionalOperatorClass: 27558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitConditionalOperatorForTemporaryDtors( 275656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall cast<AbstractConditionalOperator>(E), BindToTemporary); 27578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ImplicitCastExprClass: 27598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For implicit cast we want BindToTemporary to be passed further. 27608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<CastExpr>(E)->getSubExpr(); 27618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 27628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ParenExprClass: 27648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<ParenExpr>(E)->getSubExpr(); 27658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 27668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 27678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 27688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { 27708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // When visiting children for destructors we want to visit them in reverse 27718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. Because there's no reverse iterator for children must to reverse 27728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // them in helper vector. 27738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski typedef llvm::SmallVector<Stmt *, 4> ChildrenVect; 27748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ChildrenVect ChildrenRev; 27757502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range I = E->children(); I; ++I) { 27768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (*I) ChildrenRev.push_back(*I); 27778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 27788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = Block; 27808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(), 27818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski L = ChildrenRev.rend(); I != L; ++I) { 27828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (CFGBlock *R = VisitForTemporaryDtors(*I)) 27838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = R; 27848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 27858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 27868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 27878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { 27898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->isLogicalOp()) { 27908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors for temporaries in LHS expression should be called after 27918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // those for RHS expression. Even if this will unnecessarily create a block, 27928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // this block will be used at least by the full expression. 27938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 27948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); 27958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 27968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 27978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 27998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 28008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 28018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (RHSBlock) { 28038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 28048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 28058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If RHS expression did produce destructors we need to connect created 28078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // blocks to CFG in same manner as for binary operator itself. 28088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = createBlock(false); 28098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock->setTerminator(CFGTerminator(E, true)); 28108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For binary operator LHS block is before RHS in list of predecessors 28128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // of ConfluenceBlock. 28138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), 28148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConfluenceBlock->pred_end()); 28158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 28170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(E->getLHS()); 28188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) 28198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski KnownVal.negate(); 28208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Link LHSBlock with RHSBlock exactly the same way as for binary operator 28228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // itself. 28238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getOpcode() == BO_LOr) { 28240a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 28250a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 28268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 28278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert (E->getOpcode() == BO_LAnd); 28280a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 28290a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 28308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = LHSBlock; 28338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock; 28348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 28378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return ConfluenceBlock; 28388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 284036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (E->isAssignmentOp()) { 28418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For assignment operator (=) LHS expression is visited 28428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before RHS expression. For destructors visit them in reverse order. 28438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 28448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 28458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock ? LHSBlock : RHSBlock; 28468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For any other binary operator RHS expression is visited before 28498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // LHS expression (order of children). For destructors visit them in reverse 28508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. 28518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 28528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 28538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return RHSBlock ? RHSBlock : LHSBlock; 28548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 28558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( 28578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *E, bool BindToTemporary) { 28588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for temporaries in subexpression. 28598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr()); 2860249c9458e2cc5b671634baefe8517d7598883a20Zhongxing Xu if (!BindToTemporary) { 28618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If lifetime of temporary is not prolonged (by assigning to constant 28628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // reference) add destructor for it. 28638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 28648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendTemporaryDtor(Block, E); 28658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = Block; 28668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 28688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 28698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( 287156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AbstractConditionalOperator *E, bool BindToTemporary) { 28728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for condition expression. Even if this will 28738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // unnecessarily create a block, this block will be used at least by the full 28748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // expression. 28758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 28768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); 28778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 28788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 287956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (BinaryConditionalOperator *BCO 288056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall = dyn_cast<BinaryConditionalOperator>(E)) { 288156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); 28828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 28838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 28848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 288656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall // Try to add block with destructors for LHS expression. 288756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *LHSBlock = NULL; 288856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Succ = ConfluenceBlock; 288956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Block = NULL; 289056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); 289156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (badCFG) 289256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return NULL; 289356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 28948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for RHS expression; 28958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 28968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 289756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), 289856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall BindToTemporary); 28998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 29008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 29018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock && !LHSBlock) { 29038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If neither LHS nor RHS expression had temporaries to destroy don't create 29048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // more blocks. 29058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 29068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 29078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = createBlock(false); 29108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block->setTerminator(CFGTerminator(E, true)); 29118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 29130a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(E->getCond()); 29148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (LHSBlock) { 29160a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 29178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (KnownVal.isFalse()) { 29180a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, NULL); 29198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 29200a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, ConfluenceBlock); 29218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); 29228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock) 29258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski RHSBlock = ConfluenceBlock; 29260a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 29278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 29298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 29308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 2931befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 2932026473c2175424a039f51ca8949937268721b965Ted Kremenek 29336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 29346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 29356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 29369438252ad2ecae5338df565ca33c6969e4fbfa41Ted KremenekCFGBlock* CFG::createBlock() { 2937026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 2938026473c2175424a039f51ca8949937268721b965Ted Kremenek 2939026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 2940ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 2941ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek new (Mem) CFGBlock(NumBlockIDs++, BlkBVC); 2942ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 2943026473c2175424a039f51ca8949937268721b965Ted Kremenek 2944026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 2945ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 2946ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 2947026473c2175424a039f51ca8949937268721b965Ted Kremenek 2948026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 2949ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 2950026473c2175424a039f51ca8949937268721b965Ted Kremenek} 2951026473c2175424a039f51ca8949937268721b965Ted Kremenek 2952026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 2953026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 2954b978a441c7d8bf59e7fede938e1f3b672573b443Mike StumpCFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C, 2955b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const BuildOptions &BO) { 2956b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFGBuilder Builder(C, BO); 2957b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek return Builder.buildCFG(D, Statement); 2958fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 2959fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 2960c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekconst CXXDestructorDecl * 2961c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed KremenekCFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { 2962c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek switch (getKind()) { 2963c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Invalid: 2964c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Statement: 2965c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Initializer: 2966c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek llvm_unreachable("getDestructorDecl should only be used with " 2967c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek "ImplicitDtors"); 2968c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::AutomaticObjectDtor: { 2969c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const VarDecl *var = cast<CFGAutomaticObjDtor>(this)->getVarDecl(); 2970c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = var->getType(); 2971697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek ty = ty.getNonReferenceType(); 2972c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek if (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { 2973c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek ty = arrayType->getElementType(); 2974c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek } 2975c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const RecordType *recordType = ty->getAs<RecordType>(); 2976c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXRecordDecl *classDecl = 2977697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek cast<CXXRecordDecl>(recordType->getDecl()); 2978c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return classDecl->getDestructor(); 2979c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 2980c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::TemporaryDtor: { 2981c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXBindTemporaryExpr *bindExpr = 2982c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek cast<CFGTemporaryDtor>(this)->getBindTemporaryExpr(); 2983c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXTemporary *temp = bindExpr->getTemporary(); 2984c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return temp->getDestructor(); 2985c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 2986c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::BaseDtor: 2987c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::MemberDtor: 2988c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 2989c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // Not yet supported. 2990c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return 0; 2991c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 2992697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek llvm_unreachable("getKind() returned bogus value"); 29932ae00543d6e1bd7dba0ce2dacec740bb6049a2ddMatt Beaumont-Gay return 0; 2994c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek} 2995c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 2996c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekbool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { 2997c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek if (const CXXDestructorDecl *cdecl = getDestructorDecl(astContext)) { 2998c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = cdecl->getType(); 2999c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return cast<FunctionType>(ty)->getNoReturnAttr(); 3000c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3001c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return false; 30023c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek} 30033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 300463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 300563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek// CFG: Queries for BlkExprs. 300663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 300763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 300863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremeneknamespace { 300986946745225096243f6969dc745267b78fc211a6Ted Kremenek typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy; 301063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 301163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 30128a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenekstatic void FindSubExprAssignments(Stmt *S, 30138a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek llvm::SmallPtrSet<Expr*,50>& Set) { 30148a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!S) 301533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return; 30166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30177502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range I = S->children(); I; ++I) { 3018ad5a894df1841698c824381b414630799adc26caTed Kremenek Stmt *child = *I; 30198a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!child) 30208a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek continue; 3021ad5a894df1841698c824381b414630799adc26caTed Kremenek 30228a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(child)) 302333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (B->isAssignmentOp()) Set.insert(B); 30246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30258a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek FindSubExprAssignments(child, Set); 302633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 302733d4aab80f31bd06257526fe2883ea920529456bTed Kremenek} 302833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek 302963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekstatic BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { 303063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = new BlkExprMapTy(); 30316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Look for assignments that are used as subexpressions. These are the only 30336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // assignments that we want to *possibly* register as a block-level 30346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression. Basically, if an assignment occurs both in a subexpression and 30356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // at the block-level, it is a block-level expression. 303633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek llvm::SmallPtrSet<Expr*,50> SubExprAssignments; 30376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 303863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) 3039ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 30403c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = BI->getAs<CFGStmt>()) 30413c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek FindSubExprAssignments(S->getStmt(), SubExprAssignments); 304286946745225096243f6969dc745267b78fc211a6Ted Kremenek 3043411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { 30446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 30456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Iterate over the statements again on identify the Expr* and Stmt* at the 30466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block-level that are block-level expressions. 3047411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 3048b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { 30493c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CFGStmt *CS = BI->getAs<CFGStmt>(); 30503c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (!CS) 3051b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu continue; 30523c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (Expr* Exp = dyn_cast<Expr>(CS->getStmt())) { 3053ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert((Exp->IgnoreParens() == Exp) && "No parens on block-level exps"); 30546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3055411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { 305633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek // Assignment expressions that are not nested within another 30576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression are really "statements" whose value is never used by 30586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // another expression. 3059411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) 306033d4aab80f31bd06257526fe2883ea920529456bTed Kremenek continue; 3061ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose } else if (const StmtExpr* SE = dyn_cast<StmtExpr>(Exp)) { 30626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Special handling for statement expressions. The last statement in 30636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the statement expression is also a block-level expr. 3064ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose const CompoundStmt* C = SE->getSubStmt(); 306586946745225096243f6969dc745267b78fc211a6Ted Kremenek if (!C->body_empty()) { 3066ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose const Stmt *Last = C->body_back(); 3067ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (const Expr *LastEx = dyn_cast<Expr>(Last)) 3068ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose Last = LastEx->IgnoreParens(); 306933d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3070ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[Last] = x; 307186946745225096243f6969dc745267b78fc211a6Ted Kremenek } 307286946745225096243f6969dc745267b78fc211a6Ted Kremenek } 3073e2dcd783a04f654c50bd8b13fb08a440afbd67e7Ted Kremenek 307433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3075411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek (*M)[Exp] = x; 307633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 3077b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 30786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3079411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek // Look at terminators. The condition is a block-level expression. 30806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3081ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Stmt* S = (*I)->getTerminatorCondition(); 30826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3083390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek if (S && M->find(S) == M->end()) { 3084ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose unsigned x = M->size(); 3085ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[S] = x; 3086411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 3087411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 30886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 308986946745225096243f6969dc745267b78fc211a6Ted Kremenek return M; 309063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 309163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 309286946745225096243f6969dc745267b78fc211a6Ted KremenekCFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) { 309386946745225096243f6969dc745267b78fc211a6Ted Kremenek assert(S != NULL); 309463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } 30956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 309663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap); 309786946745225096243f6969dc745267b78fc211a6Ted Kremenek BlkExprMapTy::iterator I = M->find(S); 30983fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); 309963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 31007dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 310163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekunsigned CFG::getNumBlkExprs() { 310263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap)) 310363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return M->size(); 310436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 310536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // We assume callers interested in the number of BlkExprs will want 310636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // the map constructed if it doesn't already exist. 310736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan BlkExprMap = (void*) PopulateBlkExprMap(*this); 310836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size(); 310963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 311063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 3111274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3112ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 3113ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3114ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3115ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 3116be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 3117ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 31186e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (To && F.IgnoreDefaultsWithCoveredEnums) { 3119ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 3120ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 3121ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 31226e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { 3123ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 31246e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek const Stmt *L = To->getLabel(); 31256e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 31266e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek return true; 3127ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3128ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3129ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3130ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3131ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 3132ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 3133ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3134ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3135274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek// Cleanup: CFG dstor. 3136274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3137274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek 313863f5887f316fb52d243fcbb3631c039de6c4b993Ted KremenekCFG::~CFG() { 313963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap); 314063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 31416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31427dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 31437dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 31447dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 31457dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 314642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 31472bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 3148ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 31493c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 31503c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 315142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 31521cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 31530a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek signed currentBlock; 31540a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek unsigned currentStmt; 3155e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 315642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 31571c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 3158e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 31593c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek : currentBlock(0), currentStmt(0), LangOpts(LO) 31603c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek { 316142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 316242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 3163ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 31641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 31653c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *SE = BI->getAs<CFGStmt>()) { 31663c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt= SE->getStmt(); 31671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 31683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek StmtMap[stmt] = P; 31693c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 31703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek switch (stmt->getStmtClass()) { 31713c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::DeclStmtClass: 31723c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P; 31733c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 31743c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::IfStmtClass: { 31753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable(); 31763c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 31773c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 31783c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 31793c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 31803c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::ForStmtClass: { 31813c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable(); 31823c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 31833c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 31843c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 31853c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 31863c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::WhileStmtClass: { 31873c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 31883c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<WhileStmt>(stmt)->getConditionVariable(); 31893c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 31903c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 31913c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 31923c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 31933c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::SwitchStmtClass: { 31943c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 31953c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<SwitchStmt>(stmt)->getConditionVariable(); 31963c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 31973c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 31983c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 31993c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 32003c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::CXXCatchStmtClass: { 32013c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 32023c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<CXXCatchStmt>(stmt)->getExceptionDecl(); 32033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 32043c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 32053c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 32063c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 32073c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek default: 32083c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 32091cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 32101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 321142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 3212b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 3213fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 32143c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 32156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 321642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 32176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3218e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 32190a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setBlockID(signed i) { currentBlock = i; } 32200a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setStmtID(unsigned i) { currentStmt = i; } 32216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32221cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski virtual bool handledStmt(Stmt* S, llvm::raw_ostream& OS) { 32231cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 3224fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 322542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 322642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 32276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32280a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 32290a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek && I->second.second == currentStmt) { 323042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 32313fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 32326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32333fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 32341c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 323542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 32361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 32373c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek bool handleDecl(const Decl* D, llvm::raw_ostream& OS) { 32381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 32391cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 32401cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 32411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 32421cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 32430a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 32440a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek && I->second.second == currentStmt) { 32451cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 32461cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 32471cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 32481cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 32491cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 32501cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 325142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 3252e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3253e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 3254e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 3255e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 3256ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 32576fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 32586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3259a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_ostream& OS; 326042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 3261d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 3262d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 3263d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper, 3264e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 3265d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 32666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3267d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitIfStmt(IfStmt* I) { 3268d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 3269d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 3270d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 32716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3272d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 32736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump void VisitStmt(Stmt* Terminator) { 32746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 32756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 32766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3277d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitForStmt(ForStmt* F) { 3278d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 32793fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 32803fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3281535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 32823fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = F->getCond()) 32833fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3284535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 32853fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 32863fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3287a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 3288d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 32896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3290d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitWhileStmt(WhileStmt* W) { 3291d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 32923fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = W->getCond()) 32933fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3294d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 32956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3296d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek void VisitDoStmt(DoStmt* D) { 3297d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 32983fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (Stmt* C = D->getCond()) 32993fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 33009da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 33016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3302411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek void VisitSwitchStmt(SwitchStmt* Terminator) { 33039da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 3304d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 33059da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 33066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33075d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump void VisitCXXTryStmt(CXXTryStmt* CS) { 33085d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 33095d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 33105d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 331156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { 3312d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 33136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 3314805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 33156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3316aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek void VisitChooseExpr(ChooseExpr* C) { 3317aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 3318d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 3319a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 3320aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 33216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33221c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt* I) { 33231c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 3324d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 33251c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 33266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3327805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 3328805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 3329805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 3330805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3331805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 33326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3333d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 33346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3335805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 33362de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 3337a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 3338805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 33392de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 3340a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 3341805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3342805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 3343805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek assert(false && "Invalid logical operator."); 33446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3345805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 33466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33470b1d9b7557437176f9cea1283bfac2510812beceTed Kremenek void VisitExpr(Expr* E) { 3348d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 33496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3350d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3351e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3352e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 33531cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderskistatic void print_elem(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, 3354079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 33553c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *CS = E.getAs<CFGStmt>()) { 33563c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek Stmt *S = CS->getStmt(); 33571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 33581cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 33591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 33601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 33611cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) { 33621cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski CompoundStmt* Sub = SE->getSubStmt(); 33631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 33647502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall if (Sub->children()) { 33651cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 33661cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 33671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 33681cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 33691cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 33701cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 33711cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 33721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 33731cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 33741cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 33751cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 33761cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 33771cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 33781cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 33791c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 33801c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 33811cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 33826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33831cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 338436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (OperatorCall)"; 338536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else if (isa<CXXBindTemporaryExpr>(S)) { 338636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (BindTemporary)"; 33876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 33886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33891cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 33901cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 33911cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 33924e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 33933c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGInitializer *IE = E.getAs<CFGInitializer>()) { 33943c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXCtorInitializer *I = IE->getInitializer(); 33951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 33961cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 339700eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet else OS << I->getAnyMember()->getName(); 33986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 34001cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Expr* IE = I->getInit()) 34011cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 34021cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 34031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34041cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 34051cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 34061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 34071cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34083c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGAutomaticObjDtor *DE = E.getAs<CFGAutomaticObjDtor>()){ 34093c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl* VD = DE->getVarDecl(); 34101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 34111cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3412b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski const Type* T = VD->getType().getTypePtr(); 34131cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 34141cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 3415b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski else if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 3416b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski T = ET; 34171cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34181cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 34191cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 34207c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 34213c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGBaseDtor *BE = E.getAs<CFGBaseDtor>()) { 34223c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); 34237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 34244e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 34257c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 34263c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) { 34273c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const FieldDecl *FD = ME->getFieldDecl(); 34288c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 34298c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski const Type *T = FD->getType().getTypePtr(); 34308c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 34318c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski T = ET; 34328c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 34337c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 34348c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; 34354e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 34368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 34373c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGTemporaryDtor *TE = E.getAs<CFGTemporaryDtor>()) { 34383c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); 34398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()"; 34408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << " (Temporary object destructor)\n"; 34411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 344281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 34436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3444e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnerstatic void print_block(llvm::raw_ostream& OS, const CFG* cfg, 3445e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const CFGBlock& B, 3446e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper* Helper, bool print_edges) { 34476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 344842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(B.getBlockID()); 34496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34507dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 34516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << "\n [ B" << B.getBlockID(); 34526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 345342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 345442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (ENTRY) ]\n"; 345542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 345642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " (EXIT) ]\n"; 345742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 34587dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OS << " (INDIRECT GOTO DISPATCH) ]\n"; 345942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 346042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " ]\n"; 34616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34629cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 3463079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) { 346442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 346542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 346642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 34676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3468079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (LabelStmt* L = dyn_cast<LabelStmt>(Label)) 34699cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 3470079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) { 34719cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 3472e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 3473e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 34749cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 34759cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 3476e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 3477e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 34789cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 3479079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 34809cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 3481079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 34825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 3483a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 3484a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 3485a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 3486a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 3487a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 34885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 34895d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 34905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 349142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek assert(false && "Invalid label statement in CFGBlock."); 34926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34939cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 34949cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 34956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3496fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 3497fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 34986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 349942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 350042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 35016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35029cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 350342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 350442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 35056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3506a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 35076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 350842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 350942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 35106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35111cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski print_elem(OS,Helper,*I); 3512fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 35136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35149cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 351542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 351642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 351742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " "; 35186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35199cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " T: "; 35206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 352142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 35226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3523e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, Helper, 3524e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 35254ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt())); 3526a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 3527fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 35286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35299cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 35309cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 353142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Predecessors (" << B.pred_size() << "):"; 35329cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek unsigned i = 0; 353342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 353442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 353542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 35366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 353742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) == 0) 35389cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 35396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35409cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " B" << (*I)->getBlockID(); 35419cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 35426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35439cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 35446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35459cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 354642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek OS << " Successors (" << B.succ_size() << "):"; 35479cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek i = 0; 354842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 354942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 355042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E; ++I, ++i) { 35516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 355242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (i == 8 || (i-8) % 10 == 0) 35539cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "\n "; 355442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3555e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump if (*I) 3556e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " B" << (*I)->getBlockID(); 3557e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump else 3558e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump OS << " NULL"; 3559fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 35606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35619cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << '\n'; 3562fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 35636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 356442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 356542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 356642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 3567e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); } 356842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 356942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 3570e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const { 3571e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 35726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 357342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 357442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getEntry(), &Helper, true); 35756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 357642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 357742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 357842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 3579ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 358042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 35816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3582ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek print_block(OS, this, **I, &Helper, true); 358342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 35846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 358542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 358642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, this, getExit(), &Helper, true); 3587d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 35886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 358942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 359042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 3591e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const { 3592e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner print(llvm::errs(), cfg, LO); 3593e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 359442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 359542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 359642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 3597e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg, 3598e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LO) const { 3599e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 360042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(OS, cfg, *this, &Helper, true); 3601026473c2175424a039f51ca8949937268721b965Ted Kremenek} 36027dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3603a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 3604e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFGBlock::printTerminator(llvm::raw_ostream &OS, 36056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 3606e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 36074ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt())); 3608a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 3609a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 3610390e48b15ad93f85bfd1e33b9992c198fa0db475Ted KremenekStmt* CFGBlock::getTerminatorCondition() { 36114ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski Stmt *Terminator = this->Terminator; 3612411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 3613411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 36146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3615411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek Expr* E = NULL; 36166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3617411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 3618411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 3619411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3621411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 3622411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 3623411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3625411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 3626411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 3627411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3629411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 3630411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 3631411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3633411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 3634411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 3635411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3637411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 3638411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 3639411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3641411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 3642411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 3643411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3645411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 3646411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 3647411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 364956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 365056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall E = cast<BinaryConditionalOperator>(Terminator)->getCond(); 365156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall break; 365256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 3653411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 3654411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 3655411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 36566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3657411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 3658411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 3659390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 36606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3661390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 36626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 3663411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 36646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3665411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 3666411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 3667411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 36687dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 36697dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 36707dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 36717dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 367242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 367342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 36746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 367542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 367642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3677e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 367842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 3679e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 368042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 368142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 368242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 368342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 368442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 368542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 36867dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 36877dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 36887dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 3689006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 3690006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 3691006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 3692006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) { 36937dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3694bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 3695a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 3696a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 369742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek print_block(Out,Graph, *Node, GraphHelper, false); 3698a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 36997dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 37007dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 37017dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 37027dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 37037dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 37047dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 37057dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 37067dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 37077dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 37086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37097dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 3710bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 3711bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 3712bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 37137dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 37147dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 37157dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 3716