CFG.cpp revision 4c98b1f67cdf385e05a86d54201b319cf1f1c042
16960ee6c7cc8a8883126d9861beecb51a4e4a475Ted 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 15e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h" 16478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer#include "clang/AST/ASTContext.h" 172fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h" 182fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/CharUnits.h" 19b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump#include "clang/AST/DeclCXX.h" 2042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#include "clang/AST/PrettyPrinter.h" 212fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/StmtVisitor.h" 226cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/DenseMap.h" 230ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek#include "llvm/ADT/OwningPtr.h" 242fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/SmallPtrSet.h" 252fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/Allocator.h" 262fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/Format.h" 272fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/GraphWriter.h" 282fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/SaveAndRestore.h" 2983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 30fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenekusing namespace clang; 31fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 32fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremeneknamespace { 33fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 349c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic SourceLocation GetEndLoc(Decl *D) { 359c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(D)) 369c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *Ex = VD->getInit()) 37c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek return Ex->getSourceRange().getEnd(); 386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return D->getLocation(); 39c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek} 40ad5a894df1841698c824381b414630799adc26caTed Kremenek 413179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenekclass CFGBuilder; 423179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 4394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// The CFG builder uses a recursive algorithm to build the CFG. When 4494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// we process an expression, sometimes we know that we must add the 4594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// subexpressions as block-level expressions. For example: 4694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// exp1 || exp2 4894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// When processing the '||' expression, we know that exp1 and exp2 5094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// need to be added as block-level expressions, even though they 5194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// might not normally need to be. AddStmtChoice records this 5294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then 5394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// the builder has an option not to add a subexpression as a 5494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// block-level expression. 5594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 56852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekclass AddStmtChoice { 57852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekpublic: 58892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; 595ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 6094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} 615ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 623179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek bool alwaysAdd(CFGBuilder &builder, 633179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek const Stmt *stmt) const; 6494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 6594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// Return a copy of this object, except with the 'always-add' bit 6694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// set as specified. 6794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { 683179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); 6994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan } 7094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 71852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekprivate: 7294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan Kind kind; 73852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek}; 746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 75f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope - Node in tree of local scopes created for C++ implicit 76f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// destructor calls generation. It contains list of automatic variables 77f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// declared in the scope and link to position in previous scope this scope 78f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// began in. 79f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 80f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// The process of creating local scopes is as follows: 81f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null), 82f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Before processing statements in scope (e.g. CompoundStmt) create 83f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope object using CFGBuilder::ScopePos as link to previous scope 84f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// and set CFGBuilder::ScopePos to the end of new scope, 8535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points 86f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// at this VarDecl, 87f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every normal (without jump) end of scope add to CFGBlock destructors 88f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// for objects in the current scope, 89f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every jump add to CFGBlock destructors for objects 90f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// between CFGBuilder::ScopePos and local scope position saved for jump 91f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// target. Thanks to C++ restrictions on goto jumps we can be sure that 92f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// jump target position will be on the path to root from CFGBuilder::ScopePos 93f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// (adding any variable that doesn't need constructor to be called to 94f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope can break this assumption), 95f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 96f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiclass LocalScope { 97f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 98fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek typedef BumpVector<VarDecl*> AutomaticVarsTy; 99f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 100f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// const_iterator - Iterates local scope backwards and jumps to previous 10135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski /// scope on reaching the beginning of currently iterated scope. 102f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski class const_iterator { 103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const LocalScope* Scope; 104f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 105f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// VarIter is guaranteed to be greater then 0 for every valid iterator. 106f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Invalid iterator (with null Scope) has VarIter equal to 0. 107f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski unsigned VarIter; 108f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski public: 110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create invalid iterator. Dereferencing invalid iterator is not allowed. 111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Incrementing invalid iterator is allowed and will result in invalid 112f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// iterator. 113f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator() 114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(NULL), VarIter(0) {} 115f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 116f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create valid iterator. In case when S.Prev is an invalid iterator and 117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// I is equal to 0, this will create invalid iterator. 118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator(const LocalScope& S, unsigned I) 119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(&S), VarIter(I) { 120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Iterator to "end" of scope is not allowed. Handle it by going up 121f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // in scopes tree possibly up to invalid iterator in the root. 122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0 && Scope) 123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 124f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 125f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1269c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *const* operator->() const { 127f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (Scope && "Dereferencing invalid iterator is not allowed"); 128f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 129f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return &Scope->Vars[VarIter - 1]; 130f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1319c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *operator*() const { 132f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this->operator->(); 133f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 134f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1359c378f705405d37f49795d5e915989de774fe11fTed Kremenek const_iterator &operator++() { 136f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (!Scope) 137f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 138f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 139f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 140f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski --VarIter; 141f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0) 142f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 143f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 144f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 14535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator operator++(int) { 14635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator P = *this; 14735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski ++*this; 14835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return P; 14935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 150f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1519c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator==(const const_iterator &rhs) const { 152f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return Scope == rhs.Scope && VarIter == rhs.VarIter; 153f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1549c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator!=(const const_iterator &rhs) const { 155f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return !(*this == rhs); 156f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 15735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 1587247c88d1e41514a41085f83ebf03dd5220e054aDavid Blaikie LLVM_EXPLICIT operator bool() const { 15935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return *this != const_iterator(); 16035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 16135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 16235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int distance(const_iterator L); 163f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski }; 164f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 165f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski friend class const_iterator; 166f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 167f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiprivate: 168fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx; 169fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek 170f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Automatic variables in order of declaration. 171f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AutomaticVarsTy Vars; 172f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Iterator to variable in previous scope that was declared just before 173f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// begin of this scope. 174f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator Prev; 175f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 176f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 177f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Constructs empty scope linked to previous scope in specified place. 178fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek LocalScope(BumpVectorContext &ctx, const_iterator P) 179fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek : ctx(ctx), Vars(ctx, 4), Prev(P) {} 180f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 181f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Begin of scope in direction of CFG building (backwards). 182f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator begin() const { return const_iterator(*this, Vars.size()); } 18335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 1849c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addVar(VarDecl *VD) { 185fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Vars.push_back(VD, ctx); 18635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 187f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 188f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 18935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// distance - Calculates distance from this to L. L must be reachable from this 19035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. 19135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// number of scopes between this and L. 19235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderskiint LocalScope::const_iterator::distance(LocalScope::const_iterator L) { 19335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int D = 0; 19435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator F = *this; 19535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski while (F.Scope != L.Scope) { 1965290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek assert (F != const_iterator() 1975290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek && "L iterator is not reachable from F iterator."); 19835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter; 19935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski F = F.Scope->Prev; 20035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 20135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter - L.VarIter; 20235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return D; 20335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski} 20435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 20535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// BlockScopePosPair - Structure for specifying position in CFG during its 20635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// build process. It consists of CFGBlock that specifies position in CFG graph 20735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// and LocalScope::const_iterator that specifies position in LocalScope graph. 208f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskistruct BlockScopePosPair { 2099ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BlockScopePosPair() : block(0) {} 2109c378f705405d37f49795d5e915989de774fe11fTed Kremenek BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos) 2119ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek : block(b), scopePosition(scopePos) {} 212f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2139ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek CFGBlock *block; 2149ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek LocalScope::const_iterator scopePosition; 215f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 216f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 217e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// TryResult - a class representing a variant over the values 218e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, 219e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// and is used by the CFGBuilder to decide if a branch condition 220e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// can be decided up front during CFG construction. 221e71f3d587844110d836c82250830b27b1651afdbTed Kremenekclass TryResult { 222e71f3d587844110d836c82250830b27b1651afdbTed Kremenek int X; 223e71f3d587844110d836c82250830b27b1651afdbTed Kremenekpublic: 224e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 225e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult() : X(-1) {} 226e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 227e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isTrue() const { return X == 1; } 228e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isFalse() const { return X == 0; } 229e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isKnown() const { return X >= 0; } 230e71f3d587844110d836c82250830b27b1651afdbTed Kremenek void negate() { 231e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(isKnown()); 232e71f3d587844110d836c82250830b27b1651afdbTed Kremenek X ^= 0x1; 233e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 234e71f3d587844110d836c82250830b27b1651afdbTed Kremenek}; 235e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2365846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenekclass reverse_children { 2375846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek llvm::SmallVector<Stmt *, 12> childrenBuf; 2385846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek ArrayRef<Stmt*> children; 2395846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenekpublic: 2405846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek reverse_children(Stmt *S); 2415846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2425846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek typedef ArrayRef<Stmt*>::reverse_iterator iterator; 2435846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek iterator begin() const { return children.rbegin(); } 2445846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek iterator end() const { return children.rend(); } 2455846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek}; 2465846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2475846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2485846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenekreverse_children::reverse_children(Stmt *S) { 2495846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 2505846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek children = CE->getRawSubExprs(); 2515846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek return; 2525846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2535846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek switch (S->getStmtClass()) { 254b1855de3d61eab7d2f2e616ed59195f83e2a6dc0Ted Kremenek // Note: Fill in this switch with more cases we want to optimize. 2555846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek case Stmt::InitListExprClass: { 2565846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek InitListExpr *IE = cast<InitListExpr>(S); 2575846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()), 2585846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek IE->getNumInits()); 2595846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek return; 2605846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2615846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek default: 2625846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek break; 2635846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2645846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2655846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // Default case for all other statements. 2665846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek for (Stmt::child_range I = S->children(); I; ++I) { 2675846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek childrenBuf.push_back(*I); 2685846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2695846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2705846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // This needs to be done *after* childrenBuf has been populated. 2715846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek children = childrenBuf; 2725846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek} 2735846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 274a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 275fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 276fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 277fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 278fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 279fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 280fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 281fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 282fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 2836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 2846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 2856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 2866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 287c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 288ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 289f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpTarget; 290f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpSource; 291f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 292e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 2936f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CFG> cfg; 294ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 2959c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Block; 2969c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Succ; 297f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget ContinueJumpTarget; 298f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget BreakJumpTarget; 2999c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchTerminatedBlock; 3009c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *DefaultCaseBlock; 3019c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TryTerminatedBlock; 302e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 303f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Current position in local scope. 304f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 305f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 306f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // LabelMap records the mapping from Label expressions to their jump targets. 307ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy; 3080cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 3096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 3116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 312f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef std::vector<JumpSource> BackpatchBlocksTy; 3130cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 3146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 316ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy; 31719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 3186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31949b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu bool badCFG; 320b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &BuildOpts; 321e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 322e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // State to track for building switch statements. 323e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool switchExclusivelyCovered; 3240498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult *switchCond; 3250d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3260d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; 327a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek const Stmt *lastLookup; 32849b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu 3298c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Caches boolean evaluations of expressions to avoid multiple re-evaluations 3308c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // during construction of branches for chained logical operators. 3316955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy; 3326955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy CachedBoolEvals; 3338c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 3346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 335b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek explicit CFGBuilder(ASTContext *astContext, 336b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &buildOpts) 337b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek : Context(astContext), cfg(new CFG()), // crew a new CFG 338b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek Block(NULL), Succ(NULL), 339b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 340b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), 3410d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek switchExclusivelyCovered(false), switchCond(0), 342a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry(0), lastLookup(0) {} 3436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 344d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 345b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement); 3466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3470d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool alwaysAdd(const Stmt *stmt); 3480d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 3504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 351852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 352852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 3534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 354852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 3554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 356852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 3573fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 35856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, 35956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AddStmtChoice asc); 3603fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 3616960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 3626960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3636960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 3646960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); 3656960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); 3666960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 3676960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3686960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 3696960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3706960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 3716960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 3724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 3739c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitDeclSubExpr(DeclStmt *DS); 3743fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 3753fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 3766960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); 3773fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 3789c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt *G); 3794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 380a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); 3814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 3824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 3836960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc); 3845c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek CFGBlock *VisitLogicalOperator(BinaryOperator *B); 3853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B, 3863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Stmt *Term, 3873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *TrueBlock, 3883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *FalseBlock); 389115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 3904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 3914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 3934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 3946960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); 3954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 3964b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); 3976960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitReturnStmt(ReturnStmt *R); 398852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 3994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 4006960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 4016960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 40299cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); 4034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 4044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 405852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 406852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 4079c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitChildren(Stmt *S); 40855331da3211151aa67277aa095b7d301342200d4Ted Kremenek CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); 409cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 4108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Visitors to walk an AST and generate destructors of temporaries in 4118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // full expression. 4128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false); 4138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E); 4148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); 4158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, 4168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 41756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock * 41856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E, 41956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool BindToTemporary); 4208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 421274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 4229c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *NYS() { 4234102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 4244102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 4254102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 4266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 4284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 429dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *createNoReturnBlock(); 430d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 431df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 432df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 433852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 434cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt CFGBlock *addInitializer(CXXCtorInitializer *I); 4356a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 4369c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S); 4377c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 438239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 439239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 440239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 441239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4429c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeForStmt(Stmt *S); 4439c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, LocalScope* Scope = NULL); 4449c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = NULL); 445239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4469c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeAndDtors(Stmt *S); 447ad5a894df1841698c824381b414630799adc26caTed Kremenek 448239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 449d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek void appendStmt(CFGBlock *B, const Stmt *S) { 45074fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek if (alwaysAdd(S) && cachedEntry) 4510d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry->second = B; 4520d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 453ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose // All block-level expressions should have already been IgnoreParens()ed. 454ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); 455d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); 456ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 457cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { 45882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 45982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 4607c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 4617c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 4627c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4637c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 4647c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 4657c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { 4678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); 4688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 469c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) { 470c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext()); 471c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 472ad5a894df1841698c824381b414630799adc26caTed Kremenek 4739c378f705405d37f49795d5e915989de774fe11fTed Kremenek void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 47453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 47553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 4760a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void addSuccessor(CFGBlock *B, CFGBlock *S) { 477ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 478ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 4791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 480e71f3d587844110d836c82250830b27b1651afdbTed Kremenek /// Try and evaluate an expression to an integer constant. 481e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { 482e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 483e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return false; 484e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return !S->isTypeDependent() && 485f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek !S->isValueDependent() && 48651f4708c00110940ca3f337961915f2ca1668375Richard Smith S->EvaluateAsRValue(outResult, *Context); 487e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4890a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 49000998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 4910a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult tryEvaluateBool(Expr *S) { 49285df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (!BuildOpts.PruneTriviallyFalseEdges || 4938c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis S->isTypeDependent() || S->isValueDependent()) 494e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return TryResult(); 4958c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4968c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) { 4978c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 4988c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Check the cache first. 4996955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S); 5006955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi if (I != CachedBoolEvals.end()) 5018c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return I->second; // already in map; 5029260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi 5039260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi // Retrieve result at first, or the map might be updated. 5049260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi TryResult Result = evaluateAsBooleanConditionNoCache(S); 5059260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi CachedBoolEvals[S] = Result; // update or insert 5069260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi return Result; 5078c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5083d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek else { 5093d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek switch (Bop->getOpcode()) { 5103d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek default: break; 5113d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // For 'x & 0' and 'x * 0', we can determine that 5123d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // the value is always false. 5133d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek case BO_Mul: 5143d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek case BO_And: { 5153d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // If either operand is zero, we know the value 5163d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // must be false. 5173d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek llvm::APSInt IntVal; 5183d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) { 5193d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (IntVal.getBoolValue() == false) { 5203d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek return TryResult(false); 5213d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5223d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5233d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) { 5243d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (IntVal.getBoolValue() == false) { 5253d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek return TryResult(false); 5263d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5273d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5283d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5293d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek break; 5303d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5313d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5328c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5338c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5348c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return evaluateAsBooleanConditionNoCache(S); 5358c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5368c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5378c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis /// \brief Evaluate as boolean \param E without using the cache. 5388c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult evaluateAsBooleanConditionNoCache(Expr *E) { 5398c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) { 5408c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 5418c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult LHS = tryEvaluateBool(Bop->getLHS()); 5428c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isKnown()) { 5438c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We were able to evaluate the LHS, see if we can get away with not 5448c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 5458c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 5468c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue(); 5478c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5488c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 5498c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 5508c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->getOpcode() == BO_LOr) 5518c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() || RHS.isTrue(); 5528c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis else 5538c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() && RHS.isTrue(); 5548c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5558c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } else { 5568c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 5578c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 5588c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We can't evaluate the LHS; however, sometimes the result 5598c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. 5608c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 5618c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return RHS.isTrue(); 5628c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5638c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5648c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5658c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 5668c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5678c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5688c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5698c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis bool Result; 5708c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (E->EvaluateAsBooleanCondition(Result, *Context)) 5718c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return Result; 5728c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5738c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 57400998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 575e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 576d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 5776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5780d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekinline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, 5790d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const Stmt *stmt) const { 5800d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return builder.alwaysAdd(stmt) || kind == AlwaysAdd; 5810d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek} 582a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 5830d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekbool CFGBuilder::alwaysAdd(const Stmt *stmt) { 58474fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek bool shouldAdd = BuildOpts.alwaysAdd(stmt); 58574fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek 5860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!BuildOpts.forcedBlkExprs) 58774fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 588a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 589a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (lastLookup == stmt) { 590a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (cachedEntry) { 591a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry->first == stmt); 592a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek return true; 593a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 59474fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 595a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 5960d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 597a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek lastLookup = stmt; 598a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 599a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // Perform the lookup! 6000d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; 6010d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 602a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (!fb) { 603a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // No need to update 'cachedEntry', since it will always be null. 604a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry == 0); 60574fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 606a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 6070d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 6080d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); 609a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (itr == fb->end()) { 610a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry = 0; 61174fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 612a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 613a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 6140d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry = &*itr; 6150d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return true; 6163179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek} 6173179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 618898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 619898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 620f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCallstatic const VariableArrayType *FindVA(const Type *t) { 621f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { 622f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) 623610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 624610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 6256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 626610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 627610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 6286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 629610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 630610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 6316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 6336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 6346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 6356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 6366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 6379c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { 6380ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 6394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 6404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 641d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 6426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 6436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 6446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 64549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 646ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 64749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 6486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6497c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 6507c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 6517c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 6527c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 653d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 6541b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 6551b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6561b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 6571b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 6581b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 65982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 660b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 66182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 66282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 66382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 66482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 66582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 66682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 667b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 6686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 66982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 67082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 67182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6721b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 6731b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 6741b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 6751b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 676c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 6779c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = I->block; 6788343f8e00a222ca09dde536c77313e3e6e03ad59Rafael Espindola const GotoStmt *G = cast<GotoStmt>(B->getTerminator()); 6791b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 6806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6811b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 6821b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 6831b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 684d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 685f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 6869ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, 6879ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek JT.scopePosition); 6889ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, JT.block); 6891b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 6906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6911b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 6929c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (CFGBlock *B = cfg->getIndirectGotoBlock()) 6931b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 6941b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 6951b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6961b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 6971b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 6981b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6991b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 7001b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 7011b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 7021b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 7039ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, LI->second.block); 704c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 7056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 7066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 707322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 7086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 7091b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 710d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 7116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 712d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 713d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 7149c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::createBlock(bool add_successor) { 7159c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = cfg->createBlock(); 7164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 7170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(B, Succ); 718d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 719d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 7206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 721dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// createNoReturnBlock - Used to create a block is a 'noreturn' point in the 722dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// CFG. It is *not* connected to the current (global) successor, and instead 723dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// directly tied to the exit block in order to be reachable. 724dba3fb5413437dc613734fa4ffac892b11a37d25Chandler CarruthCFGBlock *CFGBuilder::createNoReturnBlock() { 725dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *B = createBlock(false); 72683754162f698a5dafad93fb89be0953651a604d0Chandler Carruth B->setHasNoReturnElement(); 727dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth addSuccessor(B, &cfg->getExit()); 728dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth return B; 729dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth} 730dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 73182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 732cbb67480094b3bcb5b715acd827cbad55e2a204cSean HuntCFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { 73382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 73482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 73582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 7378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 73882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 7408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 7418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Expr *Init = I->getInit(); 7428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 74300eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet if (FieldDecl *FD = I->getAnyMember()) 7448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = FD->getType()->isReferenceType(); 7454765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 74682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7475a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors && HasTemporaries) { 7488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 7494765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 7508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 7518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 75282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 7538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 7548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 7558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendInitializer(Block, I); 7568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 7578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 758892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek if (HasTemporaries) { 7598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 7608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 761892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 762892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek } 763892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(Init); 7648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 7658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 76682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 76782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 76882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7692d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// \brief Retrieve the type of the temporary object whose lifetime was 7702d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// extended by a local reference with the given initializer. 7712d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregorstatic QualType getReferenceInitTemporaryType(ASTContext &Context, 7722d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor const Expr *Init) { 7732d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (true) { 7742d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip parentheses. 7752d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = Init->IgnoreParens(); 7762d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7772d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through cleanups. 7782d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) { 7792d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = EWC->getSubExpr(); 7802d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7812d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7822d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7832d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through the temporary-materialization expression. 7842d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MaterializeTemporaryExpr *MTE 7852d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor = dyn_cast<MaterializeTemporaryExpr>(Init)) { 7862d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = MTE->GetTemporaryExpr(); 7872d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7882d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7892d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7902d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip derived-to-base and no-op casts. 7912d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const CastExpr *CE = dyn_cast<CastExpr>(Init)) { 7922d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if ((CE->getCastKind() == CK_DerivedToBase || 7932d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_UncheckedDerivedToBase || 7942d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_NoOp) && 7952d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init->getType()->isRecordType()) { 7962d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = CE->getSubExpr(); 7972d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7982d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7992d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8002d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 8012d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip member accesses into rvalues. 8022d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) { 8032d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (!ME->isArrow() && ME->getBase()->isRValue()) { 8042d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = ME->getBase(); 8052d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 8062d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8072d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8082d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 8092d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor break; 8102d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8112d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 8122d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor return Init->getType(); 8132d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor} 8142d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 815239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 816239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 817239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 8186a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 8199c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S) { 820239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 8216a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 8226a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 823239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 8246a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 825239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 826c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // We need to append the destructors in reverse order, but any one of them 827c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // may be a no-return destructor which changes the CFG. As a result, buffer 828c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // this sequence up and replay them in reverse order when appending onto the 829c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // CFGBlock(s). 830c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth SmallVector<VarDecl*, 10> Decls; 831c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.reserve(B.distance(E)); 832c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 833c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.push_back(*I); 834c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 835c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(), 836c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth E = Decls.rend(); 837c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth I != E; ++I) { 838c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If this destructor is marked as a no-return destructor, we need to 839c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // create a new block for the destructor which does not have as a successor 840c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far: control won't flow out of this block. 84188237bf587581026dcfc8386abf055cb201aa487Ted Kremenek QualType Ty = (*I)->getType(); 84288237bf587581026dcfc8386abf055cb201aa487Ted Kremenek if (Ty->isReferenceType()) { 8432d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit()); 8442d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 84588237bf587581026dcfc8386abf055cb201aa487Ted Kremenek Ty = Context->getBaseElementType(Ty); 84688237bf587581026dcfc8386abf055cb201aa487Ted Kremenek 847c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); 848cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (Dtor->isNoReturn()) 849dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 850dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 851c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 852c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 853c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth appendAutomaticObjDtor(Block, *I, S); 854c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 855239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 856239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 8577c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 8587c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 8597c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 8607c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 8617c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 8627c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 8637c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8647c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 8657c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 8667c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 8677c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 8687c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 8697c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 8707c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 8717c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8727c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8737c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8747c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 8757c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 8767c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 87723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!BI->isVirtual()) { 87823661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 87923661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 88023661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie autoCreateBlock(); 88123661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie appendBaseDtor(Block, BI); 88223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 88323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 8847c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8857c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8867c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 8877c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 8887c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 8898c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski // Check for constant size array. Set type to array element type. 8908c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QualType QT = FI->getType(); 8918c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 8928c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (AT->getSize() == 0) 8938c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski continue; 8948c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QT = AT->getElementType(); 8958c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski } 8968c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 8978c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 8987c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 8997c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 900581deb3da481053c4993c7600f97acf7768caac5David Blaikie appendMemberDtor(Block, *FI); 9017c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 9027c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 9037c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 9047c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 905239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 906239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 907239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 908239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 909fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); 910fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Scope = alloc.Allocate<LocalScope>(); 911fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx(alloc); 912fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek new (Scope) LocalScope(ctx, ScopePos); 913239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 914239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 915239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 916239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 917239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 91802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 9199c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeForStmt(Stmt *S) { 920239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 92102acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 92202acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 92302acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 924239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 925239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 926ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { 927239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 928239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 929a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth Stmt *SI = (*BI)->stripLabelLikeStatements(); 930ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) 931239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 932239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 93302acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 934239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 935239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 936239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 937239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 938a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements())) 939b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 940239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 941239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 942239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 943239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 9449c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS, 945b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 946239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 947239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 948239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 949239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 950239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 9519c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(*DI)) 952239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 953239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 954239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 955239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 956239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 957239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 958239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 959239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 9609c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, 961b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 962239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 963239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 964239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 965239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 966239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 967239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 968239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 969239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 970239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 971239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 972239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 973239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 974239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 975239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 9762d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (QT.getTypePtr()->isReferenceType()) { 97703e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor if (!VD->extendsLifetimeOfTemporary()) 978239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 9792d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 9802d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor QT = getReferenceInitTemporaryType(*Context, VD->getInit()); 981239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 982239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 983b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check for constant size array. Set type to array element type. 9842d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 985b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (AT->getSize() == 0) 986b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski return Scope; 987b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski QT = AT->getElementType(); 988b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski } 9894e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 990b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 9919c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 99223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 9934e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 9944e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 9954e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 9964e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 9974e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 998239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 999239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 1000239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 1001239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 1002239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 10039c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeAndDtors(Stmt *S) { 1004239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 1005239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 1006239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 1007239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 100802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 1009239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 1010239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 1011239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 101253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 101353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 101453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 101553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 101653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 1017c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// FIXME: This mechanism for adding automatic destructors doesn't handle 1018c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// no-return destructors properly. 10199c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 102053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 1021c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth BumpVectorContext &C = cfg->getBumpVectorContext(); 1022c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth CFGBlock::iterator InsertPos 1023c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); 1024c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 1025c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, 1026c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Blk->getTerminator()); 102753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 102853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 10294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 10306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 10316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 10329c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 1033f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 1034f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 1035f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 1036f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 1037ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 1038ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (Expr *E = dyn_cast<Expr>(S)) 1039ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose S = E->IgnoreParens(); 1040ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 10414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 10424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 1043852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 10444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 1046852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 10471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 104956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); 105056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 10514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 1052852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 10531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 105555331da3211151aa67277aa095b7d301342200d4Ted Kremenek return VisitNoRecurse(cast<Expr>(S), asc); 10564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 10584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 10591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 1061a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 10621de85338543dd6228eb518185e385d94d377f4cbJohn McCall case Stmt::CXXMemberCallExprClass: 10639fcce65e7e1307b5b8da9be13e4092d6bb94dc1dRichard Smith case Stmt::UserDefinedLiteralClass: 1064852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 10651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 10674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 10684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 1070852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 10734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 10741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 1076852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 10771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 10794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 10801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1081021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 1082021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 1083021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 10844765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall case Stmt::ExprWithCleanupsClass: 10854765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc); 108647e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 1087b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose case Stmt::CXXDefaultArgExprClass: 1088c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith case Stmt::CXXDefaultInitExprClass: 1089b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // FIXME: The expression inside a CXXDefaultArgExpr is owned by the 1090b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // called function's declaration, not by the caller. If we simply add 1091b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // this expression to the CFG, we could end up with the same Expr 1092b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // appearing multiple times. 1093b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // PR13385 / <rdar://problem/12156507> 1094c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // 1095c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // It's likewise possible for multiple CXXDefaultInitExprs for the same 1096c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // expression to be used in the same function (through aggregate 1097c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // initialization). 1098b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose return VisitStmt(S, asc); 1099b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose 1100a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXBindTemporaryExprClass: 1101a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); 1102a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 110381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXConstructExprClass: 110481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); 110581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 1106a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXFunctionalCastExprClass: 1107a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); 1108a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 110981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXTemporaryObjectExprClass: 111081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); 111181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 1112021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 1113021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 1114ad5a894df1841698c824381b414630799adc26caTed Kremenek 1115021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 1116021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 1117ad5a894df1841698c824381b414630799adc26caTed Kremenek 1118ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith case Stmt::CXXForRangeStmtClass: 1119ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); 1120ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 11214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 11224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 11231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 11254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 11261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 11284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 11291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 11314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 11321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 11344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 11351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 11374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 11381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1139892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek case Stmt::ImplicitCastExprClass: 1140892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); 1141a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 11424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 11434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 11441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 11464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 11471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 114883748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek case Stmt::LambdaExprClass: 114983748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return VisitLambdaExpr(cast<LambdaExpr>(S), asc); 115083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 1151115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 1152115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 1153115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 11546a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::NullStmtClass: 11556a9065a39ab15383082b914af28759da1652db18Ted Kremenek return Block; 11566a9065a39ab15383082b914af28759da1652db18Ted Kremenek 11574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 11581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 11591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11608e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek case Stmt::ObjCAutoreleasePoolStmtClass: 11618e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S)); 11628e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 11634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 11644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 11651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 11674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 11681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 11704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 11711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 11734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 11741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11756a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::OpaqueValueExprClass: 11764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11784b9c2d235fb9449e249d74f48ecfec601650de93John McCall case Stmt::PseudoObjectExprClass: 11794b9c2d235fb9449e249d74f48ecfec601650de93John McCall return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S)); 11804b9c2d235fb9449e249d74f48ecfec601650de93John McCall 11814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 11824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 11831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1184f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne case Stmt::UnaryExprOrTypeTraitExprClass: 1185f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), 1186f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne asc); 11871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 1189852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 11901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 11924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 11931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 119499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan case Stmt::UnaryOperatorClass: 119599cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan return VisitUnaryOperator(cast<UnaryOperator>(S), asc); 119699cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 11974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 11984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 11994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 12004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1202852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 12033179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, S)) { 12044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1205247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 12066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 12071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 12094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 12125846720f08a6b225484bfe663599c2b057a99bc8Ted KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt *S) { 12135846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek CFGBlock *B = Block; 12146b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek 12155846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // Visit the children in their reverse order so that they appear in 12165846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // left-to-right (natural) order in the CFG. 12175846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek reverse_children RChildren(S); 12185846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end(); 12195846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek I != E; ++I) { 12205846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (Stmt *Child = *I) 12215846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (CFGBlock *R = Visit(Child)) 12225846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek B = R; 12235846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 12245846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek return B; 12254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1227852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 1228852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 12294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 12306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12313179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, A)) { 12324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1233247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, A); 12346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 12356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 12374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 123999cae5b67b9711ca260e5b364a878a1a91183632Zhanyong WanCFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, 1240892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek AddStmtChoice asc) { 12413179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, U)) { 124299cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan autoCreateBlock(); 1243247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, U); 124499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan } 124599cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1246892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(U->getSubExpr(), AddStmtChoice()); 124799cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan} 124899cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 12495c3ea5c57971317c35b120ef0a2a2c79bd171008Ted KremenekCFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) { 12505c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 12515c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek appendStmt(ConfluenceBlock, B); 12521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12535c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (badCFG) 12545c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek return 0; 12551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12563f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(B, 0, ConfluenceBlock, ConfluenceBlock).first; 12573f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek} 1258862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 12593f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenekstd::pair<CFGBlock*, CFGBlock*> 12603f635c08b2d0b2d5bafb38da09589cb238407faaTed KremenekCFGBuilder::VisitLogicalOperator(BinaryOperator *B, 12613f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Stmt *Term, 12623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *TrueBlock, 12633f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *FalseBlock) { 12643f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12653f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Introspect the RHS. If it is a nested logical operation, we recursively 12663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // build the CFG using this function. Otherwise, resort to default 12673f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // CFG construction behavior. 12683f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *RHS = B->getRHS()->IgnoreParens(); 12693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *RHSBlock, *ExitBlock; 12703f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12713f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 12723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS)) 12733f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B_RHS->isLogicalOp()) { 12743f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(RHSBlock, ExitBlock) = 12753f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock); 12763f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 12773f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 12781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The RHS is not a nested logical operation. Don't push the terminator 12803f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // down further, but instead visit RHS and construct the respective 12813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // pieces of the CFG, and link up the RHSBlock with the terminator 12823f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // we have been provided. 12833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitBlock = RHSBlock = createBlock(false); 12843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!Term) { 12863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(TrueBlock == FalseBlock); 12873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, TrueBlock); 12883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 12893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else { 12903f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek RHSBlock->setTerminator(Term); 12913f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal = tryEvaluateBool(RHS); 12923f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, KnownVal.isFalse() ? NULL : TrueBlock); 12933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, KnownVal.isTrue() ? NULL : FalseBlock); 12943f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 12953f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = RHSBlock; 12973f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek RHSBlock = addStmt(RHS); 12985c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } 12993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek while (false); 13003f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13013f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (badCFG) 13023f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair((CFGBlock*)0, (CFGBlock*)0); 13038c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 13045c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // Generate the blocks for evaluating the LHS. 13053f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *LHS = B->getLHS()->IgnoreParens(); 13063f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13073f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS)) 13083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B_LHS->isLogicalOp()) { 13093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B->getOpcode() == BO_LOr) 13103f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek FalseBlock = RHSBlock; 13113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else 13123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TrueBlock = RHSBlock; 13133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // For the LHS, treat 'B' as the terminator that we want to sink 13153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // into the nested branch. The RHS always gets the top-most 13163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // terminator. 13173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock); 13183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 13193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Create the block evaluating the LHS. 13213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // This contains the '&&' or '||' as the terminator. 13223f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *LHSBlock = createBlock(false); 13233f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek LHSBlock->setTerminator(B); 13243f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13255c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek Block = LHSBlock; 13263f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryLHSBlock = addStmt(LHS); 13273f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13283f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (badCFG) 13293f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair((CFGBlock*)0, (CFGBlock*)0); 13305c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek 13315c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // See if this is a known constant. 13323f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal = tryEvaluateBool(LHS); 13335c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek 13345c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // Now link the LHSBlock with RHSBlock. 13355c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (B->getOpcode() == BO_LOr) { 13363f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : TrueBlock); 13373f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : RHSBlock); 13385c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } else { 13395c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek assert(B->getOpcode() == BO_LAnd); 13405c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 13413f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : FalseBlock); 13425c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } 134300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 13443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair(EntryLHSBlock, ExitBlock); 13455c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek} 13461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13485c3ea5c57971317c35b120ef0a2a2c79bd171008Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 13495c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek AddStmtChoice asc) { 13505c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // && or || 13515c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (B->isLogicalOp()) 13525c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek return VisitLogicalOperator(B); 135336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 135436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->getOpcode() == BO_Comma) { // , 13556dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 1356247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 13574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 13584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 13596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 136036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 136136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->isAssignmentOp()) { 13623179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1363fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 1364247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1365fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 1366892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(B->getLHS()); 1367e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 1368fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 13691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13703179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1371e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 1372247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1373e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 1374e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 1375a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *RBlock = Visit(B->getRHS()); 1376a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *LBlock = Visit(B->getLHS()); 1377a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr 1378a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // containing a DoStmt, and the LHS doesn't create a new block, then we should 1379a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // return RBlock. Otherwise we'll incorrectly return NULL. 1380a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu return (LBlock ? LBlock : RBlock); 13814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 13826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 138355331da3211151aa67277aa095b7d301342200d4Ted KremenekCFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) { 13843179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 1385721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 1386247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 1387721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 1388721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 13894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1390cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 13914f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 13924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 13934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 1394d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1395d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 13961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 13984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 13994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 14001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 14024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 14039ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (BreakJumpTarget.block) { 14049ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B); 14059ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, BreakJumpTarget.block); 1406f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 14074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 14081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 14114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 14121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14138026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redlstatic bool CanThrow(Expr *E, ASTContext &Ctx) { 14144c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 14154c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 14164c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 14174c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 14184c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 1419ad5a894df1841698c824381b414630799adc26caTed Kremenek 14204c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 14214c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 14224c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 1423b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) && 1424e6975e9b0985ad7f7ff9187e38d95bfe9ac4181bRichard Smith Proto->isNothrow(Ctx)) 14254c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 14264c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 14274c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 14284c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 14294c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1430852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 14311de85338543dd6228eb518185e385d94d377f4cbJohn McCall // Compute the callee type. 14321de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType calleeType = C->getCallee()->getType(); 14331de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (calleeType == Context->BoundMemberTy) { 14341de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType boundType = Expr::findBoundMemberType(C->getCallee()); 14351de85338543dd6228eb518185e385d94d377f4cbJohn McCall 14361de85338543dd6228eb518185e385d94d377f4cbJohn McCall // We should only get a null bound type if processing a dependent 14371de85338543dd6228eb518185e385d94d377f4cbJohn McCall // CFG. Recover by assuming nothing. 14381de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (!boundType.isNull()) calleeType = boundType; 14392455636163fdd18581d7fdae816433f886d88213Mike Stump } 14402455636163fdd18581d7fdae816433f886d88213Mike Stump 14411de85338543dd6228eb518185e385d94d377f4cbJohn McCall // If this is a call to a no-return function, this stops the block here. 14421de85338543dd6228eb518185e385d94d377f4cbJohn McCall bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); 14431de85338543dd6228eb518185e385d94d377f4cbJohn McCall 14444c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 1445079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1446079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 14474e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (Context->getLangOpts().Exceptions) { 14486c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 14494c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 1450079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 1451079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1452079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 1453cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (FD->isNoReturn()) 14542455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 1455079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 14564c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 1457079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 14582455636163fdd18581d7fdae816433f886d88213Mike Stump 14598026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (!CanThrow(C->getCallee(), *Context)) 14604c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 14614c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 146294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan if (!NoReturn && !AddEHEdge) 146394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan return VisitStmt(C, asc.withAlwaysAdd(true)); 14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1465079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1466079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1467d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1468079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1469079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 14701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1471dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (NoReturn) 1472dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 1473dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 1474dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createBlock(); 1475dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 1476247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 14772455636163fdd18581d7fdae816433f886d88213Mike Stump 14784c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1479079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1480079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 14810a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 1482079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 14830a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 1484079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 14851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14862455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1487d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1488d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1489852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1490852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 14919c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1492247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1493d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14943fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 14951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 149694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 14973fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 14983fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 14999c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd); 1500d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15013fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 15021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15033fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 15043fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 15059c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd); 1506d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15073fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 15081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15093fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 151000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 15110a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 15120a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 15130a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 15143fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 15151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 15163fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 15171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15199c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) { 1520fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 15219c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LastBlock = Block; 15224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 15234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 15244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1525334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1526334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1527334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1528334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 15291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1530e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1531e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 15321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1533079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 15344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 15354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 15361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 153756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallCFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, 1538852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 153956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); 154056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL); 154156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 1542f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1543f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 15449c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1545247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1546d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1547f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 15481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 154994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 1550115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1551f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1552f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1553f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1554f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1555f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1556f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 15579c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = 0; 155856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const Expr *trueExpr = C->getTrueExpr(); 155956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (trueExpr != opaqueValue) { 156056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); 1561d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1562f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1563f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1564f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 1565f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek else 1566f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek LHSBlock = ConfluenceBlock; 15671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1568f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1569f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 15709c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); 1571d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1572f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 15731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 157456df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith // If the condition is a logical '&&' or '||', build a more accurate CFG. 157556df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 157656df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens())) 157756df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (Cond->isLogicalOp()) 157856df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first; 157956df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith 1580f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1581f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 15821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 158300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 15840a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 1585f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 15860a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1587f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 158856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Expr *condExpr = C->getCond(); 1589d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1590f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (opaqueValue) { 1591f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Run the condition expression if it's not trivially expressed in 1592f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // terms of the opaque value (or if there is no opaque value). 1593f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (condExpr != opaqueValue) 1594f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addStmt(condExpr); 1595d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1596f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Before that, run the common subexpression if there was one. 1597f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // At least one of this or the above will be run. 1598f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(BCO->getCommon()); 1599f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek } 1600f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek 1601f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(condExpr); 1602f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1603f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 16044f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 1605bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // Check if the Decl is for an __label__. If so, elide it from the 1606bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // CFG entirely. 1607bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek if (isa<LabelDecl>(*DS->decl_begin())) 1608bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek return Block; 1609bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek 161029c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // This case also handles static_asserts. 16118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (DS->isSingleDecl()) 16128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitDeclSubExpr(DS); 16131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 16151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1616fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose // Build an individual DeclStmt for each decl. 1617fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(), 1618fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose E = DS->decl_rend(); 1619fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose I != E; ++I) { 16204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 16214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 16224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 16231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 16254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 16264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 16274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 16281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 16294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 163049a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose cfg->addSyntheticDeclStmt(DSNew, DS); 16311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 16338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = VisitDeclSubExpr(DSNew); 16344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 16351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 16374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 16381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 16408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski/// DeclStmts and initializers in them. 16419c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { 16428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert(DS->isSingleDecl() && "Can handle single declarations only."); 16438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 16441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!VD) { 16462794bc0e3757992194dd587d0f6a253ec72afc9aJordan Rose // Of everything that can be declared in a DeclStmt, only VarDecls impact 16472794bc0e3757992194dd587d0f6a253ec72afc9aJordan Rose // runtime semantics. 16484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 16498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 16501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 16528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 16538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 1654fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek // Guard static initializers under a branch. 16555062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek CFGBlock *blockAfterStaticInit = 0; 16565062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek 16575062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) { 16585062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek // For static variables, we need to create a branch to track 16595062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek // whether or not they are initialized. 16605062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (Block) { 16615062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek Succ = Block; 16625062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek Block = 0; 16635062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (badCFG) 16645062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek return 0; 16655062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek } 16665062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek blockAfterStaticInit = Succ; 16675062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek } 1668fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek 16698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 16708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 16714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 16728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 16738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = VD->getType()->isReferenceType(); 16744765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 16758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 16765a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors && HasTemporaries) { 16778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 16784765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 16798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 16808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 16818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 16828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 16838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1684892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 1685550f2234fc9218914c325041067052342dfce553Ted Kremenek 1686550f2234fc9218914c325041067052342dfce553Ted Kremenek // Keep track of the last non-null block, as 'Block' can be nulled out 1687550f2234fc9218914c325041067052342dfce553Ted Kremenek // if the initializer expression is something like a 'while' in a 1688550f2234fc9218914c325041067052342dfce553Ted Kremenek // statement-expression. 1689550f2234fc9218914c325041067052342dfce553Ted Kremenek CFGBlock *LastBlock = Block; 16901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 1692550f2234fc9218914c325041067052342dfce553Ted Kremenek if (HasTemporaries) { 16938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 16948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 1695550f2234fc9218914c325041067052342dfce553Ted Kremenek ExprWithCleanups *EC = cast<ExprWithCleanups>(Init); 1696550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(EC->getSubExpr())) 1697550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1698550f2234fc9218914c325041067052342dfce553Ted Kremenek } 1699550f2234fc9218914c325041067052342dfce553Ted Kremenek else { 1700550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(Init)) 1701550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1702550f2234fc9218914c325041067052342dfce553Ted Kremenek } 17034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 17041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 1706f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); 17078f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) { 17088f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek if (CFGBlock *newBlock = addStmt(VA->getSizeExpr())) 17098f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek LastBlock = newBlock; 17108f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek } 17111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1712fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1713fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1714fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1715fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 17160f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek CFGBlock *B = LastBlock; 17175062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (blockAfterStaticInit) { 1718fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek Succ = B; 17190f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek Block = createBlock(false); 17200f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek Block->setTerminator(DS); 17215062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek addSuccessor(Block, blockAfterStaticInit); 17220f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek addSuccessor(Block, B); 17230f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek B = Block; 1724fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek } 1725fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek 1726fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek return B; 1727d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1728fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 17299c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { 17306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 17316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 17326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 17336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 17346c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 17356c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 17366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 173704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 173804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 173904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 174004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 174104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 174204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 17439c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 174404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 174504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 174604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 174704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 174804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 1749fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // The block we were processing is now finished. Make it the successor 17506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 17516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1752d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1753d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17544e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1755c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 17566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1757b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 17589c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ElseBlock = Succ; 17596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17609c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Else = I->getElse()) { 1761d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 17626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1763d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 17646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1765d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 176604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 176704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 176804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 176904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 177004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 177104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 17724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 17736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1774b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1775b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 17764e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1777d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17784e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17794e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1780c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 17816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1782b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 17839c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ThenBlock; 1784d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 17859c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *Then = I->getThen(); 17866db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1787d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 17886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 178904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 179004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 179104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 179204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 179304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 179404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 17954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 17966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1797dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1798dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1799dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1800dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1801dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 18020a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ThenBlock, sv.get()); 18036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1804d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18054e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 18070cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1808d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 18093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by 18103f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // having these handle the actual control-flow jump. Note that 18113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)" 18123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // we resort to the old control-flow behavior. This special handling 18133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // removes infeasible paths from the control-flow graph by having the 18143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // control-flow transfer of '&&' or '||' go directly into the then/else 18153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // blocks directly. 18163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!I->getConditionVariable()) 181756df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 181856df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens())) 18193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) 18203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first; 18213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 18226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1823d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 18246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1825d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1826d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 18276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 182800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 18290a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(I->getCond()); 183000998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1831d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 18320a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 18330a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 18346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 18366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 18376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 18388f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek CFGBlock *LastBlock = addStmt(I->getCond()); 1839ad5a894df1841698c824381b414630799adc26caTed Kremenek 184061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 184161dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 184261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 184361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 184461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 1845d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, I->getConditionVariableDeclStmt()); 18468f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek LastBlock = addStmt(Init); 184761dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 184861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1849ad5a894df1841698c824381b414630799adc26caTed Kremenek 18508f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek return LastBlock; 1851d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 18526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18549c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) { 18556c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1856d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 18576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 18586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 18596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 18606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1861d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1862d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1863d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 18646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1865d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 1866fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 18670a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 18686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 18706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1871852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1872d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 18730cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 18749c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { 1875d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 18764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 1877ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner CFGBlock *LabelBlock = Block; 18786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 18804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 18816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1882ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner assert(LabelMap.find(L->getDecl()) == LabelMap.end() && 1883ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner "label already in map"); 1884ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); 18856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 18876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 18886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 18896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 18909cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1891d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1895d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 18966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1897d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1898d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 18996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1900d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1901d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 190231dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 190383748e2f41ea0ac7c954946feb5da9ccc6ab8becTed KremenekCFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { 190483748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *LastBlock = VisitNoRecurse(E, asc); 190583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), 190683748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek et = E->capture_init_end(); it != et; ++it) { 190783748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Expr *Init = *it) { 190883748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *Tmp = Visit(Init); 190983748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Tmp != 0) 191083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek LastBlock = Tmp; 191183748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 191283748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 191383748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return LastBlock; 191483748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek} 191583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 19169c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { 19176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 19186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 19194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1920d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1921d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 19226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1924d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 19256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1926d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1927d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1928f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1929f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1930f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 19319ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, JT.scopePosition, G); 19329ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, JT.block); 1933f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1934d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 19356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1936d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1937d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 19389c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { 19399c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 19406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 194147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 194247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 194347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 194447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 194547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 194647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 194747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 19489c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Init = F->getInit()) 194947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1950f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1951f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 19529c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = F->getConditionVariable()) 195347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 195447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 195547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 195647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 195747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1958fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1959fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1960d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1961d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19624e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1963d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 19644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 19654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 19666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19673f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 19683f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 1969f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 197047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 19713f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 19723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *BodyBlock = 0, *TransitionBlock = 0; 197300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1974d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1975d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 19766db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 19776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19783f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Save the current values for Block, Succ, continue and break targets. 19793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 19803f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 19816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19823f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Create an empty block to represent the transition block for looping back 19833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // to the head of the loop. If we have increment code, it will 19843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // go in this block as well. 19853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = Succ = TransitionBlock = createBlock(false); 19863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TransitionBlock->setLoopTarget(F); 19876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19889c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInc()) { 19896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 19906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 19914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 1992e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 19936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19943575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 19953575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 19963575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1997d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19984e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19993575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 20003575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 20016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20023f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The starting block for the loop increment is the block that should 20033f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 20043f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 20053f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ContinueJumpTarget.block->setLoopTarget(F); 20066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20073f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Loop body should end with destructor of Condition variable (if any). 20083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 20093575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 201047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 201147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 201247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 201347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 201447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 20156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 20166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 20173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = addStmt(F->getBody()); 2018af603f742491dc4707138c0293d295171fdd51baTed Kremenek 20193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!BodyBlock) { 20203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // In the case of "for (...;...;...);" we can have a null BodyBlock. 20213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Use the continue jump target as the proxy for the body. 20223f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = ContinueJumpTarget.block; 20233f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 2024d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 2025941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 20263f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20273f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20283f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because of short-circuit evaluation, the condition of the loop can span 20293f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 20303f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // evaluate the condition. 20313f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0; 20323f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20333f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 20343f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *C = F->getCond(); 20353f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20363f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle logical operators, which have a slightly 20373f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // more optimal CFG representation. 203856df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 203956df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : 0)) 20403f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) { 20413f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(EntryConditionBlock, ExitConditionBlock) = 20423f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor); 20433f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 20443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20463f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The default case when not handling logical operators. 20473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = ExitConditionBlock = createBlock(false); 20483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitConditionBlock->setTerminator(F); 20493f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20503f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // See if this is a known constant. 20513f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal(true); 20523f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20533f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (C) { 20543f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Now add the actual condition to the condition block. 20553f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because the condition itself may contain control-flow, new blocks may 20563f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // be created. Thus we update "Succ" after adding the condition. 20573f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = ExitConditionBlock; 20583f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(C); 20593f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20603f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // If this block contains a condition variable, add both the condition 20613f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // variable and initializer to the CFG. 20623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (VarDecl *VD = F->getConditionVariable()) { 20633f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Expr *Init = VD->getInit()) { 20643f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek autoCreateBlock(); 20653f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek appendStmt(Block, F->getConditionVariableDeclStmt()); 20663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(Init); 20673f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(Block == EntryConditionBlock); 20683f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20703f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20713f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Block && badCFG) 20723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 20733f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20743f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek KnownVal = tryEvaluateBool(C); 20753f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20763f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20773f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Add the loop body entry as a successor to the condition. 20780a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 20793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the condition block with the code that follows the loop. (the 20803f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // false branch). 20813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 20826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } while (false); 20843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the loop-back block to the entry condition block. 20863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(TransitionBlock, EntryConditionBlock); 20873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The condition block is the implicit successor for any code above the loop. 20893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Succ = EntryConditionBlock; 20906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2091d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 20926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 20939c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInit()) { 2094d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 209549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 20962bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 209736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 209836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // There is no loop initialization. We are thus basically a while loop. 209936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // NULL out Block to force lazy block construction. 210036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Block = NULL; 210136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Succ = EntryConditionBlock; 210236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return EntryConditionBlock; 2103d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2104d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2105115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 21063179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, M)) { 2107115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 2108247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, M); 2109115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 2110892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(M->getBase()); 2111115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 2112115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 21139c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { 2114514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 2115514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 2116514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2117514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 2118514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2119514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 2120514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2121514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 2122514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 2123514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 2124514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 21254cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 2126514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 2127514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 2128514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 2129514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 2130514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 2131514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 2132514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 2133514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2134514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 2135514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2136514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 2137514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 2138514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2139514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 2140514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 21416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 21426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 21436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 2144514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 21456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21469c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = 0; 21476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2148514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 2149d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21504e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2151514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 2152514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 21534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 21544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 21556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21564cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 21579c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 21586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21594cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 21606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 21616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 21636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 21646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 2165892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(ExitConditionBlock, S); 21664cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 21676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21684cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 2169fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // generate new blocks as necessary. We DON'T add the statement by default to 21706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 2171012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek CFGBlock *EntryConditionBlock = Visit(S->getElement(), 2172012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek AddStmtChoice::NotAlwaysAdd); 21736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 2174d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21754e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21764e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 21774e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 21786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 21806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 21814cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 21826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21834cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 21846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 21854cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 21864c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2187f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 21884c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks save_break(BreakJumpTarget); 21894c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks 21904c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks // Add an intermediate block between the BodyBlock and the 21914c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks // EntryConditionBlock to represent the "loop back" transition, for looping 21924c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks // back to the head of the loop. 21934c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks CFGBlock *LoopBackBlock = 0; 21944c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks Succ = LoopBackBlock = createBlock(); 21954c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks LoopBackBlock->setLoopTarget(S); 21964c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks 2197f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 21984c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks ContinueJumpTarget = JumpTarget(Succ, ScopePos); 21996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22009c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(S->getBody()); 22016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22024cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 22034c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks BodyBlock = ContinueJumpTarget.block; // can happen for "for (X in Y) ;" 22044e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2205d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22064e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 22074e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 22086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22094cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 22100a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, BodyBlock); 22114cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 22126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22134cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 22144cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 22150a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopSuccessor); 22164cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 2217514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 22184cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 2219514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 22206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 22216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22228e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted KremenekCFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { 22238e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // Inline the body. 22248e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return addStmt(S->getSubStmt()); 22258e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // TODO: consider adding cleanups for the end of @autoreleasepool scope. 22268e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek} 22278e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 22289c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 2229b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 22306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2231b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 22324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 22336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2234da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 2235da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 2236da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 2237d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2238da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 22396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2240da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 2241fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 2242da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 22436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22444beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 22454beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 2246247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 22474beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 2248b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 22494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 2250b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 22516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22529c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { 22534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 225490658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 2255e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 2256514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 22574b9c2d235fb9449e249d74f48ecfec601650de93John McCallCFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { 22584b9c2d235fb9449e249d74f48ecfec601650de93John McCall autoCreateBlock(); 22594b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22604b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Add the PseudoObject as the last thing. 22614b9c2d235fb9449e249d74f48ecfec601650de93John McCall appendStmt(Block, E); 22624b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22634b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *lastBlock = Block; 22644b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22654b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Before that, evaluate all of the semantics in order. In 22664b9c2d235fb9449e249d74f48ecfec601650de93John McCall // CFG-land, that means appending them in reverse order. 22674b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (unsigned i = E->getNumSemanticExprs(); i != 0; ) { 22684b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *Semantic = E->getSemanticExpr(--i); 22694b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22704b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If the semantic is an opaque value, we're being asked to bind 22714b9c2d235fb9449e249d74f48ecfec601650de93John McCall // it to its source expression. 22724b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) 22734b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantic = OVE->getSourceExpr(); 22744b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22754b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (CFGBlock *B = Visit(Semantic)) 22764b9c2d235fb9449e249d74f48ecfec601650de93John McCall lastBlock = B; 22774b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 22784b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22794b9c2d235fb9449e249d74f48ecfec601650de93John McCall return lastBlock; 22804b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 22814b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22829c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { 22839c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 22846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 228505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 228605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 228705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 228805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 228905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 229005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 2291f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 22929c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 229305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 229405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 229505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 2296f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2297fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 2298fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 2299d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2300d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23014e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2302d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 23036b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek Block = 0; 23043f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } else { 23054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 230649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 23076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *BodyBlock = 0, *TransitionBlock = 0; 230900998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2310d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 2311d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 2312f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 2313d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 23143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Save the current values for Block, Succ, continue and break targets. 2315f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2316f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 23173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek save_break(BreakJumpTarget); 2318f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 23196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 23206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 23213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Succ = TransitionBlock = createBlock(false); 23223f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TransitionBlock->setLoopTarget(W); 2323f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 23246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2325d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 232605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 23276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 232805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 232905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 233005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 233105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 233205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 233305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 233405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 233505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2336d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 23373f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = addStmt(W->getBody()); 23386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2339af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 23409ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;" 23413f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else if (Block && badCFG) 23423f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 23433f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 23443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23453f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because of short-circuit evaluation, the condition of the loop can span 23463f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 23473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // evaluate the condition. 23483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0; 23493f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23503f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 23513f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *C = W->getCond(); 23523f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23533f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle logical operators, which have a slightly 23543f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // more optimal CFG representation. 235556df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens())) 23563f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) { 23573f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(EntryConditionBlock, ExitConditionBlock) = 23583f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(Cond, W, BodyBlock, 23593f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek LoopSuccessor); 23603f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 23613f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 23623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23633f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The default case when not handling logical operators. 2364857f5681f5e2bbb482f41f461add502b556c712aTed Kremenek ExitConditionBlock = createBlock(false); 23653f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitConditionBlock->setTerminator(W); 23663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23673f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Now add the actual condition to the condition block. 23683f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because the condition itself may contain control-flow, new blocks may 23693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // be created. Thus we update "Succ" after adding the condition. 23703f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = ExitConditionBlock; 23713f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = EntryConditionBlock = addStmt(C); 23723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23733f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // If this block contains a condition variable, add both the condition 23743f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // variable and initializer to the CFG. 23753f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 23763f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Expr *Init = VD->getInit()) { 23773f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek autoCreateBlock(); 23783f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek appendStmt(Block, W->getConditionVariableDeclStmt()); 23793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(Init); 23803f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(Block == EntryConditionBlock); 23813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 23824e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 23836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Block && badCFG) 23853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 23863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // See if this is a known constant. 23883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C); 23893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 2390941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 23910a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 23923f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the condition block with the code that follows the loop. (the 23933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // false branch). 23943f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 23953f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } while(false); 23976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23983f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the loop-back block to the entry condition block. 23993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(TransitionBlock, EntryConditionBlock); 24006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 24026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 2403d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 24046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24054ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 24065482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 240749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 2408d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 24091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24119c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { 24124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 24134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 24144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 24154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 24166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24179c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { 24182fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 24192fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 24206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24216c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2422d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 24246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24252fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 24262fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 24276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24282fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 24290a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 24306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 24326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 2433852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 24342fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 2435989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 24369c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { 24376c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2438d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24390979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 24400979d80615df97c675423de631c1b884819f4712Mike Stump 24410979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 24420979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 24430979d80615df97c675423de631c1b884819f4712Mike Stump 24445d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 24455d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 24460a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 2447ad5a894df1841698c824381b414630799adc26caTed Kremenek else 24485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 24490a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 24500979d80615df97c675423de631c1b884819f4712Mike Stump 24510979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 24520979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 2453852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 24540979d80615df97c675423de631c1b884819f4712Mike Stump} 24550979d80615df97c675423de631c1b884819f4712Mike Stump 24569c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { 24579c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 24586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24598f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 24608f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 2461d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2462d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24634e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2464d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 24654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 24664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 24676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 24696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 24706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 24719c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 24729c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 24736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 247449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 24756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 24766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 24786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 24799c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) { 248049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 248149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 24824e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2483d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24844e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 24854e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 248649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 24876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24885482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 248949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 249049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 249100998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 24920a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(D->getCond()); 249300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2494d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 24959c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = NULL; 2496d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 24976db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 24986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2499d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2500f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2501f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2502f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 25036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2504d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 2505f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 25066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2507d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 2508f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 25096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2510d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2511b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 25126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 251305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 251405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 251505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 251605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 251705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2518d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 25194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 25206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2521af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 2522a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 25234e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2524d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25254e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 25264e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 25276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2528d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 2529d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 2530d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 2531d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 2532d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 2533d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 2534d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 2535d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 2536d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 2537d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 2538d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 2539d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 25400a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopBackBlock); 2541d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 2542d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 25430a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, NULL); 2544b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 25456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2546941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 2547941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 25480a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 25496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 25516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 2552d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 25536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2554d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 25555482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 2556d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 2557d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2558d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 25599c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { 2560d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 2561d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 2562d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2563d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 25646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2565d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 2566d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 2567d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 25686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2569d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 2570235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 25719ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (ContinueJumpTarget.block) { 25729ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C); 25739ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, ContinueJumpTarget.block); 2574f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 2575235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 25766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2577d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 2578d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 25791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2580f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter CollingbourneCFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 2581f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc) { 258213fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 25833179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 258413fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2585892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, E); 258613fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 25871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 258997e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek CFGBlock *lastBlock = Block; 259097e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek 25914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 2592f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); 25934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 259497e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek lastBlock = addStmt(VA->getSizeExpr()); 2595f91a5b008d1a63630ae483247204c2651e512fa1Ted Kremenek } 259697e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek return lastBlock; 2597d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 25981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 26004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 26019c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 26023179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, SE)) { 260313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2604892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, SE); 260513fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 26064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 26074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2608d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 26099c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { 26106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 26116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 26129c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchSuccessor = NULL; 26136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26148ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 26158ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 26168ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 26178ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 26188ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 26198ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 26209c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 26218ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 26228ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 26238ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 26248ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 26258ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2626d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2627d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 26284e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2629d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 26306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2631d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2632d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2633d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2634eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2635f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2636eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 26376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 26386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 26396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2640eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 26416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2642d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2643d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 26446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2645d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2646d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2647d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2648f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 26496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 26516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 26526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 26536db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 265449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 26558ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2656e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // For pruning unreachable case statements, save the current state 2657e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // for tracking the condition value. 2658e71f3d587844110d836c82250830b27b1651afdbTed Kremenek SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered, 2659e71f3d587844110d836c82250830b27b1651afdbTed Kremenek false); 26600498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2661e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Determine if the switch condition can be explicitly evaluated. 2662e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 26630498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult result; 2664e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek bool b = tryEvaluate(Terminator->getCond(), result); 2665e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, 2666e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek b ? &result : 0); 26670498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 26688ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 26698ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 26708ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 26718ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 26728ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2673d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 26744e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2675d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 26764e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 26774e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 267849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 26796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 2680432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // following the switch body. Moreover, take into account if all the 2681432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // cases of a switch are covered (e.g., switching on an enum value). 26822a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer // 26832a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer // Note: We add a successor to a switch that is considered covered yet has no 26842a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer // case statements if the enumeration has no enumerators. 26852a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer bool SwitchAlwaysHasSuccessor = false; 26862a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer SwitchAlwaysHasSuccessor |= switchExclusivelyCovered; 26872a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() && 26882a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer Terminator->getSwitchCaseList(); 2689e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 26902a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer SwitchAlwaysHasSuccessor ? 0 : DefaultCaseBlock); 26916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 269249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2693411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 2694d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 26958f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek CFGBlock *LastBlock = addStmt(Terminator->getCond()); 2696ad5a894df1841698c824381b414630799adc26caTed Kremenek 26976b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 26986b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 26996b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 27006b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 27016b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 2702d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, Terminator->getConditionVariableDeclStmt()); 27038f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek LastBlock = addStmt(Init); 27046b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 27056b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2706ad5a894df1841698c824381b414630799adc26caTed Kremenek 27078f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek return LastBlock; 2708d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2709e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2710e71f3d587844110d836c82250830b27b1651afdbTed Kremenekstatic bool shouldAddCase(bool &switchExclusivelyCovered, 2711e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const Expr::EvalResult *switchCond, 2712e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const CaseStmt *CS, 2713e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ASTContext &Ctx) { 2714e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (!switchCond) 2715e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek return true; 2716e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek 2717e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool addCase = false; 27180498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2719e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!switchExclusivelyCovered) { 2720e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (switchCond->Val.isInt()) { 2721e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the LHS of the case value. 272285df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx); 2723e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const llvm::APSInt &condInt = switchCond->Val.getInt(); 2724e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2725e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (condInt == lhsInt) { 2726e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2727e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2728e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2729e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else if (condInt < lhsInt) { 2730e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (const Expr *RHS = CS->getRHS()) { 2731e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the RHS of the case value. 273285df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx); 273385df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (V2 <= condInt) { 2734e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2735e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2736e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2737e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2738e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2739e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2740e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else 2741e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2742e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2743e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return addCase; 2744e71f3d587844110d836c82250830b27b1651afdbTed Kremenek} 2745d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 27469c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) { 27476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 27486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 27490fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 27500498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 27510fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 27520fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 27530fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 27540fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 27550fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 27560a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek CFGBlock *currentBlock = createBlock(false); 27570a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek currentBlock->setLabel(CS); 27580fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 27590fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 27600a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, currentBlock); 27610fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 27620a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TopBlock = currentBlock; 27630fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2764e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2765e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2766e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2767e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? currentBlock : 0); 27680fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2769e71f3d587844110d836c82250830b27b1651afdbTed Kremenek LastBlock = currentBlock; 27700fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 27710fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 27720fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 277329ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 27740fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 27750fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 27761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27779c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CaseBlock = Block; 27784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 27794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 27806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 27826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 27834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 27844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2785d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 27864e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 27876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 27896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 27904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2791e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2792e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2793e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2794e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? CaseBlock : 0); 27956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2796d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2797d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 27986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27990fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 28000a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, CaseBlock); 28010fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 280236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 28030fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 28040fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 28050fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 28066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28070fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2808d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 28096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28109c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) { 28114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 28124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 28131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2814eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 28154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 28164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 28174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 28186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 28206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2821411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 28221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2823d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 28244e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2825eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 28266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 28276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 28286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 28296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 28306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 28316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2832eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2833eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 28346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2835eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2836eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 28376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2839295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2840d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 28415d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 28425d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 28435d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 28449c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TrySuccessor = NULL; 28455d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28465d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2847d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 28485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 28495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 28505d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 28515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2852a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 28535d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2855f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 28565d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2857f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 28585d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2859a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 28605d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 28615d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 28625d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 28635d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2864a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2865a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2866a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 28675d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 28685d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 28695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 28705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 28715d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 28725d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 28730a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, CatchBlock); 28745d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2875a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2876a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 28770a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2878a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 28790a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2880a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 28815d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 28835d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 28845d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2885f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2886f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock, NewTryTerminatedBlock); 2887f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek cfg->addTryDispatchBlock(TryTerminatedBlock); 2888f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 28896db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 28905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 28918f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek return addStmt(Terminator->getTryBlock()); 28925d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 28935d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28949c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { 28955d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 28965d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 28975d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28980e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 28990e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 29000e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 29010e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 29020e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 29030e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 29049c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = CS->getExceptionDecl()) { 29050e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 29060e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 29070e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 29080e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 29090e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 29105d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 29115d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 29125d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29139c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CatchBlock = Block; 29145d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 29155d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 2916337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2917337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // CXXCatchStmt is more than just a label. They have semantic meaning 2918337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // as well, as they implicitly "initialize" the catch variable. Add 2919337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // it to the CFG as a CFGElement so that the control-flow of these 2920337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // semantics gets captured. 2921337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek appendStmt(CatchBlock, CS); 2922337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2923337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Also add the CXXCatchStmt as a label, to mirror handling of regular 2924337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // labels. 29255d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 29265d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2927337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Bail out if the CFG is bad. 2928d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 29295d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 29305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29315d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 29325d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 29335d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29345d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 29355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 29365d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29379c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { 2938ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // C++0x for-range statements are specified as [stmt.ranged]: 2939ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // 2940ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // { 2941ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // auto && __range = range-init; 2942ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for ( auto __begin = begin-expr, 2943ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __end = end-expr; 2944ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __begin != __end; 2945ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // ++__begin ) { 2946ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for-range-declaration = *__begin; 2947ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // statement 2948ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2949ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2950ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2951ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save local scope position before the addition of the implicit variables. 2952ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 2953ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2954ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Create local scopes and destructors for range, begin and end variables. 2955ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *Range = S->getRangeStmt()) 2956ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(Range); 2957ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *BeginEnd = S->getBeginEndStmt()) 2958ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(BeginEnd); 2959ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S); 2960ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2961ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LocalScope::const_iterator ContinueScopePos = ScopePos; 2962ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2963ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // "for" is a control-flow statement. Thus we stop processing the current 2964ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // block. 29659c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 2966ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Block) { 2967ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2968ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2969ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Block; 2970ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } else 2971ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Succ; 2972ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2973ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current value for the break targets. 2974ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // All breaks should go to the code following the loop. 2975ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2976ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 2977ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2978ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The block for the __begin != __end expression. 29799c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConditionBlock = createBlock(false); 2980ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ConditionBlock->setTerminator(S); 2981ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2982ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now add the actual condition to the condition block. 2983ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Expr *C = S->getCond()) { 2984ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = ConditionBlock; 2985ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *BeginConditionBlock = addStmt(C); 2986ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2987ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2988ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(BeginConditionBlock == ConditionBlock && 2989ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith "condition block in for-range was unexpectedly complex"); 2990ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith (void)BeginConditionBlock; 2991ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2992ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2993ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The condition block is the implicit successor for the loop body as well as 2994ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // any code above the loop. 2995ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = ConditionBlock; 2996ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2997ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // See if this is a known constant. 2998ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith TryResult KnownVal(true); 2999ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3000ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (S->getCond()) 3001ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith KnownVal = tryEvaluateBool(S->getCond()); 3002ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3003ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now create the loop body. 3004ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith { 3005ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(S->getBody()); 3006ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3007ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current values for Block, Succ, and continue targets. 3008ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 3009ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 3010ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3011ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Generate increment code in its own basic block. This is the target of 3012ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // continue statements. 3013ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 3014ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = addStmt(S->getInc()); 3015ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 3016ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3017ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The starting block for the loop increment is the block that should 3018ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // represent the 'loop target' for looping back to the start of the loop. 3019ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget.block->setLoopTarget(S); 3020ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3021ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Finish up the increment block and prepare to start the loop body. 3022ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(Block); 3023ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3024ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 3025ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 3026ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3027ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3028ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add implicit scope and dtors for loop variable. 3029ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeAndDtors(S->getLoopVarStmt()); 3030ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3031ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Populate a new block to contain the loop body and loop variable. 30328f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek addStmt(S->getBody()); 3033ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3034ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 30358f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt()); 3036ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3037ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 3038ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3039ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // This new body block is a successor to our condition block. 30408f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : LoopVarStmtBlock); 3041ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 3042ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3043ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Link up the condition block with the code that follows the loop (the 3044ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // false branch). 3045ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor); 3046ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3047ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add the initialization statements. 3048ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = createBlock(); 3049b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith addStmt(S->getBeginEndStmt()); 3050b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith return addStmt(S->getRangeStmt()); 3051ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith} 3052ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 30534765fa05b5652fcc4356371c2f481d0ea9a1b007John McCallCFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, 30548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc) { 30555a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors) { 30568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If adding implicit destructors visit the full expression for adding 30578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // destructors of temporaries. 30588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(E->getSubExpr()); 30598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Full expression has to be added as CFGStmt so it will be sequenced 30618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before destructors of it's temporaries. 306294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(true); 30638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(E->getSubExpr(), asc); 30658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 30668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3067a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 3068a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 30693179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3070a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3071247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3072a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 3073a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 307494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 3075a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3076a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 3077a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3078a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 307981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, 308081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 308181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 308297a72c35a62304c3781aa280e28cb97a59afd585Zhongxing Xu appendStmt(Block, C); 308394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 308481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 308581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 308681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 3087a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 3088a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 30893179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3090a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3091247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3092a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 309394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 3094a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3095a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 3096a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3097a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 309881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 309981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 310081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 3101247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 310281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 310381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 310481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 3105a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, 3106a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 31073179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3108a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3109247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3110a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3111892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(E->getSubExpr(), AddStmtChoice()); 3112a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3113a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 31149c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) { 31156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 31169c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *IBlock = cfg->getIndirectGotoBlock(); 31176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 311819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 311919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 312019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 312119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 31226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 312319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 312419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 3125d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 31264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 31274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 312819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 312919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 31300a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, IBlock); 313119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 313219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 313319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 31348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) { 31355a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors); 31365a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose 31378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskitryAgain: 31388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!E) { 31398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski badCFG = true; 31408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 31418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski switch (E->getStmtClass()) { 31438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski default: 31448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitChildrenForTemporaryDtors(E); 31458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::BinaryOperatorClass: 31478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E)); 31488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXBindTemporaryExprClass: 31508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXBindTemporaryExprForTemporaryDtors( 31518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<CXXBindTemporaryExpr>(E), BindToTemporary); 31528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 315356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 31548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ConditionalOperatorClass: 31558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitConditionalOperatorForTemporaryDtors( 315656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall cast<AbstractConditionalOperator>(E), BindToTemporary); 31578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ImplicitCastExprClass: 31598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For implicit cast we want BindToTemporary to be passed further. 31608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<CastExpr>(E)->getSubExpr(); 31618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 31628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ParenExprClass: 31648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<ParenExpr>(E)->getSubExpr(); 31658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 316603e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor 316703e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor case Stmt::MaterializeTemporaryExprClass: 316803e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(); 316903e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor goto tryAgain; 31708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 31728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { 31748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // When visiting children for destructors we want to visit them in reverse 31755846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // order that they will appear in the CFG. Because the CFG is built 31765846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // bottom-up, this means we visit them in their natural order, which 31775846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // reverses them in the CFG. 31788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = Block; 31795846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek for (Stmt::child_range I = E->children(); I; ++I) { 31805846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (Stmt *Child = *I) 31815846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (CFGBlock *R = VisitForTemporaryDtors(Child)) 31825846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek B = R; 31838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 31858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 31868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { 31888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->isLogicalOp()) { 31898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors for temporaries in LHS expression should be called after 31908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // those for RHS expression. Even if this will unnecessarily create a block, 31918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // this block will be used at least by the full expression. 31928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 31938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); 31948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 31958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 31968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 31988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 31998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 32008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (RHSBlock) { 32028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 32048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If RHS expression did produce destructors we need to connect created 32068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // blocks to CFG in same manner as for binary operator itself. 32078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = createBlock(false); 32088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock->setTerminator(CFGTerminator(E, true)); 32098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For binary operator LHS block is before RHS in list of predecessors 32118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // of ConfluenceBlock. 32128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), 32138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConfluenceBlock->pred_end()); 32148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 32160a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(E->getLHS()); 32178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) 32188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski KnownVal.negate(); 32198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Link LHSBlock with RHSBlock exactly the same way as for binary operator 32218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // itself. 32228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getOpcode() == BO_LOr) { 32230a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 32240a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 32258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 32268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert (E->getOpcode() == BO_LAnd); 32270a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 32280a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 32298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = LHSBlock; 32328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock; 32338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 32368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return ConfluenceBlock; 32378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 323936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (E->isAssignmentOp()) { 32408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For assignment operator (=) LHS expression is visited 32418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before RHS expression. For destructors visit them in reverse order. 32428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 32438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 32448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock ? LHSBlock : RHSBlock; 32458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For any other binary operator RHS expression is visited before 32488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // LHS expression (order of children). For destructors visit them in reverse 32498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. 32508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 32518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 32528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return RHSBlock ? RHSBlock : LHSBlock; 32538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 32548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( 32568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *E, bool BindToTemporary) { 32578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for temporaries in subexpression. 32588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr()); 3259249c9458e2cc5b671634baefe8517d7598883a20Zhongxing Xu if (!BindToTemporary) { 32608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If lifetime of temporary is not prolonged (by assigning to constant 32618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // reference) add destructor for it. 3262c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 3263c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If the destructor is marked as a no-return destructor, we need to create 3264c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // a new block for the destructor which does not have as a successor 3265c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far. Control won't flow out of this block. 3266c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor(); 3267cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (Dtor->isNoReturn()) 3268dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 3269dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 3270c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 3271c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 32728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendTemporaryDtor(Block, E); 32738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = Block; 32748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 32768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 32778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( 327956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AbstractConditionalOperator *E, bool BindToTemporary) { 32808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for condition expression. Even if this will 32818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // unnecessarily create a block, this block will be used at least by the full 32828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // expression. 32838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 32848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); 32858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 328756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (BinaryConditionalOperator *BCO 328856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall = dyn_cast<BinaryConditionalOperator>(E)) { 328956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); 32908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 32928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 329456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall // Try to add block with destructors for LHS expression. 329556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *LHSBlock = NULL; 329656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Succ = ConfluenceBlock; 329756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Block = NULL; 329856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); 329956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (badCFG) 330056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return NULL; 330156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 33028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for RHS expression; 33038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 33048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 330556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), 330656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall BindToTemporary); 33078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 33088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 33098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock && !LHSBlock) { 33118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If neither LHS nor RHS expression had temporaries to destroy don't create 33128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // more blocks. 33138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 33148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 33158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 33168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = createBlock(false); 33188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block->setTerminator(CFGTerminator(E, true)); 33198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 33210a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(E->getCond()); 33228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (LHSBlock) { 33240a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 33258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (KnownVal.isFalse()) { 33260a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, NULL); 33278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 33280a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, ConfluenceBlock); 33298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); 33308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 33318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock) 33338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski RHSBlock = ConfluenceBlock; 33340a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 33358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 33378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 33388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3339befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 3340026473c2175424a039f51ca8949937268721b965Ted Kremenek 33416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 33426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 33436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 33449c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFG::createBlock() { 3345026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 3346026473c2175424a039f51ca8949937268721b965Ted Kremenek 3347026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 3348ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 334902f34c5003b2c5067675f89ffce0a84c28faf722Anna Zaks new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this); 3350ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 3351026473c2175424a039f51ca8949937268721b965Ted Kremenek 3352026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 3353ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 3354ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 3355026473c2175424a039f51ca8949937268721b965Ted Kremenek 3356026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 3357ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 3358026473c2175424a039f51ca8949937268721b965Ted Kremenek} 3359026473c2175424a039f51ca8949937268721b965Ted Kremenek 3360026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 3361026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 33629c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFG::buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, 3363b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const BuildOptions &BO) { 3364b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFGBuilder Builder(C, BO); 3365b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek return Builder.buildCFG(D, Statement); 3366fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 3367fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 3368c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekconst CXXDestructorDecl * 3369c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed KremenekCFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { 3370c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek switch (getKind()) { 3371c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Statement: 3372c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Initializer: 3373c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek llvm_unreachable("getDestructorDecl should only be used with " 3374c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek "ImplicitDtors"); 3375c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::AutomaticObjectDtor: { 3376fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl(); 3377c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = var->getType(); 3378697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek ty = ty.getNonReferenceType(); 33794cf225382a8b061dce41733c962d62b6db9721f8Ted Kremenek while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { 3380c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek ty = arrayType->getElementType(); 3381c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek } 3382c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const RecordType *recordType = ty->getAs<RecordType>(); 3383c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXRecordDecl *classDecl = 3384697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek cast<CXXRecordDecl>(recordType->getDecl()); 3385c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return classDecl->getDestructor(); 3386c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3387c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::TemporaryDtor: { 3388c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXBindTemporaryExpr *bindExpr = 3389fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie castAs<CFGTemporaryDtor>().getBindTemporaryExpr(); 3390c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXTemporary *temp = bindExpr->getTemporary(); 3391c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return temp->getDestructor(); 3392c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3393c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::BaseDtor: 3394c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::MemberDtor: 3395c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3396c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // Not yet supported. 3397c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return 0; 3398c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3399697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek llvm_unreachable("getKind() returned bogus value"); 3400c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek} 3401c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3402c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekbool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { 3403cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (const CXXDestructorDecl *DD = getDestructorDecl(astContext)) 3404cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith return DD->isNoReturn(); 3405c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return false; 34063c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek} 34073c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 340863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 3409ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 3410ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3411ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3412ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 3413be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 3414ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 34156e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (To && F.IgnoreDefaultsWithCoveredEnums) { 3416ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 3417ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 3418ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 34196e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { 3420ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 34216e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek const Stmt *L = To->getLabel(); 34226e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 34236e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek return true; 3424ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3425ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3426ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3427ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3428ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 3429ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 3430ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3431ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 34327dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 34337dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 34347dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 343542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 34362bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 3437ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 34383c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 34393c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 344042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 34411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 34420a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek signed currentBlock; 344366c486f275531df6362b3511fc3af6563561801bTed Kremenek unsigned currStmt; 3444e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 344542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 34461c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 3447e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 344866c486f275531df6362b3511fc3af6563561801bTed Kremenek : currentBlock(0), currStmt(0), LangOpts(LO) 34493c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek { 345042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 345142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 3452ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 34531cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 3454b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> SE = BI->getAs<CFGStmt>()) { 3455b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *stmt= SE->getStmt(); 34561cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 34573c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek StmtMap[stmt] = P; 34583c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 34593c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek switch (stmt->getStmtClass()) { 34603c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::DeclStmtClass: 34613c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P; 34623c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34633c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::IfStmtClass: { 34643c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable(); 34653c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 34663c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34673c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34693c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::ForStmtClass: { 34703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable(); 34713c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 34723c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34733c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34743c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::WhileStmtClass: { 34763c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 34773c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<WhileStmt>(stmt)->getConditionVariable(); 34783c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 34793c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34803c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34813c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34823c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::SwitchStmtClass: { 34833c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 34843c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<SwitchStmt>(stmt)->getConditionVariable(); 34853c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 34863c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34873c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34883c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34893c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::CXXCatchStmtClass: { 34903c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 34913c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<CXXCatchStmt>(stmt)->getExceptionDecl(); 34923c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 34933c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34943c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34953c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34963c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek default: 34973c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34981cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 34991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 350042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 3501b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 3502fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 35033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 35046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 350542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 35066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3507e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 35080a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setBlockID(signed i) { currentBlock = i; } 350966c486f275531df6362b3511fc3af6563561801bTed Kremenek void setStmtID(unsigned i) { currStmt = i; } 35106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35119c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual bool handledStmt(Stmt *S, raw_ostream &OS) { 35121cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 3513fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 351442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 351542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 35166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 351866c486f275531df6362b3511fc3af6563561801bTed Kremenek && I->second.second == currStmt) { 351942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 35203fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 35216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35223fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 35231c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 352442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 35251cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35269c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool handleDecl(const Decl *D, raw_ostream &OS) { 35271cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 35281cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35291cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 35301cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 35311cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35320a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 353366c486f275531df6362b3511fc3af6563561801bTed Kremenek && I->second.second == currStmt) { 35341cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 35351cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 35361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35371cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 35381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 35391cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 354042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 3541e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3542e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 3543e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 3544e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 3545ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 35466fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 35476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35489c378f705405d37f49795d5e915989de774fe11fTed Kremenek raw_ostream &OS; 354942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 3550d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 3551d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 35529c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper, 3553e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 3554d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 35556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35569c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIfStmt(IfStmt *I) { 3557d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 3558d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 3559d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 35606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3561d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 35629c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitStmt(Stmt *Terminator) { 35636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 35646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 35656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3566fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek void VisitDeclStmt(DeclStmt *DS) { 3567fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 3568fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek OS << "static init " << VD->getName(); 3569fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek } 3570fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek 35719c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitForStmt(ForStmt *F) { 3572d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 35733fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 35743fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3575535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 35769c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = F->getCond()) 35773fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3578535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 35793fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 35803fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3581a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 3582d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 35836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35849c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitWhileStmt(WhileStmt *W) { 3585d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 35869c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = W->getCond()) 35873fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3588d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 35896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35909c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitDoStmt(DoStmt *D) { 3591d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 35929c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) 35933fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 35949da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 35956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35969c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitSwitchStmt(SwitchStmt *Terminator) { 35979da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 3598d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 35999da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 36006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36019c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitCXXTryStmt(CXXTryStmt *CS) { 36025d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 36035d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 36045d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 360556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { 3606d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 36076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 3608805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36109c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitChooseExpr(ChooseExpr *C) { 3611aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 3612d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 3613a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 3614aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 36156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36169c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt *I) { 36171c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 3618d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 36191c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 36206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3621805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 3622805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 3623805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 3624805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3625805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3627d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 36286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3629805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 36302de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 3631a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 3632805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 36332de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 3634a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 3635805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3636805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 3637b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid logical operator."); 36386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3639805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36419c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitExpr(Expr *E) { 3642d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 36436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3644d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3645e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3646e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 36475f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper, 3648079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 3649b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) { 3650b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *S = CS->getStmt(); 36511cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36521cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 36531cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36541cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 3655f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) { 3656f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const CompoundStmt *Sub = SE->getSubStmt(); 36571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36587502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall if (Sub->children()) { 36591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 36601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 36611cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 36621cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 36631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 36641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 36651cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 3666f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 36671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 36681cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 36691cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 36701cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 36711cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 36721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 36731c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 36741c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 36751cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 36766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36771cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 367836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (OperatorCall)"; 3679893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 3680893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (isa<CXXBindTemporaryExpr>(S)) { 368136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (BindTemporary)"; 36826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 36833b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) { 36843b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek OS << " (CXXConstructExpr, " << CCE->getType().getAsString() << ")"; 36853b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek } 3686893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) { 3687893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek OS << " (" << CE->getStmtClassName() << ", " 3688893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << CE->getCastKindName() 3689893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ", " << CE->getType().getAsString() 3690893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ")"; 3691893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 36926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36931cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 36941cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 36951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 36964e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 3697b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) { 3698b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const CXXCtorInitializer *I = IE->getInitializer(); 36991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 37001cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 370100eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet else OS << I->getAnyMember()->getName(); 37026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 37049c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *IE = I->getInit()) 37051cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 37061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 37071cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37081cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 37091cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 37101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 37111cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3712b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGAutomaticObjDtor> DE = 3713b07805485c603be3d8011f72611465324c9e664bDavid Blaikie E.getAs<CFGAutomaticObjDtor>()) { 3714b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const VarDecl *VD = DE->getVarDecl(); 37151cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 37161cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3717b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski const Type* T = VD->getType().getTypePtr(); 37181cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 37191cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 372056df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith T = T->getBaseElementTypeUnsafe(); 37211cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37221cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 37231cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 37247c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 3725b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) { 3726b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); 37277c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 37284e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 37297c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 3730b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) { 3731b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const FieldDecl *FD = ME->getFieldDecl(); 373256df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith const Type *T = FD->getType()->getBaseElementTypeUnsafe(); 37337c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 37348c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; 37354e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 37368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3737b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) { 3738b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); 37398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()"; 37408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << " (Temporary object destructor)\n"; 37411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 374281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 37436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37449c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void print_block(raw_ostream &OS, const CFG* cfg, 37459c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock &B, 3746682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek StmtPrinterHelper* Helper, bool print_edges, 3747682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) { 37486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3749682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (Helper) 3750682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek Helper->setBlockID(B.getBlockID()); 37516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37527dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 3753682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3754682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::YELLOW, true); 3755682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3756682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n [B" << B.getBlockID(); 37576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 375842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 3759682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (ENTRY)]\n"; 376042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 3761682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (EXIT)]\n"; 376242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 3763682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (INDIRECT GOTO DISPATCH)]\n"; 376442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 3765682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "]\n"; 3766682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3767682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3768682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 37696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37709cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 37719c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) { 377242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 377342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3774682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 37756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37769c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (LabelStmt *L = dyn_cast<LabelStmt>(Label)) 37779cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 37789c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) { 37799cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 3780e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 3781e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 37829cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 37839cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 3784e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 3785e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 37869cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 3787079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 37889cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 3789079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 37905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 3791a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 3792a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 3793a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 3794a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 3795a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 37965d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 37975d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 37985d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 3799b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid label statement in CFGBlock."); 38006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38019cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 38029cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 38036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3804fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 3805fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 38066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 380742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 380842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 38096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38109cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 381142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3812682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 38136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3814a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 38156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 381642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 381742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 38186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3819682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_elem(OS, Helper, *I); 3820fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 38216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38229cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 382342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 3824682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3825682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::GREEN); 38266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3827682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " T: "; 38286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 382942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 38306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3831507d106c758e745d3f71f44639092eb97d356525Ted Kremenek PrintingPolicy PP(Helper ? Helper->getLangOpts() : LangOptions()); 3832507d106c758e745d3f71f44639092eb97d356525Ted Kremenek CFGBlockTerminatorPrint TPrinter(OS, Helper, PP); 38334ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt())); 3834a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 3835682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3836682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3837682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3838fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 38396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38409cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 38419cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 3842682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.pred_empty()) { 3843682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::BLUE; 3844682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3845682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3846682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Preds " ; 3847682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3848682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3849682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.pred_size() << "):"; 3850682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3851682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3852682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3853682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3854682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3855682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 3856682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 385742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3858dac62528c1a66db867e21cfa7cfc439d557d6f0cWill Dietz if (i % 10 == 8) 3859682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 38606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3861682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3862682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3863682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3864682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3865682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 38666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3867682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 38689cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 38696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38709cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 3871682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.succ_empty()) { 3872682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::MAGENTA; 3873682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3874682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3875682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Succs "; 3876682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3877682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3878682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.succ_size() << "):"; 3879682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3880682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3881682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3882682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3883682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3884682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 3885682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 3886682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3887dac62528c1a66db867e21cfa7cfc439d557d6f0cWill Dietz if (i % 10 == 8) 3888682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 3889682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3890682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (*I) 3891682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3892682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek else 3893682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " NULL"; 3894682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3895682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3896682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3897682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3898682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3899fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 3900fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 39016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 390242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 390342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 390442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 3905682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::dump(const LangOptions &LO, bool ShowColors) const { 3906682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), LO, ShowColors); 3907682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek} 390842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 390942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 3910682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const { 3911e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 39126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 391342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 3914682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getEntry(), &Helper, true, ShowColors); 39156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 391642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 391742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 391842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 3919ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 392042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 39216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3922682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, **I, &Helper, true, ShowColors); 392342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 39246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 392542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 3926682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getExit(), &Helper, true, ShowColors); 3927682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3928d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 39296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 393042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 393142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 3932682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO, 3933682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) const { 3934682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), cfg, LO, ShowColors); 3935e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 393642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 393742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 393842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 39399c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBlock::print(raw_ostream &OS, const CFG* cfg, 3940682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const LangOptions &LO, bool ShowColors) const { 3941e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 3942682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, cfg, *this, &Helper, true, ShowColors); 3943682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3944026473c2175424a039f51ca8949937268721b965Ted Kremenek} 39457dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3946a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 39475f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid CFGBlock::printTerminator(raw_ostream &OS, 39486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 3949e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 39504ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt())); 3951a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 3952a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 39539c378f705405d37f49795d5e915989de774fe11fTed KremenekStmt *CFGBlock::getTerminatorCondition() { 39544ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski Stmt *Terminator = this->Terminator; 3955411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 3956411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 39576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 39589c378f705405d37f49795d5e915989de774fe11fTed Kremenek Expr *E = NULL; 39596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3960411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 3961411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 3962411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 396449a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose case Stmt::CXXForRangeStmtClass: 396549a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose E = cast<CXXForRangeStmt>(Terminator)->getCond(); 396649a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose break; 396749a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose 3968411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 3969411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 3970411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3972411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 3973411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 3974411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3976411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 3977411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 3978411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3980411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 3981411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 3982411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3984411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 3985411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 3986411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3988411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 3989411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 3990411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3992411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 3993411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 3994411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 399656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 399756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall E = cast<BinaryConditionalOperator>(Terminator)->getCond(); 399856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall break; 399956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 4000411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 4001411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 4002411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4004411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 4005411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 4006390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 40076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4008390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 40096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 4010411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 40116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4012411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 4013411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 4014411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 40157dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 40167dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 40177dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 40187dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 401942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 402042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 40216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 402242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 402342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 4024e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 402542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 4026e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 402742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 402842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 402942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 403042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 403142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 403242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 40337dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 40347dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 40357dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 4036006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 4037006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 4038006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 40399c378f705405d37f49795d5e915989de774fe11fTed Kremenek static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) { 40407dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 4041bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 4042a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 4043a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 4044682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(Out,Graph, *Node, GraphHelper, false, false); 4045a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 40467dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 40477dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 40487dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 40497dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 40507dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 40517dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 40527dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 40537dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 40547dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 40556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 40567dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 4057bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 4058bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 4059bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 40607dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 40617dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 40627dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 4063