CFG.cpp revision 6f42b62b6194f53bcbc349f5d17388e1936535d7
1fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===// 2fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 3fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// The LLVM Compiler Infrastructure 4fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 7fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 8fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 9fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 10fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// This file defines the CFG and CFGBuilder classes for representing and 11fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// building Control-Flow Graphs (CFGs) from ASTs. 12fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 13fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 14fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 15bd0487825751230a4396952b770349d2beac60b3Ted Kremenek#include "clang/Analysis/Support/SaveAndRestore.h" 16e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h" 17b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump#include "clang/AST/DeclCXX.h" 18c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek#include "clang/AST/StmtVisitor.h" 1942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#include "clang/AST/PrettyPrinter.h" 20c56c004e0b8030e8ca8614e7febe581221938b75Ted Kremenek#include "clang/AST/CharUnits.h" 217dba8607e59096014b7139ff20ef00870041d518Ted Kremenek#include "llvm/Support/GraphWriter.h" 226cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Allocator.h" 236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Format.h" 246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/DenseMap.h" 256cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/SmallPtrSet.h" 260ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek#include "llvm/ADT/OwningPtr.h" 2783c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 28fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenekusing namespace clang; 29fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 30fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremeneknamespace { 31fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 329c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic SourceLocation GetEndLoc(Decl *D) { 339c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(D)) 349c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *Ex = VD->getInit()) 35c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek return Ex->getSourceRange().getEnd(); 366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return D->getLocation(); 37c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek} 38ad5a894df1841698c824381b414630799adc26caTed Kremenek 393179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenekclass CFGBuilder; 403179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 4194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// The CFG builder uses a recursive algorithm to build the CFG. When 4294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// we process an expression, sometimes we know that we must add the 4394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// subexpressions as block-level expressions. For example: 4494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// exp1 || exp2 4694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// When processing the '||' expression, we know that exp1 and exp2 4894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// need to be added as block-level expressions, even though they 4994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// might not normally need to be. AddStmtChoice records this 5094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then 5194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// the builder has an option not to add a subexpression as a 5294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// block-level expression. 5394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 54852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekclass AddStmtChoice { 55852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekpublic: 56892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; 575ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 5894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} 595ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 603179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek bool alwaysAdd(CFGBuilder &builder, 613179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek const Stmt *stmt) const; 6294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 6394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// Return a copy of this object, except with the 'always-add' bit 6494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// set as specified. 6594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { 663179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); 6794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan } 6894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 69852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekprivate: 7094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan Kind kind; 71852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek}; 726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 73f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope - Node in tree of local scopes created for C++ implicit 74f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// destructor calls generation. It contains list of automatic variables 75f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// declared in the scope and link to position in previous scope this scope 76f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// began in. 77f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 78f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// The process of creating local scopes is as follows: 79f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null), 80f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Before processing statements in scope (e.g. CompoundStmt) create 81f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope object using CFGBuilder::ScopePos as link to previous scope 82f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// and set CFGBuilder::ScopePos to the end of new scope, 8335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points 84f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// at this VarDecl, 85f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every normal (without jump) end of scope add to CFGBlock destructors 86f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// for objects in the current scope, 87f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every jump add to CFGBlock destructors for objects 88f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// between CFGBuilder::ScopePos and local scope position saved for jump 89f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// target. Thanks to C++ restrictions on goto jumps we can be sure that 90f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// jump target position will be on the path to root from CFGBuilder::ScopePos 91f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// (adding any variable that doesn't need constructor to be called to 92f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope can break this assumption), 93f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 94f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiclass LocalScope { 95f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 96fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek typedef BumpVector<VarDecl*> AutomaticVarsTy; 97f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 98f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// const_iterator - Iterates local scope backwards and jumps to previous 9935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski /// scope on reaching the beginning of currently iterated scope. 100f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski class const_iterator { 101f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const LocalScope* Scope; 102f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// VarIter is guaranteed to be greater then 0 for every valid iterator. 104f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Invalid iterator (with null Scope) has VarIter equal to 0. 105f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski unsigned VarIter; 106f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 107f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski public: 108f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create invalid iterator. Dereferencing invalid iterator is not allowed. 109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Incrementing invalid iterator is allowed and will result in invalid 110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// iterator. 111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator() 112f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(NULL), VarIter(0) {} 113f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create valid iterator. In case when S.Prev is an invalid iterator and 115f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// I is equal to 0, this will create invalid iterator. 116f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator(const LocalScope& S, unsigned I) 117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(&S), VarIter(I) { 118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Iterator to "end" of scope is not allowed. Handle it by going up 119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // in scopes tree possibly up to invalid iterator in the root. 120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0 && Scope) 121f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1249c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *const* operator->() const { 125f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (Scope && "Dereferencing invalid iterator is not allowed"); 126f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 127f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return &Scope->Vars[VarIter - 1]; 128f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1299c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *operator*() const { 130f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this->operator->(); 131f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 132f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1339c378f705405d37f49795d5e915989de774fe11fTed Kremenek const_iterator &operator++() { 134f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (!Scope) 135f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 136f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 137f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 138f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski --VarIter; 139f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0) 140f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 141f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 142f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 14335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator operator++(int) { 14435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator P = *this; 14535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski ++*this; 14635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return P; 14735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 148f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1499c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator==(const const_iterator &rhs) const { 150f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return Scope == rhs.Scope && VarIter == rhs.VarIter; 151f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1529c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator!=(const const_iterator &rhs) const { 153f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return !(*this == rhs); 154f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 15535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 15635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski operator bool() const { 15735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return *this != const_iterator(); 15835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 15935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 16035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int distance(const_iterator L); 161f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski }; 162f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 163f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski friend class const_iterator; 164f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 165f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiprivate: 166fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx; 167fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek 168f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Automatic variables in order of declaration. 169f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AutomaticVarsTy Vars; 170f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Iterator to variable in previous scope that was declared just before 171f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// begin of this scope. 172f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator Prev; 173f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 174f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 175f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Constructs empty scope linked to previous scope in specified place. 176fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek LocalScope(BumpVectorContext &ctx, const_iterator P) 177fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek : ctx(ctx), Vars(ctx, 4), Prev(P) {} 178f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 179f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Begin of scope in direction of CFG building (backwards). 180f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator begin() const { return const_iterator(*this, Vars.size()); } 18135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 1829c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addVar(VarDecl *VD) { 183fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Vars.push_back(VD, ctx); 18435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 185f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 186f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 18735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// distance - Calculates distance from this to L. L must be reachable from this 18835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. 18935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// number of scopes between this and L. 19035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderskiint LocalScope::const_iterator::distance(LocalScope::const_iterator L) { 19135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int D = 0; 19235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator F = *this; 19335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski while (F.Scope != L.Scope) { 1945290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek assert (F != const_iterator() 1955290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek && "L iterator is not reachable from F iterator."); 19635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter; 19735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski F = F.Scope->Prev; 19835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 19935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter - L.VarIter; 20035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return D; 20135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski} 20235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 20335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// BlockScopePosPair - Structure for specifying position in CFG during its 20435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// build process. It consists of CFGBlock that specifies position in CFG graph 20535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// and LocalScope::const_iterator that specifies position in LocalScope graph. 206f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskistruct BlockScopePosPair { 2079ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BlockScopePosPair() : block(0) {} 2089c378f705405d37f49795d5e915989de774fe11fTed Kremenek BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos) 2099ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek : block(b), scopePosition(scopePos) {} 210f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2119ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek CFGBlock *block; 2129ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek LocalScope::const_iterator scopePosition; 213f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 214f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 215e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// TryResult - a class representing a variant over the values 216e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, 217e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// and is used by the CFGBuilder to decide if a branch condition 218e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// can be decided up front during CFG construction. 219e71f3d587844110d836c82250830b27b1651afdbTed Kremenekclass TryResult { 220e71f3d587844110d836c82250830b27b1651afdbTed Kremenek int X; 221e71f3d587844110d836c82250830b27b1651afdbTed Kremenekpublic: 222e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 223e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult() : X(-1) {} 224e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 225e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isTrue() const { return X == 1; } 226e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isFalse() const { return X == 0; } 227e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isKnown() const { return X >= 0; } 228e71f3d587844110d836c82250830b27b1651afdbTed Kremenek void negate() { 229e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(isKnown()); 230e71f3d587844110d836c82250830b27b1651afdbTed Kremenek X ^= 0x1; 231e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 232e71f3d587844110d836c82250830b27b1651afdbTed Kremenek}; 233e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 234a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 235fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 236fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 237fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 238fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 239fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 240fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 241fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 242fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 2436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 2446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 2456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 2466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 247c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 248ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 249f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpTarget; 250f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpSource; 251f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 252e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 2536f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CFG> cfg; 254ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 2559c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Block; 2569c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Succ; 257f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget ContinueJumpTarget; 258f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget BreakJumpTarget; 2599c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchTerminatedBlock; 2609c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *DefaultCaseBlock; 2619c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TryTerminatedBlock; 262e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 263f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Current position in local scope. 264f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 265f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 266f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // LabelMap records the mapping from Label expressions to their jump targets. 267ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy; 2680cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 2696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 2716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 272f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef std::vector<JumpSource> BackpatchBlocksTy; 2730cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 2746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 276ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy; 27719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 2786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27949b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu bool badCFG; 280b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &BuildOpts; 281e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 282e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // State to track for building switch statements. 283e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool switchExclusivelyCovered; 2840498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult *switchCond; 2850d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 2860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; 287a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek const Stmt *lastLookup; 28849b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu 2896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 290b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek explicit CFGBuilder(ASTContext *astContext, 291b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &buildOpts) 292b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek : Context(astContext), cfg(new CFG()), // crew a new CFG 293b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek Block(NULL), Succ(NULL), 294b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 295b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), 2960d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek switchExclusivelyCovered(false), switchCond(0), 297a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry(0), lastLookup(0) {} 2986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 299d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 300b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement); 3016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3020d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool alwaysAdd(const Stmt *stmt); 3030d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 3054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 306852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 307852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 3089c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitBlockExpr(BlockExpr *E, AddStmtChoice asc); 3094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 3107ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 3114765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, 3128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc); 3137ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 3147ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 315ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); 316a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 317a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 31881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); 319a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 320a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 32181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 32281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc); 323852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 3244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 325852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 3263fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 32756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, 32856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AddStmtChoice asc); 3293fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 3304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 3319c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitDeclSubExpr(DeclStmt *DS); 3323fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 3333fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 3343fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 3359c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt *G); 3364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 337a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); 3384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 3394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 340115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 3414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 3424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 3444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 3454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 3469c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitReturnStmt(ReturnStmt *R); 3474b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); 348f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 349f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc); 350852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 3514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 35299cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); 3534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 3544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 355852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 356852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 3579c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitChildren(Stmt *S); 358cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 3598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Visitors to walk an AST and generate destructors of temporaries in 3608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // full expression. 3618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false); 3628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E); 3638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); 3648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, 3658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 36656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock * 36756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E, 36856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool BindToTemporary); 3698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 370274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 3719c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *NYS() { 3724102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 3734102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 3744102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 3756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 3774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 378dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *createNoReturnBlock(); 379d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 380df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 381df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 382852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 383cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt CFGBlock *addInitializer(CXXCtorInitializer *I); 3846a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 3859c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S); 3867c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 387239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 388239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 389239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 390239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 3919c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeForStmt(Stmt *S); 3929c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, LocalScope* Scope = NULL); 3939c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = NULL); 394239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 3959c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeAndDtors(Stmt *S); 396ad5a894df1841698c824381b414630799adc26caTed Kremenek 397239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 398d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek void appendStmt(CFGBlock *B, const Stmt *S) { 39974fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek if (alwaysAdd(S) && cachedEntry) 4000d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry->second = B; 4010d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 402ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose // All block-level expressions should have already been IgnoreParens()ed. 403ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); 404d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); 405ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 406cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { 40782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 40882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 4097c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 4107c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 4117c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4127c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 4137c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 4147c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { 4168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); 4178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 418c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) { 419c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext()); 420c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 421ad5a894df1841698c824381b414630799adc26caTed Kremenek 4229c378f705405d37f49795d5e915989de774fe11fTed Kremenek void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 42353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 42453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 4250a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void addSuccessor(CFGBlock *B, CFGBlock *S) { 426ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 427ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 4281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 429e71f3d587844110d836c82250830b27b1651afdbTed Kremenek /// Try and evaluate an expression to an integer constant. 430e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { 431e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 432e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return false; 433e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return !S->isTypeDependent() && 434f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek !S->isValueDependent() && 43551f4708c00110940ca3f337961915f2ca1668375Richard Smith S->EvaluateAsRValue(outResult, *Context); 436e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 4371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4380a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 43900998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 4400a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult tryEvaluateBool(Expr *S) { 44185df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith bool Result; 44285df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (!BuildOpts.PruneTriviallyFalseEdges || 44385df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith S->isTypeDependent() || S->isValueDependent() || 44485df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith !S->EvaluateAsBooleanCondition(Result, *Context)) 445e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return TryResult(); 44685df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith return Result; 44700998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 448e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 449d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 4506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4510d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekinline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, 4520d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const Stmt *stmt) const { 4530d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return builder.alwaysAdd(stmt) || kind == AlwaysAdd; 4540d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek} 455a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 4560d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekbool CFGBuilder::alwaysAdd(const Stmt *stmt) { 45774fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek bool shouldAdd = BuildOpts.alwaysAdd(stmt); 45874fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek 4590d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!BuildOpts.forcedBlkExprs) 46074fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 461a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 462a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (lastLookup == stmt) { 463a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (cachedEntry) { 464a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry->first == stmt); 465a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek return true; 466a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 46774fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 468a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 4690d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 470a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek lastLookup = stmt; 471a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 472a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // Perform the lookup! 4730d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; 4740d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 475a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (!fb) { 476a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // No need to update 'cachedEntry', since it will always be null. 477a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry == 0); 47874fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 479a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 4800d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 4810d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); 482a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (itr == fb->end()) { 483a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry = 0; 48474fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 485a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 486a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 4870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry = &*itr; 4880d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return true; 4893179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek} 4903179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 491898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 492898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 493f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCallstatic const VariableArrayType *FindVA(const Type *t) { 494f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { 495f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) 496610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 497610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 4986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 499610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 500610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 5016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 502610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 503610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 5046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 5066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 5076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 5086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 5096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 5109c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { 5110ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 5124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 5134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 514d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 5156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 5166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 5176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 51849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 519ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 52049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 5216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5227c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 5237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 5247c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 5257c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 526d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 5271b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 5281b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5291b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 5301b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 5311b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 53282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 533b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 53482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 53582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 53682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 53782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 53882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 53982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 540b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 5416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 54282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 54382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 54482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 5451b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 5461b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 5471b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 5481b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 549c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 5509c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = I->block; 5519c378f705405d37f49795d5e915989de774fe11fTed Kremenek GotoStmt *G = cast<GotoStmt>(B->getTerminator()); 5521b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 5536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5541b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 5551b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 5561b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 557d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 558f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 5599ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, 5609ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek JT.scopePosition); 5619ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, JT.block); 5621b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 5636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5641b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 5659c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (CFGBlock *B = cfg->getIndirectGotoBlock()) 5661b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 5671b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 5681b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5691b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 5701b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 5711b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5721b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 5731b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 5741b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 5751b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5769ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, LI->second.block); 577c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 5786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 580322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 5816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5821b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 583d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 5846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 585d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 586d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 5879c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::createBlock(bool add_successor) { 5889c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = cfg->createBlock(); 5894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 5900a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(B, Succ); 591d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 592d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 5936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 594dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// createNoReturnBlock - Used to create a block is a 'noreturn' point in the 595dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// CFG. It is *not* connected to the current (global) successor, and instead 596dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// directly tied to the exit block in order to be reachable. 597dba3fb5413437dc613734fa4ffac892b11a37d25Chandler CarruthCFGBlock *CFGBuilder::createNoReturnBlock() { 598dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *B = createBlock(false); 59983754162f698a5dafad93fb89be0953651a604d0Chandler Carruth B->setHasNoReturnElement(); 600dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth addSuccessor(B, &cfg->getExit()); 601dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth return B; 602dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth} 603dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 60482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 605cbb67480094b3bcb5b715acd827cbad55e2a204cSean HuntCFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { 60682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 60782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 60882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 6108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 61182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 6138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 6148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Expr *Init = I->getInit(); 6158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 61600eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet if (FieldDecl *FD = I->getAnyMember()) 6178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = FD->getType()->isReferenceType(); 6184765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 61982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 6218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 6224765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 6238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 6248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 62582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 6268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 6278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 6288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendInitializer(Block, I); 6298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 6308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 631892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek if (HasTemporaries) { 6328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 6338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 634892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 635892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek } 636892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(Init); 6378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 6388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 63982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 64082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 64182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6422d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// \brief Retrieve the type of the temporary object whose lifetime was 6432d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// extended by a local reference with the given initializer. 6442d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregorstatic QualType getReferenceInitTemporaryType(ASTContext &Context, 6452d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor const Expr *Init) { 6462d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (true) { 6472d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip parentheses. 6482d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = Init->IgnoreParens(); 6492d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 6502d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through cleanups. 6512d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) { 6522d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = EWC->getSubExpr(); 6532d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 6542d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 6552d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 6562d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through the temporary-materialization expression. 6572d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MaterializeTemporaryExpr *MTE 6582d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor = dyn_cast<MaterializeTemporaryExpr>(Init)) { 6592d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = MTE->GetTemporaryExpr(); 6602d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 6612d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 6622d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 6632d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip derived-to-base and no-op casts. 6642d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const CastExpr *CE = dyn_cast<CastExpr>(Init)) { 6652d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if ((CE->getCastKind() == CK_DerivedToBase || 6662d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_UncheckedDerivedToBase || 6672d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_NoOp) && 6682d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init->getType()->isRecordType()) { 6692d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = CE->getSubExpr(); 6702d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 6712d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 6722d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 6732d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 6742d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip member accesses into rvalues. 6752d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) { 6762d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (!ME->isArrow() && ME->getBase()->isRValue()) { 6772d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = ME->getBase(); 6782d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 6792d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 6802d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 6812d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 6822d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor break; 6832d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 6842d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 6852d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor return Init->getType(); 6862d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor} 6872d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 688239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 689239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 690239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 6916a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 6929c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S) { 693239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 6946a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 6956a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 696239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 6976a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 698239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 699c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // We need to append the destructors in reverse order, but any one of them 700c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // may be a no-return destructor which changes the CFG. As a result, buffer 701c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // this sequence up and replay them in reverse order when appending onto the 702c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // CFGBlock(s). 703c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth SmallVector<VarDecl*, 10> Decls; 704c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.reserve(B.distance(E)); 705c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 706c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.push_back(*I); 707c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 708c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(), 709c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth E = Decls.rend(); 710c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth I != E; ++I) { 711c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If this destructor is marked as a no-return destructor, we need to 712c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // create a new block for the destructor which does not have as a successor 713c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far: control won't flow out of this block. 7142d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor QualType Ty; 7152d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if ((*I)->getType()->isReferenceType()) { 7162d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit()); 7172d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } else { 7182d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Ty = Context->getBaseElementType((*I)->getType()); 7192d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7202d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 721c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); 72223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) 723dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 724dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 725c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 726c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 727c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth appendAutomaticObjDtor(Block, *I, S); 728c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 729239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 730239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 7317c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 7327c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 7337c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 7347c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 7357c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 7367c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 7377c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 7387c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 7397c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 7407c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 7417c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 7427c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 7437c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 7447c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 7457c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 7467c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 7477c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 7487c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 7497c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 7507c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 75123661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!BI->isVirtual()) { 75223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 75323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 75423661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie autoCreateBlock(); 75523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie appendBaseDtor(Block, BI); 75623661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 75723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 7587c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 7597c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 7607c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 7617c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 7627c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 7638c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski // Check for constant size array. Set type to array element type. 7648c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QualType QT = FI->getType(); 7658c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 7668c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (AT->getSize() == 0) 7678c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski continue; 7688c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QT = AT->getElementType(); 7698c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski } 7708c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 7718c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 7727c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 7737c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 7747c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendMemberDtor(Block, *FI); 7757c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 7767c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 7777c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 7787c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 779239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 780239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 781239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 782239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 783fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); 784fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Scope = alloc.Allocate<LocalScope>(); 785fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx(alloc); 786fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek new (Scope) LocalScope(ctx, ScopePos); 787239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 788239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 789239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 790239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 791239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 79202acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 7939c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeForStmt(Stmt *S) { 794239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 79502acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 79602acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 79702acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 798239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 799239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 800ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { 801239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 802239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 803a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth Stmt *SI = (*BI)->stripLabelLikeStatements(); 804ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) 805239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 806239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 80702acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 808239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 809239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 810239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 811239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 812a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements())) 813b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 814239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 815239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 816239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 817239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 8189c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS, 819b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 820239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 821239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 822239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 823239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 824239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 8259c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(*DI)) 826239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 827239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 828239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 829239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 830239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 831239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 832239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 833239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 8349c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, 835b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 836239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 837239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 838239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 839239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 840239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 841239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 842239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 843239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 844239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 845239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 846239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 847239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 848239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 849239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 8502d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (QT.getTypePtr()->isReferenceType()) { 85103e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor if (!VD->extendsLifetimeOfTemporary()) 852239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 8532d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 8542d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor QT = getReferenceInitTemporaryType(*Context, VD->getInit()); 855239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 856239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 857b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check for constant size array. Set type to array element type. 8582d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 859b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (AT->getSize() == 0) 860b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski return Scope; 861b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski QT = AT->getElementType(); 862b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski } 8634e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 864b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 8659c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 86623661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 8674e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 8684e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 8694e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 8704e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 8714e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 872239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 873239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 874239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 875239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 876239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 8779c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeAndDtors(Stmt *S) { 878239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 879239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 880239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 881239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 88202acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 883239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 884239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 885239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 88653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 88753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 88853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 88953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 89053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 891c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// FIXME: This mechanism for adding automatic destructors doesn't handle 892c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// no-return destructors properly. 8939c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 89453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 895c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth BumpVectorContext &C = cfg->getBumpVectorContext(); 896c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth CFGBlock::iterator InsertPos 897c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); 898c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 899c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, 900c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Blk->getTerminator()); 90153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 90253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 9034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 9046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 9056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 9069c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 907f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 908f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 909f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 910f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 911ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 912ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (Expr *E = dyn_cast<Expr>(S)) 913ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose S = E->IgnoreParens(); 914ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 9154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 9164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 917852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 9184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 9194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 920852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 9211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 92256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 92356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); 92456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 9254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 926852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 9271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 929852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBlockExpr(cast<BlockExpr>(S), asc); 9304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 9314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 9324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 9331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 935a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 9361de85338543dd6228eb518185e385d94d377f4cbJohn McCall case Stmt::CXXMemberCallExprClass: 937852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 9381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 9404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 9414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 9424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 943852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 9441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 9464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 9471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 949852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 9501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 9524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 9531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 954021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 955021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 956021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 9574765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall case Stmt::ExprWithCleanupsClass: 9584765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc); 95947e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 960a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXBindTemporaryExprClass: 961a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); 962a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 96381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXConstructExprClass: 96481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); 96581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 966a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXFunctionalCastExprClass: 967a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); 968a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 96981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXTemporaryObjectExprClass: 97081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); 97181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 972021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 973021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 974ad5a894df1841698c824381b414630799adc26caTed Kremenek 975021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 976021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 977ad5a894df1841698c824381b414630799adc26caTed Kremenek 978ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith case Stmt::CXXForRangeStmtClass: 979ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); 980ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 9814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 9824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 9831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 9854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 9861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 9884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 9891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 9914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 9921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 9944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 9951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 9974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 9981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 999892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek case Stmt::ImplicitCastExprClass: 1000892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); 1001a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 10024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 10034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 10041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 10064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 10071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1008115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 1009115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 1010115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 10116a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::NullStmtClass: 10126a9065a39ab15383082b914af28759da1652db18Ted Kremenek return Block; 10136a9065a39ab15383082b914af28759da1652db18Ted Kremenek 10144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 10151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 10161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 10184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 10191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 10214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 10221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 10244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 10251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 10274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 10281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10296a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::OpaqueValueExprClass: 10304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 10311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10324b9c2d235fb9449e249d74f48ecfec601650de93John McCall case Stmt::PseudoObjectExprClass: 10334b9c2d235fb9449e249d74f48ecfec601650de93John McCall return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S)); 10344b9c2d235fb9449e249d74f48ecfec601650de93John McCall 10354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 10364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 10371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1038f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne case Stmt::UnaryExprOrTypeTraitExprClass: 1039f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), 1040f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne asc); 10411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 1043852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 10441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 10464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 10471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104899cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan case Stmt::UnaryOperatorClass: 104999cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan return VisitUnaryOperator(cast<UnaryOperator>(S), asc); 105099cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 10514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 10524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 10534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 10544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1056852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 10573179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, S)) { 10584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1059247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 10606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 10611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 10634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 10669c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) { 10676b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek CFGBlock *lastBlock = Block; 10686b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek for (Stmt::child_range I = Terminator->children(); I; ++I) 10696b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (Stmt *child = *I) 10706b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (CFGBlock *b = Visit(child)) 10716b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek lastBlock = b; 10726b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek 10736b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek return lastBlock; 10744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1076852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 1077852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 10784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 10796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10803179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, A)) { 10814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1082247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, A); 10836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 10846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 10854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 10864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 10871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108899cae5b67b9711ca260e5b364a878a1a91183632Zhanyong WanCFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, 1089892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek AddStmtChoice asc) { 10903179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, U)) { 109199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan autoCreateBlock(); 1092247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, U); 109399cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan } 109499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1095892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(U->getSubExpr(), AddStmtChoice()); 109699cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan} 109799cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1098852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 1099852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 11004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (B->isLogicalOp()) { // && or || 11019c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1102247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, B); 11031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1104d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 11054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 11061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the LHS 11089c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = createBlock(false); 11094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LHSBlock->setTerminator(B); 11101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the RHS 11124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = ConfluenceBlock; 11134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = NULL; 11149c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = addStmt(B->getRHS()); 1115862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 1116862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek if (RHSBlock) { 1117d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1118862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek return 0; 111936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 1120862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // Create an empty block for cases where the RHS doesn't require 1121862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // any explicit statements in the CFG. 1122862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek RHSBlock = createBlock(); 1123862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 11241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112500998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 11260a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(B->getLHS()); 11272de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr)) 1128941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek KnownVal.negate(); 112900998a068e50945118f334c98af05ed44d7c22a6Mike Stump 11304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now link the LHSBlock with RHSBlock. 11312de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LOr) { 11320a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 11330a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else { 11352de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LAnd); 11360a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 11370a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 113819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 11391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Generate the blocks for evaluating the LHS. 11414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = LHSBlock; 11424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 114436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 114536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->getOpcode() == BO_Comma) { // , 11466dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 1147247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 11484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 11494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 11506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 115136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 115236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->isAssignmentOp()) { 11533179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1154fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 1155247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1156fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 1157892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(B->getLHS()); 1158e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 1159fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 11601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11613179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1162e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 1163247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1164e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 1165e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 1166a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *RBlock = Visit(B->getRHS()); 1167a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *LBlock = Visit(B->getLHS()); 1168a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr 1169a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // containing a DoStmt, and the LHS doesn't create a new block, then we should 1170a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // return RBlock. Otherwise we'll incorrectly return NULL. 1171a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu return (LBlock ? LBlock : RBlock); 11724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1174852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { 11753179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 1176721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 1177247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 1178721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 1179721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 11804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1181cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 11824f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 11834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 11844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 1185d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1186d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 11871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 11894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 11904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 11911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 11934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 11949ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (BreakJumpTarget.block) { 11959ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B); 11969ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, BreakJumpTarget.block); 1197f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 11984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 11991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 12024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12048026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redlstatic bool CanThrow(Expr *E, ASTContext &Ctx) { 12054c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 12064c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 12074c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 12084c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 12094c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 1210ad5a894df1841698c824381b414630799adc26caTed Kremenek 12114c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 12124c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 12134c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 12148026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (Proto->isNothrow(Ctx)) 12154c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 12164c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 12174c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 12184c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 12194c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1220852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 12211de85338543dd6228eb518185e385d94d377f4cbJohn McCall // Compute the callee type. 12221de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType calleeType = C->getCallee()->getType(); 12231de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (calleeType == Context->BoundMemberTy) { 12241de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType boundType = Expr::findBoundMemberType(C->getCallee()); 12251de85338543dd6228eb518185e385d94d377f4cbJohn McCall 12261de85338543dd6228eb518185e385d94d377f4cbJohn McCall // We should only get a null bound type if processing a dependent 12271de85338543dd6228eb518185e385d94d377f4cbJohn McCall // CFG. Recover by assuming nothing. 12281de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (!boundType.isNull()) calleeType = boundType; 12292455636163fdd18581d7fdae816433f886d88213Mike Stump } 12302455636163fdd18581d7fdae816433f886d88213Mike Stump 12311de85338543dd6228eb518185e385d94d377f4cbJohn McCall // If this is a call to a no-return function, this stops the block here. 12321de85338543dd6228eb518185e385d94d377f4cbJohn McCall bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); 12331de85338543dd6228eb518185e385d94d377f4cbJohn McCall 12344c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 1235079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1236079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 12377a17851eee37f933eb57a5af7e1a0eb455443f6aAnders Carlsson if (Context->getLangOptions().Exceptions) { 12386c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 12394c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 1240079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 1241079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1242079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 12432455636163fdd18581d7fdae816433f886d88213Mike Stump if (FD->hasAttr<NoReturnAttr>()) 12442455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 1245079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 12464c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 1247079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 12482455636163fdd18581d7fdae816433f886d88213Mike Stump 12498026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (!CanThrow(C->getCallee(), *Context)) 12504c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 12514c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 125294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan if (!NoReturn && !AddEHEdge) 125394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan return VisitStmt(C, asc.withAlwaysAdd(true)); 12541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1255079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1256079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1257d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1258079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1259079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1261dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (NoReturn) 1262dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 1263dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 1264dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createBlock(); 1265dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 1266247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 12672455636163fdd18581d7fdae816433f886d88213Mike Stump 12684c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1269079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1270079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 12710a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 1272079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 12730a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 1274079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 12751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12762455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1277d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1278d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1279852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1280852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 12819c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1282247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1283d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12843fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 12851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 128694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 12873fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 12883fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 12899c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd); 1290d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12913fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 12921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12933fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 12943fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 12959c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd); 1296d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 12973fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 12981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12993fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 130000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 13010a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 13020a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 13030a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 13043fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 13051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 13063fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 13071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13099c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) { 1310fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 13119c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LastBlock = Block; 13124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 13134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 13144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1315334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1316334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1317334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1318334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 13191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1320e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1321e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 13221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1323079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 13244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 13254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 13261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 132756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallCFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, 1328852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 132956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); 133056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL); 133156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 1332f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1333f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 13349c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1335247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1336d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1337f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 13381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 133994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 1340115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1341f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1342f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1343f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1344f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1345f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1346f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 13479c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = 0; 134856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const Expr *trueExpr = C->getTrueExpr(); 134956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (trueExpr != opaqueValue) { 135056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); 1351d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1352f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1353f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1354f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 1355f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek else 1356f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek LHSBlock = ConfluenceBlock; 13571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1358f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1359f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 13609c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); 1361d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1362f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 13631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1364f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1365f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 13661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 136700998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 13680a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 1369f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 13700a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1371f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 137256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Expr *condExpr = C->getCond(); 1373d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1374f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (opaqueValue) { 1375f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Run the condition expression if it's not trivially expressed in 1376f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // terms of the opaque value (or if there is no opaque value). 1377f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (condExpr != opaqueValue) 1378f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addStmt(condExpr); 1379d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1380f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Before that, run the common subexpression if there was one. 1381f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // At least one of this or the above will be run. 1382f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(BCO->getCommon()); 1383f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek } 1384f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek 1385f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(condExpr); 1386f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1387f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 13884f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 1389bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // Check if the Decl is for an __label__. If so, elide it from the 1390bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // CFG entirely. 1391bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek if (isa<LabelDecl>(*DS->decl_begin())) 1392bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek return Block; 1393bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek 139429c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // This case also handles static_asserts. 13958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (DS->isSingleDecl()) 13968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitDeclSubExpr(DS); 13971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 13991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy. 14015f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<Decl*,10> BufTy; 14024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BufTy Buf(DS->decl_begin(), DS->decl_end()); 14031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) { 14054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 14064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 14074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 14081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 14104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 14114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 14124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 14131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 14144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 14151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 14178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = VisitDeclSubExpr(DSNew); 14184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 14191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 14214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 14221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 14248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski/// DeclStmts and initializers in them. 14259c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { 14268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert(DS->isSingleDecl() && "Can handle single declarations only."); 142729c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek Decl *D = DS->getSingleDecl(); 142829c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 142929c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek if (isa<StaticAssertDecl>(D)) { 143029c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // static_asserts aren't added to the CFG because they do not impact 143129c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // runtime semantics. 143229c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek return Block; 143329c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek } 143429c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 14358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 14361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!VD) { 14388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1439892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 14404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 14418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 14421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 14448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 14458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 14468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 14478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 14484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 14498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 14508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = VD->getType()->isReferenceType(); 14514765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 14528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 14538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 14548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 14554765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 14568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 14578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 14588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 14598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 14608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1461892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 14621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 14648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (HasTemporaries) 14658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 14668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 1467892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 14688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski else 1469892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(Init); 14704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 14711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 1473f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); 1474f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 14754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = addStmt(VA->getSizeExpr()); 14761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1477fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1478fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1479fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1480fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 14814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 1482d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1483fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 14849c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { 14856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 14866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 14876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 14886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 14896c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 14906c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 14916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 149204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 149304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 149404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 149504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 149604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 149704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 14989c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 149904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 150004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 150104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 150204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 150304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 1504fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // The block we were processing is now finished. Make it the successor 15056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 15066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1507d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1508d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15094e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1510c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 15116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1512b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 15139c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ElseBlock = Succ; 15146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15159c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Else = I->getElse()) { 1516d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 15176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1518d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 15196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1520d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 152104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 152204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 152304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 152404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 152504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 152604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 15274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 15286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1529b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1530b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 15314e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1532d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15334e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 15344e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1535c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 15366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1537b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 15389c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ThenBlock; 1539d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 15409c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *Then = I->getThen(); 15416db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1542d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 15436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 154404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 154504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 154604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 154704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 154804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 154904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 15504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 15516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1552dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1553dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1554dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1555dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1556dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 15570a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ThenBlock, sv.get()); 15586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1559d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15604e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 15616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 15620cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1563d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 15646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1565d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 15666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1567d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1568d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 15696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 157000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 15710a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(I->getCond()); 157200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1573d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 15740a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 15750a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 15766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 15786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 15796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 158061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek Block = addStmt(I->getCond()); 1581ad5a894df1841698c824381b414630799adc26caTed Kremenek 158261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 158361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 158461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 158561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 158661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 1587d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, I->getConditionVariableDeclStmt()); 158861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek addStmt(Init); 158961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 159061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1591ad5a894df1841698c824381b414630799adc26caTed Kremenek 159261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek return Block; 1593d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 15946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15969c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) { 15976c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1598d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 15996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 16006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 16016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 16026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1603d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1604d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1605d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 16066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1607d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 1608fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 16090a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 16106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 16126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1613852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1614d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 16150cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 16169c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { 1617d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 16184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 1619ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner CFGBlock *LabelBlock = Block; 16206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 16224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 16236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1624ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner assert(LabelMap.find(L->getDecl()) == LabelMap.end() && 1625ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner "label already in map"); 1626ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); 16276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 16296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 16306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 16316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 16329cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1633d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16344e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 16356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1637d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 16386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1639d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1640d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 16416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1642d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1643d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 164431dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 16459c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { 16466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 16476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 16484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1649d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1650d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 16516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1653d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 16546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1655d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1656d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1657f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1658f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1659f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 16609ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, JT.scopePosition, G); 16619ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, JT.block); 1662f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1663d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 16646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1665d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1666d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 16679c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { 16689c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 16696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 167047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 167147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 167247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 167347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 167447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 167547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 167647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 16779c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Init = F->getInit()) 167847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1679f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1680f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 16819c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = F->getConditionVariable()) 168247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 168347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 168447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 168547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 168647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1687fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1688fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1689d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1690d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16914e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1692d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 16934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 16944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 16956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16963f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 16973f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 1698f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 169947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 17003f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 17016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 17026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 17036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 17049c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 17059c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 17066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 170749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 17086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(F); 17096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 17116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 17129c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = F->getCond()) { 171349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 171449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 17159ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (badCFG) 17169ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek return 0; 17178f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek assert(Block == EntryConditionBlock || 17188f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek (Block == 0 && EntryConditionBlock == Succ)); 171958b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek 172058b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // If this block contains a condition variable, add both the condition 172158b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // variable and initializer to the CFG. 172258b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (VarDecl *VD = F->getConditionVariable()) { 172358b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (Expr *Init = VD->getInit()) { 172458b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek autoCreateBlock(); 1725d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, F->getConditionVariableDeclStmt()); 172658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek EntryConditionBlock = addStmt(Init); 172758b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek assert(Block == EntryConditionBlock); 172858b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 172958b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 1730ad5a894df1841698c824381b414630799adc26caTed Kremenek 17314e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1732d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17334e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17344e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 173549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 1736d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 17376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 17386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 173949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 17406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 174100998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1742941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal(true); 17431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 174400998a068e50945118f334c98af05ed44d7c22a6Mike Stump if (F->getCond()) 17450a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek KnownVal = tryEvaluateBool(F->getCond()); 174600998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1747d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1748d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 17496db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 17506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17513f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current values for Block, Succ, and continue targets. 1752f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1753f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 17546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1755af603f742491dc4707138c0293d295171fdd51baTed Kremenek // Create a new block to contain the (bottom) of the loop body. 1756af603f742491dc4707138c0293d295171fdd51baTed Kremenek Block = NULL; 175747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 175847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 175947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 17606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17619c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInc()) { 17626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 17636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 17644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 17656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 17666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // No increment code. Create a special, empty, block that is used as the 17676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // target block for "looping back" to the start of the loop. 17683575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Succ == EntryConditionBlock); 176947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski Succ = Block ? Block : createBlock(); 1770e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 17716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17723575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 17733575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 17743575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1775d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17764e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17773575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 17783575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 17796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 178047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 17816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17823575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // The starting block for the loop increment is the block that should 17833575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 17849ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek ContinueJumpTarget.block->setLoopTarget(F); 17853575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 178647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 178747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 178847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 178947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 179047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 17916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 17926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 17939c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(F->getBody()); 1794af603f742491dc4707138c0293d295171fdd51baTed Kremenek 1795af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 17969ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block;//can happen for "for (...;...;...);" 1797d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 1798941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 17996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1800941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // This new body block is a successor to our "exit" condition block. 18010a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1802d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 18036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1804941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1805941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 18060a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 18076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1808d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 18096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 18109c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInit()) { 1811d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 181249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 18132bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 181436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 181536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // There is no loop initialization. We are thus basically a while loop. 181636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // NULL out Block to force lazy block construction. 181736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Block = NULL; 181836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Succ = EntryConditionBlock; 181936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return EntryConditionBlock; 1820d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1821d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1822115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 18233179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, M)) { 1824115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 1825247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, M); 1826115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 1827892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(M->getBase()); 1828115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 1829115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 18309c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { 1831514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 1832514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 1833514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1834514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 1835514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1836514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1837514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1838514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 1839514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 1840514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1841514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 18424cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 1843514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 1844514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 1845514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 1846514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 1847514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1848514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 1849514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 1850514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1851514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 1852514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1853514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 1854514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 1855514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1856514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1857514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 18586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 18596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 18606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 1861514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 18626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18639c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = 0; 18646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1865514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 1866d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18674e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1868514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 1869514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 18704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 18714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 18726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18734cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 18749c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 18756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18764cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 18776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 18786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 18806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 18816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 1882892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(ExitConditionBlock, S); 18834cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 18846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18854cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 1886fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // generate new blocks as necessary. We DON'T add the statement by default to 18876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 1888012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek CFGBlock *EntryConditionBlock = Visit(S->getElement(), 1889012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek AddStmtChoice::NotAlwaysAdd); 18906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1891d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18934e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 18944e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 18956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 18976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 18984cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 18996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19004cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 19016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 19024cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 1903f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Succ(Succ); 1904f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 1905f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 19066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1907f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 1908f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 19096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19109c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(S->getBody()); 19116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19124cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 19134cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" 19144e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1915d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19164e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19174e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 19186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19194cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 19200a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, BodyBlock); 19214cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 19226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19234cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 19244cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 19250a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopSuccessor); 19264cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 1927514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 19284cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 1929514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 19306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 19316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19329c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 1933b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 19346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1935b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 19364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 19376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1938da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 1939da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 1940da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 1941d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1942da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 19436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1944da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 1945fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 1946da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 19476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19484beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 19494beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 1950247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 19514beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 1952b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 19534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 1954b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 19556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19569c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { 19574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 195890658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 1959e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 1960514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 19614b9c2d235fb9449e249d74f48ecfec601650de93John McCallCFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { 19624b9c2d235fb9449e249d74f48ecfec601650de93John McCall autoCreateBlock(); 19634b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19644b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Add the PseudoObject as the last thing. 19654b9c2d235fb9449e249d74f48ecfec601650de93John McCall appendStmt(Block, E); 19664b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19674b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *lastBlock = Block; 19684b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19694b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Before that, evaluate all of the semantics in order. In 19704b9c2d235fb9449e249d74f48ecfec601650de93John McCall // CFG-land, that means appending them in reverse order. 19714b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (unsigned i = E->getNumSemanticExprs(); i != 0; ) { 19724b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *Semantic = E->getSemanticExpr(--i); 19734b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19744b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If the semantic is an opaque value, we're being asked to bind 19754b9c2d235fb9449e249d74f48ecfec601650de93John McCall // it to its source expression. 19764b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) 19774b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantic = OVE->getSourceExpr(); 19784b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19794b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (CFGBlock *B = Visit(Semantic)) 19804b9c2d235fb9449e249d74f48ecfec601650de93John McCall lastBlock = B; 19814b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 19824b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19834b9c2d235fb9449e249d74f48ecfec601650de93John McCall return lastBlock; 19844b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 19854b9c2d235fb9449e249d74f48ecfec601650de93John McCall 19869c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { 19879c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 19886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 198905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 199005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 199105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 199205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 199305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 199405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 1995f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 19969c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 199705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 199805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 199905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 2000f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2001fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 2002fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 2003d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2004d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20054e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2006d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 20076b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek Block = 0; 20084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 20094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 20106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 20126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 20136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 20149c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 20159c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 20166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 201749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 201849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek ExitConditionBlock->setTerminator(W); 20196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 20216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. Thus we update 20226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "Succ" after adding the condition. 20239c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = W->getCond()) { 202449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 202549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 2026a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // The condition might finish the current 'Block'. 2027a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu Block = EntryConditionBlock; 2028ad5a894df1841698c824381b414630799adc26caTed Kremenek 20294ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // If this block contains a condition variable, add both the condition 20304ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // variable and initializer to the CFG. 20314ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 20324ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (Expr *Init = VD->getInit()) { 20334ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek autoCreateBlock(); 2034d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, W->getConditionVariableDeclStmt()); 20354ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek EntryConditionBlock = addStmt(Init); 20364ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek assert(Block == EntryConditionBlock); 20374ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 20384ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 20394ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek 20404e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2041d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20424e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20434e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 204449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 20456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 20476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 204849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 20496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 205000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 20510a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(W->getCond()); 205200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2053d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 2054d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 2055f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 2056d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2057d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2058f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2059f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2060f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 2061f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 20626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 20636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 2064f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Block = 0; 2065f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Succ == EntryConditionBlock); 2066f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ = createBlock(); 2067f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ->setLoopTarget(W); 2068f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 20696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2070d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 207105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 20726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2073d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2074f752fcfae84fbf21b78383bf2461633382d51844Ted Kremenek Block = NULL; 20756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 207605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 207705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 207805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 207905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 208005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 208105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 208205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 208305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2084d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 20859c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(W->getBody()); 20866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2087af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 20889ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;" 20894e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2090d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20914e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 20936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2094941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 20950a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 2096bf15b278a439d73b605ec00a8d3977ef305712f4Ted Kremenek } 20976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2098941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 2099941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 21000a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 21016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 21036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 2104d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 21056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21064ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 21075482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 210849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 2109d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 21101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21129c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { 21134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 21144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 21154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 21164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 21176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21189c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { 21192fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 21202fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 21216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21226c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2123d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 21256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21262fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 21272fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 21286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21292fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 21300a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 21316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 21336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 2134852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 21352fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 2136989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 21379c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { 21386c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2139d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21400979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 21410979d80615df97c675423de631c1b884819f4712Mike Stump 21420979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 21430979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 21440979d80615df97c675423de631c1b884819f4712Mike Stump 21455d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 21465d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 21470a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 2148ad5a894df1841698c824381b414630799adc26caTed Kremenek else 21495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 21500a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 21510979d80615df97c675423de631c1b884819f4712Mike Stump 21520979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 21530979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 2154852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 21550979d80615df97c675423de631c1b884819f4712Mike Stump} 21560979d80615df97c675423de631c1b884819f4712Mike Stump 21579c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { 21589c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 21596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21608f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 21618f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 2162d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2163d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21644e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2165d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 21664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 21674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 21686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 21706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 21716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 21729c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 21739c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 21746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 217549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 21766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 21776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 21796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 21809c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) { 218149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 218249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 21834e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2184d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21854e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21864e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 218749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 21886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21895482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 219049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 219149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 219200998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 21930a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(D->getCond()); 219400998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2195d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 21969c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = NULL; 2197d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 21986db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 21996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2200d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2201f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2202f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2203f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 22046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2205d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 2206f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 22076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2208d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 2209f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 22106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2211d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2212b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 22136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 221405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 221505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 221605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 221705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 221805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2219d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 22204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 22216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2222af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 2223a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 22244e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2225d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22264e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 22274e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 22286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2229d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 2230d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 2231d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 2232d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 2233d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 2234d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 2235d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 2236d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 2237d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 2238d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 2239d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 2240d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 22410a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopBackBlock); 2242d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 2243d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 22440a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, NULL); 2245b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 22466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2247941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 2248941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 22490a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 22506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 22526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 2253d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 22546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2255d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 22565482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 2257d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 2258d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2259d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 22609c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { 2261d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 2262d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 2263d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2264d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 22656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2266d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 2267d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 2268d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 22696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2270d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 2271235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 22729ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (ContinueJumpTarget.block) { 22739ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C); 22749ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, ContinueJumpTarget.block); 2275f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 2276235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 22776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2278d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 2279d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 22801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2281f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter CollingbourneCFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 2282f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc) { 228313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 22843179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 228513fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2286892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, E); 228713fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 22881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 229097e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek CFGBlock *lastBlock = Block; 229197e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek 22924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 2293f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); 22944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 229597e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek lastBlock = addStmt(VA->getSizeExpr()); 2296f91a5b008d1a63630ae483247204c2651e512fa1Ted Kremenek } 229797e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek return lastBlock; 2298d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 22991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 23014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 23029c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 23033179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, SE)) { 230413fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2305892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, SE); 230613fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 23074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 23084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2309d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 23109c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { 23116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 23126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 23139c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchSuccessor = NULL; 23146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23158ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 23168ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 23178ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 23188ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 23198ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 23208ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 23219c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 23228ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 23238ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 23248ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 23258ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 23268ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2327d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2328d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23294e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2330d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 23316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2332d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2333d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2334d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2335eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2336f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2337eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 23386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 23396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 23406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2341eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 23426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2343d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2344d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 23456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2346d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2347d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2348d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2349f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 23506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 23526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 23536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 23546db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 235549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 23568ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2357e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // For pruning unreachable case statements, save the current state 2358e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // for tracking the condition value. 2359e71f3d587844110d836c82250830b27b1651afdbTed Kremenek SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered, 2360e71f3d587844110d836c82250830b27b1651afdbTed Kremenek false); 23610498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2362e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Determine if the switch condition can be explicitly evaluated. 2363e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 23640498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult result; 2365e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek bool b = tryEvaluate(Terminator->getCond(), result); 2366e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, 2367e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek b ? &result : 0); 23680498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 23698ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 23708ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 23718ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 23728ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 23738ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2374d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 23754e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2376d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23774e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 23784e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 237949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 23806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 2381432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // following the switch body. Moreover, take into account if all the 2382432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // cases of a switch are covered (e.g., switching on an enum value). 2383e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2384432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek switchExclusivelyCovered || Terminator->isAllEnumCasesCovered() 2385432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek ? 0 : DefaultCaseBlock); 23866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 238749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2388411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 2389d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 23906b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek Block = addStmt(Terminator->getCond()); 2391ad5a894df1841698c824381b414630799adc26caTed Kremenek 23926b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 23936b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 23946b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 23956b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 23966b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 2397d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, Terminator->getConditionVariableDeclStmt()); 23986b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek addStmt(Init); 23996b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 24006b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2401ad5a894df1841698c824381b414630799adc26caTed Kremenek 24026b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek return Block; 2403d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2404e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2405e71f3d587844110d836c82250830b27b1651afdbTed Kremenekstatic bool shouldAddCase(bool &switchExclusivelyCovered, 2406e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const Expr::EvalResult *switchCond, 2407e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const CaseStmt *CS, 2408e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ASTContext &Ctx) { 2409e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (!switchCond) 2410e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek return true; 2411e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek 2412e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool addCase = false; 24130498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2414e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!switchExclusivelyCovered) { 2415e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (switchCond->Val.isInt()) { 2416e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the LHS of the case value. 241785df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx); 2418e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const llvm::APSInt &condInt = switchCond->Val.getInt(); 2419e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2420e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (condInt == lhsInt) { 2421e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2422e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2423e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2424e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else if (condInt < lhsInt) { 2425e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (const Expr *RHS = CS->getRHS()) { 2426e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the RHS of the case value. 242785df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx); 242885df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (V2 <= condInt) { 2429e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2430e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2431e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2432e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2433e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2434e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2435e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else 2436e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2437e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2438e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return addCase; 2439e71f3d587844110d836c82250830b27b1651afdbTed Kremenek} 2440d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 24419c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) { 24426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 24436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 24440fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 24450498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 24460fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 24470fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 24480fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 24490fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 24500fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 24510a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek CFGBlock *currentBlock = createBlock(false); 24520a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek currentBlock->setLabel(CS); 24530fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 24540fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 24550a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, currentBlock); 24560fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 24570a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TopBlock = currentBlock; 24580fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2459e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2460e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2461e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2462e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? currentBlock : 0); 24630fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2464e71f3d587844110d836c82250830b27b1651afdbTed Kremenek LastBlock = currentBlock; 24650fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 24660fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 24670fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 246829ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 24690fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 24700fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 24711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24729c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CaseBlock = Block; 24734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 24744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 24756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 24776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 24784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 24794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2480d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24814e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 24826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 24846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 24854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2486e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2487e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2488e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2489e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? CaseBlock : 0); 24906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2491d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2492d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 24936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24940fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 24950a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, CaseBlock); 24960fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 249736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 24980fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 24990fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 25000fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 25016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25020fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2503d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 25046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25059c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) { 25064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 25074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 25081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2509eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 25104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 25114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 25124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 25136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 25156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2516411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 25171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2518d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25194e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2520eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 25216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 25226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 25236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 25246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 25256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 25266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2527eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2528eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 25296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2530eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2531eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 25326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2534295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2535d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 25365d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 25375d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 25385d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 25399c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TrySuccessor = NULL; 25405d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25415d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2542d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25435d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 25445d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 25455d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 25465d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2547a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 25485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2550f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 25515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2552f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 25535d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2554a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 25555d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 25565d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 25575d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 25585d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2559a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2560a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2561a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 25625d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 25635d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 25645d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 25655d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 25665d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 25675d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 25680a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, CatchBlock); 25695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2570a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2571a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 25720a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2573a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 25740a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2575a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 25765d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25775d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 25785d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 25795d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2580f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2581f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock, NewTryTerminatedBlock); 2582f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek cfg->addTryDispatchBlock(TryTerminatedBlock); 2583f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 25846db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 25855d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 25863fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek Block = addStmt(Terminator->getTryBlock()); 25875d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return Block; 25885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 25895d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25909c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { 25915d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 25925d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 25935d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 25940e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 25950e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 25960e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 25970e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 25980e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 25990e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 26009c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = CS->getExceptionDecl()) { 26010e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 26020e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 26030e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 26040e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 26050e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 26065d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 26075d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 26085d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26099c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CatchBlock = Block; 26105d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 26115d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 26125d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26135d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 26145d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2615d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 26165d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 26175d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26185d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 26195d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 26205d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26215d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 26225d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 26235d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26249c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { 2625ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // C++0x for-range statements are specified as [stmt.ranged]: 2626ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // 2627ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // { 2628ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // auto && __range = range-init; 2629ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for ( auto __begin = begin-expr, 2630ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __end = end-expr; 2631ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __begin != __end; 2632ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // ++__begin ) { 2633ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for-range-declaration = *__begin; 2634ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // statement 2635ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2636ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2637ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2638ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save local scope position before the addition of the implicit variables. 2639ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 2640ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2641ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Create local scopes and destructors for range, begin and end variables. 2642ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *Range = S->getRangeStmt()) 2643ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(Range); 2644ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *BeginEnd = S->getBeginEndStmt()) 2645ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(BeginEnd); 2646ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S); 2647ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2648ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LocalScope::const_iterator ContinueScopePos = ScopePos; 2649ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2650ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // "for" is a control-flow statement. Thus we stop processing the current 2651ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // block. 26529c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 2653ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Block) { 2654ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2655ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2656ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Block; 2657ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } else 2658ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Succ; 2659ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2660ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current value for the break targets. 2661ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // All breaks should go to the code following the loop. 2662ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2663ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 2664ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2665ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The block for the __begin != __end expression. 26669c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConditionBlock = createBlock(false); 2667ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ConditionBlock->setTerminator(S); 2668ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2669ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now add the actual condition to the condition block. 2670ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Expr *C = S->getCond()) { 2671ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = ConditionBlock; 2672ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *BeginConditionBlock = addStmt(C); 2673ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2674ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2675ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(BeginConditionBlock == ConditionBlock && 2676ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith "condition block in for-range was unexpectedly complex"); 2677ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith (void)BeginConditionBlock; 2678ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2679ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2680ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The condition block is the implicit successor for the loop body as well as 2681ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // any code above the loop. 2682ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = ConditionBlock; 2683ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2684ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // See if this is a known constant. 2685ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith TryResult KnownVal(true); 2686ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2687ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (S->getCond()) 2688ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith KnownVal = tryEvaluateBool(S->getCond()); 2689ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2690ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now create the loop body. 2691ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith { 2692ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(S->getBody()); 2693ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2694ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current values for Block, Succ, and continue targets. 2695ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2696ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 2697ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2698ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Generate increment code in its own basic block. This is the target of 2699ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // continue statements. 2700ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2701ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = addStmt(S->getInc()); 2702ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 2703ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2704ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The starting block for the loop increment is the block that should 2705ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // represent the 'loop target' for looping back to the start of the loop. 2706ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget.block->setLoopTarget(S); 2707ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2708ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Finish up the increment block and prepare to start the loop body. 2709ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(Block); 2710ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2711ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2712ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2713ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2714ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2715ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add implicit scope and dtors for loop variable. 2716ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeAndDtors(S->getLoopVarStmt()); 2717ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2718ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Populate a new block to contain the loop body and loop variable. 2719ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getBody()); 2720ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2721ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2722ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getLoopVarStmt()); 2723ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2724ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2725ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2726ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // This new body block is a successor to our condition block. 2727ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : Block); 2728ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2729ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2730ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Link up the condition block with the code that follows the loop (the 2731ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // false branch). 2732ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor); 2733ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2734ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add the initialization statements. 2735ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = createBlock(); 2736b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith addStmt(S->getBeginEndStmt()); 2737b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith return addStmt(S->getRangeStmt()); 2738ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith} 2739ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 27404765fa05b5652fcc4356371c2f481d0ea9a1b007John McCallCFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, 27418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc) { 27428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors) { 27438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If adding implicit destructors visit the full expression for adding 27448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // destructors of temporaries. 27458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(E->getSubExpr()); 27468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 27478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Full expression has to be added as CFGStmt so it will be sequenced 27488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before destructors of it's temporaries. 274994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(true); 27508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 27518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(E->getSubExpr(), asc); 27528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 27538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 2754a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 2755a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 27563179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2757a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2758247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2759a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 2760a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 276194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 2762a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2763a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2764a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2765a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 276681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, 276781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 276881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 276997a72c35a62304c3781aa280e28cb97a59afd585Zhongxing Xu appendStmt(Block, C); 277094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 277181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 277281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 277381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2774a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 2775a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 27763179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2777a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2778247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2779a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 278094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 2781a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2782a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2783a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2784a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 278581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 278681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 278781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 2788247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 278981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 279081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 279181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2792a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, 2793a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 27943179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2795a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2796247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2797a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2798892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(E->getSubExpr(), AddStmtChoice()); 2799a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2800a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 28019c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) { 28026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 28039c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *IBlock = cfg->getIndirectGotoBlock(); 28046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 280519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 280619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 280719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 280819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 28096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 281019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 281119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 2812d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 28134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 28144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 281519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 281619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 28170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, IBlock); 281819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 281919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 282019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 28218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) { 28228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskitryAgain: 28238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!E) { 28248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski badCFG = true; 28258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 28268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski switch (E->getStmtClass()) { 28288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski default: 28298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitChildrenForTemporaryDtors(E); 28308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::BinaryOperatorClass: 28328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E)); 28338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXBindTemporaryExprClass: 28358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXBindTemporaryExprForTemporaryDtors( 28368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<CXXBindTemporaryExpr>(E), BindToTemporary); 28378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 283856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 28398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ConditionalOperatorClass: 28408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitConditionalOperatorForTemporaryDtors( 284156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall cast<AbstractConditionalOperator>(E), BindToTemporary); 28428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ImplicitCastExprClass: 28448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For implicit cast we want BindToTemporary to be passed further. 28458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<CastExpr>(E)->getSubExpr(); 28468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 28478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ParenExprClass: 28498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<ParenExpr>(E)->getSubExpr(); 28508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 285103e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor 285203e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor case Stmt::MaterializeTemporaryExprClass: 285303e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(); 285403e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor goto tryAgain; 28558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 28578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { 28598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // When visiting children for destructors we want to visit them in reverse 28608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. Because there's no reverse iterator for children must to reverse 28618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // them in helper vector. 28625f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<Stmt *, 4> ChildrenVect; 28638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ChildrenVect ChildrenRev; 28647502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range I = E->children(); I; ++I) { 28658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (*I) ChildrenRev.push_back(*I); 28668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = Block; 28698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(), 28708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski L = ChildrenRev.rend(); I != L; ++I) { 28718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (CFGBlock *R = VisitForTemporaryDtors(*I)) 28728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = R; 28738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 28758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 28768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { 28788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->isLogicalOp()) { 28798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors for temporaries in LHS expression should be called after 28808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // those for RHS expression. Even if this will unnecessarily create a block, 28818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // this block will be used at least by the full expression. 28828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 28838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); 28848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 28858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 28868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 28888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 28898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 28908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (RHSBlock) { 28928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 28938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 28948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If RHS expression did produce destructors we need to connect created 28968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // blocks to CFG in same manner as for binary operator itself. 28978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = createBlock(false); 28988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock->setTerminator(CFGTerminator(E, true)); 28998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For binary operator LHS block is before RHS in list of predecessors 29018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // of ConfluenceBlock. 29028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), 29038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConfluenceBlock->pred_end()); 29048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 29060a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(E->getLHS()); 29078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) 29088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski KnownVal.negate(); 29098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Link LHSBlock with RHSBlock exactly the same way as for binary operator 29118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // itself. 29128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getOpcode() == BO_LOr) { 29130a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 29140a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 29158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 29168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert (E->getOpcode() == BO_LAnd); 29170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 29180a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 29198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = LHSBlock; 29228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock; 29238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 29268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return ConfluenceBlock; 29278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 292936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (E->isAssignmentOp()) { 29308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For assignment operator (=) LHS expression is visited 29318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before RHS expression. For destructors visit them in reverse order. 29328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 29338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 29348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock ? LHSBlock : RHSBlock; 29358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For any other binary operator RHS expression is visited before 29388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // LHS expression (order of children). For destructors visit them in reverse 29398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. 29408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 29418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 29428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return RHSBlock ? RHSBlock : LHSBlock; 29438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 29448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( 29468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *E, bool BindToTemporary) { 29478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for temporaries in subexpression. 29488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr()); 2949249c9458e2cc5b671634baefe8517d7598883a20Zhongxing Xu if (!BindToTemporary) { 29508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If lifetime of temporary is not prolonged (by assigning to constant 29518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // reference) add destructor for it. 2952c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 2953c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If the destructor is marked as a no-return destructor, we need to create 2954c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // a new block for the destructor which does not have as a successor 2955c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far. Control won't flow out of this block. 2956c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor(); 2957dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) 2958dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 2959dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 2960c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 2961c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 29628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendTemporaryDtor(Block, E); 29638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = Block; 29648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 29668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 29678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( 296956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AbstractConditionalOperator *E, bool BindToTemporary) { 29708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for condition expression. Even if this will 29718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // unnecessarily create a block, this block will be used at least by the full 29728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // expression. 29738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 29748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); 29758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 29768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 297756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (BinaryConditionalOperator *BCO 297856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall = dyn_cast<BinaryConditionalOperator>(E)) { 297956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); 29808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 29818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 29828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 298456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall // Try to add block with destructors for LHS expression. 298556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *LHSBlock = NULL; 298656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Succ = ConfluenceBlock; 298756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Block = NULL; 298856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); 298956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (badCFG) 299056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return NULL; 299156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 29928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for RHS expression; 29938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 29948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 299556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), 299656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall BindToTemporary); 29978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 29988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 29998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock && !LHSBlock) { 30018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If neither LHS nor RHS expression had temporaries to destroy don't create 30028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // more blocks. 30038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 30048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 30058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = createBlock(false); 30088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block->setTerminator(CFGTerminator(E, true)); 30098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 30110a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(E->getCond()); 30128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (LHSBlock) { 30140a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 30158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (KnownVal.isFalse()) { 30160a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, NULL); 30178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 30180a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, ConfluenceBlock); 30198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); 30208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock) 30238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski RHSBlock = ConfluenceBlock; 30240a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 30258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 30278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 30288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3029befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 3030026473c2175424a039f51ca8949937268721b965Ted Kremenek 30316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 30326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 30336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 30349c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFG::createBlock() { 3035026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 3036026473c2175424a039f51ca8949937268721b965Ted Kremenek 3037026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 3038ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 303902f34c5003b2c5067675f89ffce0a84c28faf722Anna Zaks new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this); 3040ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 3041026473c2175424a039f51ca8949937268721b965Ted Kremenek 3042026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 3043ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 3044ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 3045026473c2175424a039f51ca8949937268721b965Ted Kremenek 3046026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 3047ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 3048026473c2175424a039f51ca8949937268721b965Ted Kremenek} 3049026473c2175424a039f51ca8949937268721b965Ted Kremenek 3050026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 3051026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 30529c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFG::buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, 3053b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const BuildOptions &BO) { 3054b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFGBuilder Builder(C, BO); 3055b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek return Builder.buildCFG(D, Statement); 3056fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 3057fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 3058c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekconst CXXDestructorDecl * 3059c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed KremenekCFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { 3060c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek switch (getKind()) { 3061c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Invalid: 3062c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Statement: 3063c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Initializer: 3064c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek llvm_unreachable("getDestructorDecl should only be used with " 3065c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek "ImplicitDtors"); 3066c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::AutomaticObjectDtor: { 3067c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const VarDecl *var = cast<CFGAutomaticObjDtor>(this)->getVarDecl(); 3068c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = var->getType(); 3069697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek ty = ty.getNonReferenceType(); 3070c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek if (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { 3071c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek ty = arrayType->getElementType(); 3072c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek } 3073c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const RecordType *recordType = ty->getAs<RecordType>(); 3074c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXRecordDecl *classDecl = 3075697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek cast<CXXRecordDecl>(recordType->getDecl()); 3076c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return classDecl->getDestructor(); 3077c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3078c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::TemporaryDtor: { 3079c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXBindTemporaryExpr *bindExpr = 3080c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek cast<CFGTemporaryDtor>(this)->getBindTemporaryExpr(); 3081c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXTemporary *temp = bindExpr->getTemporary(); 3082c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return temp->getDestructor(); 3083c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3084c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::BaseDtor: 3085c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::MemberDtor: 3086c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3087c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // Not yet supported. 3088c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return 0; 3089c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3090697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek llvm_unreachable("getKind() returned bogus value"); 3091c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek} 3092c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3093c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekbool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { 3094c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek if (const CXXDestructorDecl *cdecl = getDestructorDecl(astContext)) { 3095c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = cdecl->getType(); 3096c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return cast<FunctionType>(ty)->getNoReturnAttr(); 3097c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3098c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return false; 30993c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek} 31003c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 310163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 310263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek// CFG: Queries for BlkExprs. 310363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 310463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 310563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremeneknamespace { 310686946745225096243f6969dc745267b78fc211a6Ted Kremenek typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy; 310763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 310863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 3109f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenekstatic void FindSubExprAssignments(const Stmt *S, 3110f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek llvm::SmallPtrSet<const Expr*,50>& Set) { 31118a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!S) 311233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return; 31136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3114f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek for (Stmt::const_child_range I = S->children(); I; ++I) { 3115f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *child = *I; 31168a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!child) 31178a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek continue; 3118ad5a894df1841698c824381b414630799adc26caTed Kremenek 3119f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(child)) 312033d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (B->isAssignmentOp()) Set.insert(B); 31216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31228a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek FindSubExprAssignments(child, Set); 312333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 312433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek} 312533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek 312663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekstatic BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { 312763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = new BlkExprMapTy(); 31286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Look for assignments that are used as subexpressions. These are the only 31306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // assignments that we want to *possibly* register as a block-level 31316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression. Basically, if an assignment occurs both in a subexpression and 31326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // at the block-level, it is a block-level expression. 3133f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek llvm::SmallPtrSet<const Expr*,50> SubExprAssignments; 31346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 313563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) 3136ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 31373c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = BI->getAs<CFGStmt>()) 31383c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek FindSubExprAssignments(S->getStmt(), SubExprAssignments); 313986946745225096243f6969dc745267b78fc211a6Ted Kremenek 3140411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { 31416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Iterate over the statements again on identify the Expr* and Stmt* at the 31436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block-level that are block-level expressions. 3144411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 3145b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { 31463c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CFGStmt *CS = BI->getAs<CFGStmt>(); 31473c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (!CS) 3148b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu continue; 3149f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const Expr *Exp = dyn_cast<Expr>(CS->getStmt())) { 3150ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert((Exp->IgnoreParens() == Exp) && "No parens on block-level exps"); 31516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3152f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { 315333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek // Assignment expressions that are not nested within another 31546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression are really "statements" whose value is never used by 31556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // another expression. 3156411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) 315733d4aab80f31bd06257526fe2883ea920529456bTed Kremenek continue; 31589c378f705405d37f49795d5e915989de774fe11fTed Kremenek } else if (const StmtExpr *SE = dyn_cast<StmtExpr>(Exp)) { 31596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Special handling for statement expressions. The last statement in 31606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the statement expression is also a block-level expr. 31619c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CompoundStmt *C = SE->getSubStmt(); 316286946745225096243f6969dc745267b78fc211a6Ted Kremenek if (!C->body_empty()) { 3163ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose const Stmt *Last = C->body_back(); 3164ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (const Expr *LastEx = dyn_cast<Expr>(Last)) 3165ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose Last = LastEx->IgnoreParens(); 316633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3167ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[Last] = x; 316886946745225096243f6969dc745267b78fc211a6Ted Kremenek } 316986946745225096243f6969dc745267b78fc211a6Ted Kremenek } 3170e2dcd783a04f654c50bd8b13fb08a440afbd67e7Ted Kremenek 317133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3172411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek (*M)[Exp] = x; 317333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 3174b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 31756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3176411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek // Look at terminators. The condition is a block-level expression. 31776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31789c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *S = (*I)->getTerminatorCondition(); 31796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3180390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek if (S && M->find(S) == M->end()) { 3181ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose unsigned x = M->size(); 3182ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[S] = x; 3183411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 3184411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 31856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 318686946745225096243f6969dc745267b78fc211a6Ted Kremenek return M; 318763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 318863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 31899c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt *S) { 319086946745225096243f6969dc745267b78fc211a6Ted Kremenek assert(S != NULL); 319163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } 31926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 319363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap); 319486946745225096243f6969dc745267b78fc211a6Ted Kremenek BlkExprMapTy::iterator I = M->find(S); 31953fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); 319663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 31977dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 319863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekunsigned CFG::getNumBlkExprs() { 319963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap)) 320063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return M->size(); 320136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 320236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // We assume callers interested in the number of BlkExprs will want 320336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // the map constructed if it doesn't already exist. 320436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan BlkExprMap = (void*) PopulateBlkExprMap(*this); 320536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size(); 320663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 320763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 3208274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3209ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 3210ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3211ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3212ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 3213be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 3214ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 32156e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (To && F.IgnoreDefaultsWithCoveredEnums) { 3216ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 3217ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 3218ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 32196e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { 3220ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 32216e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek const Stmt *L = To->getLabel(); 32226e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 32236e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek return true; 3224ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3225ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3226ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3227ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3228ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 3229ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 3230ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3231ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3232274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek// Cleanup: CFG dstor. 3233274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3234274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek 323563f5887f316fb52d243fcbb3631c039de6c4b993Ted KremenekCFG::~CFG() { 323663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap); 323763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 32386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32397dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 32407dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 32417dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 32427dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 324342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 32442bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 3245ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 32463c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 32473c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 324842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 32491cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 32500a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek signed currentBlock; 32510a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek unsigned currentStmt; 3252e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 325342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 32541c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 3255e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 32563c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek : currentBlock(0), currentStmt(0), LangOpts(LO) 32573c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek { 325842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 325942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 3260ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 32611cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 32623c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *SE = BI->getAs<CFGStmt>()) { 32633c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt= SE->getStmt(); 32641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 32653c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek StmtMap[stmt] = P; 32663c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 32673c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek switch (stmt->getStmtClass()) { 32683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::DeclStmtClass: 32693c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P; 32703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 32713c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::IfStmtClass: { 32723c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable(); 32733c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 32743c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 32753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 32763c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 32773c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::ForStmtClass: { 32783c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable(); 32793c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 32803c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 32813c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 32823c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 32833c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::WhileStmtClass: { 32843c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 32853c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<WhileStmt>(stmt)->getConditionVariable(); 32863c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 32873c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 32883c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 32893c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 32903c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::SwitchStmtClass: { 32913c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 32923c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<SwitchStmt>(stmt)->getConditionVariable(); 32933c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 32943c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 32953c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 32963c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 32973c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::CXXCatchStmtClass: { 32983c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 32993c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<CXXCatchStmt>(stmt)->getExceptionDecl(); 33003c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 33013c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 33023c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 33033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 33043c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek default: 33053c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 33061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 33071cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 330842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 3309b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 3310fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 33113c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 33126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 331342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 33146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3315e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 33160a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setBlockID(signed i) { currentBlock = i; } 33170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setStmtID(unsigned i) { currentStmt = i; } 33186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33199c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual bool handledStmt(Stmt *S, raw_ostream &OS) { 33201cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 3321fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 332242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 332342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 33246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33250a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 33260a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek && I->second.second == currentStmt) { 332742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 33283fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 33296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33303fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 33311c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 333242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 33331cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 33349c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool handleDecl(const Decl *D, raw_ostream &OS) { 33351cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 33361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 33371cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 33381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 33391cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 33400a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 33410a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek && I->second.second == currentStmt) { 33421cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 33431cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 33441cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 33451cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 33461cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 33471cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 334842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 3349e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3350e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 3351e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 3352e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 3353ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 33546fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 33556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33569c378f705405d37f49795d5e915989de774fe11fTed Kremenek raw_ostream &OS; 335742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 3358d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 3359d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 33609c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper, 3361e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 3362d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 33636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33649c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIfStmt(IfStmt *I) { 3365d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 3366d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 3367d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 33686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3369d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 33709c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitStmt(Stmt *Terminator) { 33716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 33726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 33736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33749c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitForStmt(ForStmt *F) { 3375d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 33763fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 33773fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3378535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 33799c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = F->getCond()) 33803fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3381535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 33823fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 33833fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3384a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 3385d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 33866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33879c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitWhileStmt(WhileStmt *W) { 3388d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 33899c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = W->getCond()) 33903fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3391d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 33926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33939c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitDoStmt(DoStmt *D) { 3394d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 33959c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) 33963fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 33979da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 33986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33999c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitSwitchStmt(SwitchStmt *Terminator) { 34009da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 3401d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 34029da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 34036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34049c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitCXXTryStmt(CXXTryStmt *CS) { 34055d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 34065d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 34075d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 340856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { 3409d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 34106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 3411805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 34126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34139c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitChooseExpr(ChooseExpr *C) { 3414aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 3415d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 3416a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 3417aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 34186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34199c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt *I) { 34201c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 3421d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 34221c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 34236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3424805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 3425805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 3426805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 3427805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3428805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 34296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3430d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 34316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3432805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 34332de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 3434a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 3435805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 34362de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 3437a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 3438805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3439805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 3440b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid logical operator."); 34416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3442805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 34436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34449c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitExpr(Expr *E) { 3445d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 34466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3447d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3448e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3449e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 34505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper, 3451079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 34523c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *CS = E.getAs<CFGStmt>()) { 3453f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *S = CS->getStmt(); 34541cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34551cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 34561cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 3458f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) { 3459f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const CompoundStmt *Sub = SE->getSubStmt(); 34601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34617502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall if (Sub->children()) { 34621cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 34631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 34641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 34651cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 34661cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 34671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 34681cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 3469f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 34701cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 34711cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 34721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 34731cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 34741cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 34751cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 34761c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 34771c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 34781cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 34796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34801cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 348136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (OperatorCall)"; 3482893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 3483893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (isa<CXXBindTemporaryExpr>(S)) { 348436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (BindTemporary)"; 34856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 34863b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) { 34873b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek OS << " (CXXConstructExpr, " << CCE->getType().getAsString() << ")"; 34883b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek } 3489893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) { 3490893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek OS << " (" << CE->getStmtClassName() << ", " 3491893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << CE->getCastKindName() 3492893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ", " << CE->getType().getAsString() 3493893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ")"; 3494893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 34956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34961cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 34971cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 34981cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 34994e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 35003c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGInitializer *IE = E.getAs<CFGInitializer>()) { 35013c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXCtorInitializer *I = IE->getInitializer(); 35021cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 35031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 350400eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet else OS << I->getAnyMember()->getName(); 35056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 35079c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *IE = I->getInit()) 35081cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 35091cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 35101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35111cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 35121cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 35131cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 35141cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35153c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGAutomaticObjDtor *DE = E.getAs<CFGAutomaticObjDtor>()){ 35169c378f705405d37f49795d5e915989de774fe11fTed Kremenek const VarDecl *VD = DE->getVarDecl(); 35171cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 35181cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3519b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski const Type* T = VD->getType().getTypePtr(); 35201cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 35211cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 3522b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski else if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 3523b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski T = ET; 35241cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35251cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 35261cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 35277c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 35283c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGBaseDtor *BE = E.getAs<CFGBaseDtor>()) { 35293c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); 35307c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 35314e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 35327c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 35333c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) { 35343c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const FieldDecl *FD = ME->getFieldDecl(); 35358c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 35368c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski const Type *T = FD->getType().getTypePtr(); 35378c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 35388c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski T = ET; 35398c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 35407c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 35418c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; 35424e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 35438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 35443c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGTemporaryDtor *TE = E.getAs<CFGTemporaryDtor>()) { 35453c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); 35468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()"; 35478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << " (Temporary object destructor)\n"; 35481cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 354981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 35506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35519c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void print_block(raw_ostream &OS, const CFG* cfg, 35529c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock &B, 3553682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek StmtPrinterHelper* Helper, bool print_edges, 3554682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) { 35556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3556682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (Helper) 3557682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek Helper->setBlockID(B.getBlockID()); 35586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35597dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 3560682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3561682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::YELLOW, true); 3562682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3563682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n [B" << B.getBlockID(); 35646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 356542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 3566682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (ENTRY)]\n"; 356742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 3568682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (EXIT)]\n"; 356942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 3570682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (INDIRECT GOTO DISPATCH)]\n"; 357142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 3572682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "]\n"; 3573682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3574682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3575682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 35766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35779cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 35789c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) { 357942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 358042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3581682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 35826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35839c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (LabelStmt *L = dyn_cast<LabelStmt>(Label)) 35849cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 35859c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) { 35869cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 3587e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 3588e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 35899cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 35909cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 3591e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 3592e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 35939cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 3594079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 35959cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 3596079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 35975d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 3598a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 3599a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 3600a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 3601a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 3602a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 36035d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 36045d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 36055d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 3606b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid label statement in CFGBlock."); 36076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36089cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 36099cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 36106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3611fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 3612fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 36136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 361442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 361542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 36166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36179cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 361842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3619682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 36206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3621a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 36226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 362342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 362442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 36256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3626682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_elem(OS, Helper, *I); 3627fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 36286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36299cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 363042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 3631682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3632682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::GREEN); 36336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3634682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " T: "; 36356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 363642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 36376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3638e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, Helper, 3639e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 36404ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt())); 3641a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 3642682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3643682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3644682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3645fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 36466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36479cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 36489cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 3649682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.pred_empty()) { 3650682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::BLUE; 3651682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3652682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3653682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Preds " ; 3654682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3655682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3656682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.pred_size() << "):"; 3657682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3658682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3659682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3660682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3661682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3662682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 3663682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 366442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3665682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (i == 8 || (i-8) == 0) 3666682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 36676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3668682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3669682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3670682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3671682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3672682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 36736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3674682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 36759cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 36766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36779cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 3678682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.succ_empty()) { 3679682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::MAGENTA; 3680682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3681682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3682682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Succs "; 3683682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3684682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3685682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.succ_size() << "):"; 3686682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3687682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3688682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3689682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3690682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3691682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 3692682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 3693682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3694682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (i == 8 || (i-8) % 10 == 0) 3695682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 3696682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3697682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (*I) 3698682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3699682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek else 3700682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " NULL"; 3701682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3702682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3703682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3704682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3705682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3706fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 3707fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 37086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 370942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 371042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 371142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 3712682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::dump(const LangOptions &LO, bool ShowColors) const { 3713682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), LO, ShowColors); 3714682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek} 371542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 371642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 3717682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const { 3718e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 37196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 372042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 3721682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getEntry(), &Helper, true, ShowColors); 37226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 372342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 372442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 372542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 3726ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 372742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 37286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3729682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, **I, &Helper, true, ShowColors); 373042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 37316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 373242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 3733682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getExit(), &Helper, true, ShowColors); 3734682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3735d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 37366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 373742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 373842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 3739682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO, 3740682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) const { 3741682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), cfg, LO, ShowColors); 3742e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 374342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 374442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 374542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 37469c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBlock::print(raw_ostream &OS, const CFG* cfg, 3747682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const LangOptions &LO, bool ShowColors) const { 3748e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 3749682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, cfg, *this, &Helper, true, ShowColors); 3750682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3751026473c2175424a039f51ca8949937268721b965Ted Kremenek} 37527dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3753a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 37545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid CFGBlock::printTerminator(raw_ostream &OS, 37556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 3756e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 37574ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt())); 3758a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 3759a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 37609c378f705405d37f49795d5e915989de774fe11fTed KremenekStmt *CFGBlock::getTerminatorCondition() { 37614ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski Stmt *Terminator = this->Terminator; 3762411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 3763411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 37646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37659c378f705405d37f49795d5e915989de774fe11fTed Kremenek Expr *E = NULL; 37666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3767411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 3768411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 3769411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3771411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 3772411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 3773411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3775411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 3776411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 3777411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3779411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 3780411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 3781411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3783411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 3784411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 3785411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3787411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 3788411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 3789411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3791411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 3792411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 3793411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3795411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 3796411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 3797411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 37986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 379956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 380056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall E = cast<BinaryConditionalOperator>(Terminator)->getCond(); 380156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall break; 380256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 3803411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 3804411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 3805411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 38066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3807411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 3808411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 3809390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 38106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3811390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 38126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 3813411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 38146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3815411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 3816411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 3817411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 38187dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 38197dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 38207dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 38217dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 382242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 382342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 38246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 382542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 382642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3827e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 382842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 3829e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 383042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 383142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 383242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 383342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 383442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 383542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 38367dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 38377dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 38387dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 3839006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 3840006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 3841006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 38429c378f705405d37f49795d5e915989de774fe11fTed Kremenek static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) { 38437dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3844bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 3845a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 3846a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 3847682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(Out,Graph, *Node, GraphHelper, false, false); 3848a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 38497dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 38507dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 38517dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 38527dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 38537dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 38547dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 38557dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 38567dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 38577dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 38586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38597dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 3860bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 3861bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 3862bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 38637dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 38647dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 38657dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 3866