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 15b2c60b04a597cc5ba4154837cf8e0a155a376fd7Argyrios Kyrtzidis#include "llvm/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" 21534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith#include "clang/Basic/AttrKinds.h" 227dba8607e59096014b7139ff20ef00870041d518Ted Kremenek#include "llvm/Support/GraphWriter.h" 236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Allocator.h" 246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Format.h" 256cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/DenseMap.h" 266cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/SmallPtrSet.h" 270ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek#include "llvm/ADT/OwningPtr.h" 2883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 29fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenekusing namespace clang; 30fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 31fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremeneknamespace { 32fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 339c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic SourceLocation GetEndLoc(Decl *D) { 349c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(D)) 359c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *Ex = VD->getInit()) 36c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek return Ex->getSourceRange().getEnd(); 376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return D->getLocation(); 38c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek} 39ad5a894df1841698c824381b414630799adc26caTed Kremenek 403179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenekclass CFGBuilder; 413179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 4294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// The CFG builder uses a recursive algorithm to build the CFG. When 4394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// we process an expression, sometimes we know that we must add the 4494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// subexpressions as block-level expressions. For example: 4594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// exp1 || exp2 4794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// When processing the '||' expression, we know that exp1 and exp2 4994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// need to be added as block-level expressions, even though they 5094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// might not normally need to be. AddStmtChoice records this 5194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then 5294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// the builder has an option not to add a subexpression as a 5394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// block-level expression. 5494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 55852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekclass AddStmtChoice { 56852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekpublic: 57892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; 585ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 5994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} 605ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 613179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek bool alwaysAdd(CFGBuilder &builder, 623179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek const Stmt *stmt) const; 6394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 6494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// Return a copy of this object, except with the 'always-add' bit 6594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// set as specified. 6694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { 673179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); 6894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan } 6994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 70852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekprivate: 7194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan Kind kind; 72852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek}; 736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 74f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope - Node in tree of local scopes created for C++ implicit 75f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// destructor calls generation. It contains list of automatic variables 76f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// declared in the scope and link to position in previous scope this scope 77f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// began in. 78f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 79f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// The process of creating local scopes is as follows: 80f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null), 81f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Before processing statements in scope (e.g. CompoundStmt) create 82f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope object using CFGBuilder::ScopePos as link to previous scope 83f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// and set CFGBuilder::ScopePos to the end of new scope, 8435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points 85f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// at this VarDecl, 86f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every normal (without jump) end of scope add to CFGBlock destructors 87f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// for objects in the current scope, 88f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every jump add to CFGBlock destructors for objects 89f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// between CFGBuilder::ScopePos and local scope position saved for jump 90f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// target. Thanks to C++ restrictions on goto jumps we can be sure that 91f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// jump target position will be on the path to root from CFGBuilder::ScopePos 92f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// (adding any variable that doesn't need constructor to be called to 93f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope can break this assumption), 94f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 95f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiclass LocalScope { 96f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 97fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek typedef BumpVector<VarDecl*> AutomaticVarsTy; 98f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 99f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// const_iterator - Iterates local scope backwards and jumps to previous 10035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski /// scope on reaching the beginning of currently iterated scope. 101f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski class const_iterator { 102f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const LocalScope* Scope; 103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 104f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// VarIter is guaranteed to be greater then 0 for every valid iterator. 105f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Invalid iterator (with null Scope) has VarIter equal to 0. 106f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski unsigned VarIter; 107f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 108f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski public: 109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create invalid iterator. Dereferencing invalid iterator is not allowed. 110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Incrementing invalid iterator is allowed and will result in invalid 111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// iterator. 112f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator() 113f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(NULL), VarIter(0) {} 114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 115f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create valid iterator. In case when S.Prev is an invalid iterator and 116f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// I is equal to 0, this will create invalid iterator. 117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator(const LocalScope& S, unsigned I) 118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(&S), VarIter(I) { 119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Iterator to "end" of scope is not allowed. Handle it by going up 120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // in scopes tree possibly up to invalid iterator in the root. 121f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0 && Scope) 122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 124f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1259c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *const* operator->() const { 126f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (Scope && "Dereferencing invalid iterator is not allowed"); 127f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 128f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return &Scope->Vars[VarIter - 1]; 129f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1309c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *operator*() const { 131f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this->operator->(); 132f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 133f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1349c378f705405d37f49795d5e915989de774fe11fTed Kremenek const_iterator &operator++() { 135f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (!Scope) 136f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 137f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 138f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 139f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski --VarIter; 140f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0) 141f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 142f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 143f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 14435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator operator++(int) { 14535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator P = *this; 14635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski ++*this; 14735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return P; 14835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 149f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1509c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator==(const const_iterator &rhs) const { 151f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return Scope == rhs.Scope && VarIter == rhs.VarIter; 152f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1539c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator!=(const const_iterator &rhs) const { 154f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return !(*this == rhs); 155f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 15635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 15735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski operator bool() const { 15835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return *this != const_iterator(); 15935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 16035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 16135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int distance(const_iterator L); 162f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski }; 163f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 164f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski friend class const_iterator; 165f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 166f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiprivate: 167fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx; 168fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek 169f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Automatic variables in order of declaration. 170f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AutomaticVarsTy Vars; 171f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Iterator to variable in previous scope that was declared just before 172f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// begin of this scope. 173f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator Prev; 174f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 175f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 176f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Constructs empty scope linked to previous scope in specified place. 177fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek LocalScope(BumpVectorContext &ctx, const_iterator P) 178fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek : ctx(ctx), Vars(ctx, 4), Prev(P) {} 179f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 180f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Begin of scope in direction of CFG building (backwards). 181f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator begin() const { return const_iterator(*this, Vars.size()); } 18235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 1839c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addVar(VarDecl *VD) { 184fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Vars.push_back(VD, ctx); 18535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 186f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 187f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 18835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// distance - Calculates distance from this to L. L must be reachable from this 18935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. 19035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// number of scopes between this and L. 19135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderskiint LocalScope::const_iterator::distance(LocalScope::const_iterator L) { 19235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int D = 0; 19335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator F = *this; 19435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski while (F.Scope != L.Scope) { 1955290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek assert (F != const_iterator() 1965290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek && "L iterator is not reachable from F iterator."); 19735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter; 19835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski F = F.Scope->Prev; 19935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 20035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter - L.VarIter; 20135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return D; 20235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski} 20335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 20435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// BlockScopePosPair - Structure for specifying position in CFG during its 20535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// build process. It consists of CFGBlock that specifies position in CFG graph 20635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// and LocalScope::const_iterator that specifies position in LocalScope graph. 207f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskistruct BlockScopePosPair { 2089ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BlockScopePosPair() : block(0) {} 2099c378f705405d37f49795d5e915989de774fe11fTed Kremenek BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos) 2109ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek : block(b), scopePosition(scopePos) {} 211f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2129ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek CFGBlock *block; 2139ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek LocalScope::const_iterator scopePosition; 214f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 215f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 216e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// TryResult - a class representing a variant over the values 217e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, 218e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// and is used by the CFGBuilder to decide if a branch condition 219e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// can be decided up front during CFG construction. 220e71f3d587844110d836c82250830b27b1651afdbTed Kremenekclass TryResult { 221e71f3d587844110d836c82250830b27b1651afdbTed Kremenek int X; 222e71f3d587844110d836c82250830b27b1651afdbTed Kremenekpublic: 223e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 224e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult() : X(-1) {} 225e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 226e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isTrue() const { return X == 1; } 227e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isFalse() const { return X == 0; } 228e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isKnown() const { return X >= 0; } 229e71f3d587844110d836c82250830b27b1651afdbTed Kremenek void negate() { 230e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(isKnown()); 231e71f3d587844110d836c82250830b27b1651afdbTed Kremenek X ^= 0x1; 232e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 233e71f3d587844110d836c82250830b27b1651afdbTed Kremenek}; 234e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 235a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 236fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 237fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 238fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 239fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 240fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 241fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 242fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 243fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 2446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 2456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 2466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 2476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 248c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 249ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 250f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpTarget; 251f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpSource; 252f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 253e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 2546f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CFG> cfg; 255ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 2569c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Block; 2579c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Succ; 258f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget ContinueJumpTarget; 259f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget BreakJumpTarget; 2609c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchTerminatedBlock; 2619c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *DefaultCaseBlock; 2629c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TryTerminatedBlock; 263e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 264f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Current position in local scope. 265f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 266f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 267f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // LabelMap records the mapping from Label expressions to their jump targets. 268ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy; 2690cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 2706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 2726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 273f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef std::vector<JumpSource> BackpatchBlocksTy; 2740cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 2756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 277ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy; 27819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 2796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28049b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu bool badCFG; 281b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &BuildOpts; 282e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 283e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // State to track for building switch statements. 284e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool switchExclusivelyCovered; 2850498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult *switchCond; 2860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 2870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; 288a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek const Stmt *lastLookup; 28949b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu 2908c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Caches boolean evaluations of expressions to avoid multiple re-evaluations 2918c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // during construction of branches for chained logical operators. 2926955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy; 2936955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy CachedBoolEvals; 2948c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 2956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 296b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek explicit CFGBuilder(ASTContext *astContext, 297b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &buildOpts) 298b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek : Context(astContext), cfg(new CFG()), // crew a new CFG 299b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek Block(NULL), Succ(NULL), 300b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 301b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), 3020d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek switchExclusivelyCovered(false), switchCond(0), 303a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry(0), lastLookup(0) {} 3046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 305d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 306b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement); 3076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3080d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool alwaysAdd(const Stmt *stmt); 3090d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 3114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 312852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 313852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 3144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 3157ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 3164765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, 3178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc); 3187ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 3197ea2136685403045f91b3a8b83e34c51ac0e082eTed Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 320ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); 321a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 322a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 32381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); 324a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 325a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc); 32681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 32781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc); 328852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 3294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 330852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 3313fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 33256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, 33356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AddStmtChoice asc); 3343fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 3354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 3369c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitDeclSubExpr(DeclStmt *DS); 3373fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 3383fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 33955331da3211151aa67277aa095b7d301342200d4Ted Kremenek CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc); 3403fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 3419c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt *G); 3424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 343a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); 3444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 3454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 34683748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *VisitLambdaExpr(LambdaExpr *L); 347115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 3484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 3498e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); 3504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 3524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 3534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 3549c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitReturnStmt(ReturnStmt *R); 3554b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); 356f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 357f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc); 358852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 3594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 36099cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); 3614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 3624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 363852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 364852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 3659c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitChildren(Stmt *S); 36655331da3211151aa67277aa095b7d301342200d4Ted Kremenek CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); 367cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 3688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Visitors to walk an AST and generate destructors of temporaries in 3698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // full expression. 3708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false); 3718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E); 3728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); 3738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, 3748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 37556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock * 37656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E, 37756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool BindToTemporary); 3788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 379274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 3809c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *NYS() { 3814102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 3824102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 3834102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 3846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 3864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 387dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *createNoReturnBlock(); 388d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 389df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 390df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 391852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 392cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt CFGBlock *addInitializer(CXXCtorInitializer *I); 3936a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 3949c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S); 3957c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 396239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 397239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 398239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 399239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4009c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeForStmt(Stmt *S); 4019c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, LocalScope* Scope = NULL); 4029c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = NULL); 403239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4049c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeAndDtors(Stmt *S); 405ad5a894df1841698c824381b414630799adc26caTed Kremenek 406239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 407d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek void appendStmt(CFGBlock *B, const Stmt *S) { 40874fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek if (alwaysAdd(S) && cachedEntry) 4090d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry->second = B; 4100d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 411ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose // All block-level expressions should have already been IgnoreParens()ed. 412ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); 413d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); 414ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 415cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { 41682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 41782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 4187c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 4197c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 4207c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4217c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 4227c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 4237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { 4258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); 4268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 427c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) { 428c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext()); 429c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 430ad5a894df1841698c824381b414630799adc26caTed Kremenek 4319c378f705405d37f49795d5e915989de774fe11fTed Kremenek void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 43253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 43353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 4340a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void addSuccessor(CFGBlock *B, CFGBlock *S) { 435ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 436ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 4371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 438e71f3d587844110d836c82250830b27b1651afdbTed Kremenek /// Try and evaluate an expression to an integer constant. 439e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { 440e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 441e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return false; 442e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return !S->isTypeDependent() && 443f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek !S->isValueDependent() && 44451f4708c00110940ca3f337961915f2ca1668375Richard Smith S->EvaluateAsRValue(outResult, *Context); 445e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 4461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4470a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 44800998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 4490a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult tryEvaluateBool(Expr *S) { 45085df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (!BuildOpts.PruneTriviallyFalseEdges || 4518c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis S->isTypeDependent() || S->isValueDependent()) 452e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return TryResult(); 4538c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4548c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) { 4558c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 4568c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Check the cache first. 4576955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S); 4586955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi if (I != CachedBoolEvals.end()) 4598c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return I->second; // already in map; 4609260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi 4619260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi // Retrieve result at first, or the map might be updated. 4629260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi TryResult Result = evaluateAsBooleanConditionNoCache(S); 4639260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi CachedBoolEvals[S] = Result; // update or insert 4649260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi return Result; 4658c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4668c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4678c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4688c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return evaluateAsBooleanConditionNoCache(S); 4698c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4708c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4718c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis /// \brief Evaluate as boolean \param E without using the cache. 4728c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult evaluateAsBooleanConditionNoCache(Expr *E) { 4738c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) { 4748c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 4758c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult LHS = tryEvaluateBool(Bop->getLHS()); 4768c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isKnown()) { 4778c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We were able to evaluate the LHS, see if we can get away with not 4788c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 4798c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 4808c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue(); 4818c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4828c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 4838c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 4848c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->getOpcode() == BO_LOr) 4858c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() || RHS.isTrue(); 4868c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis else 4878c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() && RHS.isTrue(); 4888c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4898c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } else { 4908c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 4918c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 4928c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We can't evaluate the LHS; however, sometimes the result 4938c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. 4948c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 4958c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return RHS.isTrue(); 4968c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4978c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4988c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4998c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 5008c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5018c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5028c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5038c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis bool Result; 5048c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (E->EvaluateAsBooleanCondition(Result, *Context)) 5058c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return Result; 5068c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5078c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 50800998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 509e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 510d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 5116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5120d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekinline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, 5130d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const Stmt *stmt) const { 5140d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return builder.alwaysAdd(stmt) || kind == AlwaysAdd; 5150d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek} 516a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 5170d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekbool CFGBuilder::alwaysAdd(const Stmt *stmt) { 51874fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek bool shouldAdd = BuildOpts.alwaysAdd(stmt); 51974fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek 5200d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!BuildOpts.forcedBlkExprs) 52174fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 522a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 523a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (lastLookup == stmt) { 524a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (cachedEntry) { 525a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry->first == stmt); 526a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek return true; 527a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 52874fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 529a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 5300d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 531a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek lastLookup = stmt; 532a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 533a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // Perform the lookup! 5340d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; 5350d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 536a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (!fb) { 537a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // No need to update 'cachedEntry', since it will always be null. 538a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry == 0); 53974fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 540a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 5410d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 5420d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); 543a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (itr == fb->end()) { 544a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry = 0; 54574fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 546a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 547a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 5480d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry = &*itr; 5490d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return true; 5503179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek} 5513179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 552898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 553898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 554f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCallstatic const VariableArrayType *FindVA(const Type *t) { 555f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { 556f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) 557610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 558610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 5596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 560610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 561610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 5626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 563610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 564610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 5656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 5676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 5686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 5696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 5706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 5719c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { 5720ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 5734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 5744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 575d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 5766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 5776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 5786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 57949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 580ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 58149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 5826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5837c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 5847c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 5857c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 5867c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 587d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 5881b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 5891b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 5901b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 5911b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 5921b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 59382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 594b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 59582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 59682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 59782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 59882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 59982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 60082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 601b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 6026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 60382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 60482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 60582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6061b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 6071b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 6081b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 6091b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 610c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 6119c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = I->block; 6129c378f705405d37f49795d5e915989de774fe11fTed Kremenek GotoStmt *G = cast<GotoStmt>(B->getTerminator()); 6131b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 6146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6151b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 6161b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 6171b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 618d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 619f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 6209ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, 6219ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek JT.scopePosition); 6229ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, JT.block); 6231b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 6246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6251b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 6269c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (CFGBlock *B = cfg->getIndirectGotoBlock()) 6271b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 6281b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 6291b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6301b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 6311b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 6321b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6331b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 6341b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 6351b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 6361b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6379ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, LI->second.block); 638c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 6396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 641322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 6426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6431b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 644d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 6456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 646d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 647d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 6489c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::createBlock(bool add_successor) { 6499c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = cfg->createBlock(); 6504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 6510a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(B, Succ); 652d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 653d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 6546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 655dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// createNoReturnBlock - Used to create a block is a 'noreturn' point in the 656dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// CFG. It is *not* connected to the current (global) successor, and instead 657dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// directly tied to the exit block in order to be reachable. 658dba3fb5413437dc613734fa4ffac892b11a37d25Chandler CarruthCFGBlock *CFGBuilder::createNoReturnBlock() { 659dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *B = createBlock(false); 66083754162f698a5dafad93fb89be0953651a604d0Chandler Carruth B->setHasNoReturnElement(); 661dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth addSuccessor(B, &cfg->getExit()); 662dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth return B; 663dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth} 664dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 66582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 666cbb67480094b3bcb5b715acd827cbad55e2a204cSean HuntCFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { 66782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 66882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 66982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 6718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 67282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 6748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 6758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Expr *Init = I->getInit(); 6768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 67700eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet if (FieldDecl *FD = I->getAnyMember()) 6788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = FD->getType()->isReferenceType(); 6794765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 68082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 6828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 6834765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 6848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 6858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 68682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 6878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 6888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 6898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendInitializer(Block, I); 6908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 6918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 692892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek if (HasTemporaries) { 6938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 6948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 695892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 696892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek } 697892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(Init); 6988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 6998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 70082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 70182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 70282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7032d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// \brief Retrieve the type of the temporary object whose lifetime was 7042d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// extended by a local reference with the given initializer. 7052d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregorstatic QualType getReferenceInitTemporaryType(ASTContext &Context, 7062d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor const Expr *Init) { 7072d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (true) { 7082d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip parentheses. 7092d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = Init->IgnoreParens(); 7102d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7112d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through cleanups. 7122d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) { 7132d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = EWC->getSubExpr(); 7142d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7152d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7162d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7172d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through the temporary-materialization expression. 7182d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MaterializeTemporaryExpr *MTE 7192d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor = dyn_cast<MaterializeTemporaryExpr>(Init)) { 7202d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = MTE->GetTemporaryExpr(); 7212d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7222d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7232d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7242d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip derived-to-base and no-op casts. 7252d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const CastExpr *CE = dyn_cast<CastExpr>(Init)) { 7262d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if ((CE->getCastKind() == CK_DerivedToBase || 7272d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_UncheckedDerivedToBase || 7282d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_NoOp) && 7292d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init->getType()->isRecordType()) { 7302d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = CE->getSubExpr(); 7312d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7322d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7332d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7342d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7352d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip member accesses into rvalues. 7362d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) { 7372d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (!ME->isArrow() && ME->getBase()->isRValue()) { 7382d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = ME->getBase(); 7392d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7402d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7412d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7422d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7432d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor break; 7442d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7452d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7462d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor return Init->getType(); 7472d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor} 7482d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 749239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 750239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 751239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 7526a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 7539c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S) { 754239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 7556a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 7566a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 757239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 7586a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 759239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 760c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // We need to append the destructors in reverse order, but any one of them 761c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // may be a no-return destructor which changes the CFG. As a result, buffer 762c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // this sequence up and replay them in reverse order when appending onto the 763c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // CFGBlock(s). 764c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth SmallVector<VarDecl*, 10> Decls; 765c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.reserve(B.distance(E)); 766c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 767c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.push_back(*I); 768c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 769c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(), 770c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth E = Decls.rend(); 771c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth I != E; ++I) { 772c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If this destructor is marked as a no-return destructor, we need to 773c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // create a new block for the destructor which does not have as a successor 774c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far: control won't flow out of this block. 7752d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor QualType Ty; 7762d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if ((*I)->getType()->isReferenceType()) { 7772d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit()); 7782d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } else { 7792d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Ty = Context->getBaseElementType((*I)->getType()); 7802d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7812d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 782c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); 78323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) 784dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 785dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 786c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 787c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 788c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth appendAutomaticObjDtor(Block, *I, S); 789c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 790239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 791239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 7927c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 7937c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 7947c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 7957c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 7967c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 7977c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 7987c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 7997c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 8007c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 8017c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 8027c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 8037c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 8047c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 8057c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 8067c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8077c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8087c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8097c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 8107c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 8117c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 81223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!BI->isVirtual()) { 81323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 81423661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 81523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie autoCreateBlock(); 81623661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie appendBaseDtor(Block, BI); 81723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 81823661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 8197c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8207c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8217c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 8227c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 8237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 8248c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski // Check for constant size array. Set type to array element type. 8258c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QualType QT = FI->getType(); 8268c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 8278c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (AT->getSize() == 0) 8288c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski continue; 8298c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QT = AT->getElementType(); 8308c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski } 8318c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 8328c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 8337c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 8347c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 8357c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendMemberDtor(Block, *FI); 8367c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8377c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8387c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 8397c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 840239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 841239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 842239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 843239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 844fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); 845fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Scope = alloc.Allocate<LocalScope>(); 846fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx(alloc); 847fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek new (Scope) LocalScope(ctx, ScopePos); 848239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 849239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 850239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 851239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 852239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 85302acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 8549c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeForStmt(Stmt *S) { 855239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 85602acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 85702acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 85802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 859239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 860239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 861ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { 862239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 863239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 864a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth Stmt *SI = (*BI)->stripLabelLikeStatements(); 865ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) 866239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 867239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 86802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 869239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 870239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 871239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 872239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 873a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements())) 874b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 875239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 876239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 877239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 878239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 8799c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS, 880b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 881239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 882239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 883239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 884239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 885239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 8869c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(*DI)) 887239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 888239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 889239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 890239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 891239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 892239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 893239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 894239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 8959c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, 896b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 897239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 898239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 899239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 900239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 901239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 902239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 903239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 904239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 905239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 906239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 907239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 908239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 909239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 910239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 9112d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (QT.getTypePtr()->isReferenceType()) { 91203e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor if (!VD->extendsLifetimeOfTemporary()) 913239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 9142d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 9152d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor QT = getReferenceInitTemporaryType(*Context, VD->getInit()); 916239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 917239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 918b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check for constant size array. Set type to array element type. 9192d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 920b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (AT->getSize() == 0) 921b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski return Scope; 922b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski QT = AT->getElementType(); 923b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski } 9244e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 925b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 9269c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 92723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 9284e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 9294e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 9304e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 9314e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 9324e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 933239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 934239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 935239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 936239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 937239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 9389c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeAndDtors(Stmt *S) { 939239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 940239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 941239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 942239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 94302acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 944239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 945239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 946239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 94753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 94853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 94953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 95053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 95153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 952c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// FIXME: This mechanism for adding automatic destructors doesn't handle 953c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// no-return destructors properly. 9549c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 95553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 956c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth BumpVectorContext &C = cfg->getBumpVectorContext(); 957c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth CFGBlock::iterator InsertPos 958c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); 959c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 960c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, 961c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Blk->getTerminator()); 96253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 96353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 9644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 9656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 9666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 9679c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 968f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 969f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 970f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 971f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 972ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 973ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (Expr *E = dyn_cast<Expr>(S)) 974ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose S = E->IgnoreParens(); 975ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 9764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 9774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 978852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 9794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 9804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 981852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 9821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 98356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 98456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); 98556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 9864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 987852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 9881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 99055331da3211151aa67277aa095b7d301342200d4Ted Kremenek return VisitNoRecurse(cast<Expr>(S), asc); 9914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 9924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 9934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 9941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 996a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 9971de85338543dd6228eb518185e385d94d377f4cbJohn McCall case Stmt::CXXMemberCallExprClass: 9989fcce65e7e1307b5b8da9be13e4092d6bb94dc1dRichard Smith case Stmt::UserDefinedLiteralClass: 999852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 10001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 10024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 10034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 1005852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 10061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 10084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 10091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 1011852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 10121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 10144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 10151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1016021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 1017021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 1018021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 10194765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall case Stmt::ExprWithCleanupsClass: 10204765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc); 102147e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 1022a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXBindTemporaryExprClass: 1023a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); 1024a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 102581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXConstructExprClass: 102681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); 102781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 1028a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXFunctionalCastExprClass: 1029a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); 1030a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 103181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXTemporaryObjectExprClass: 103281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); 103381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 1034021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 1035021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 1036ad5a894df1841698c824381b414630799adc26caTed Kremenek 1037021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 1038021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 1039ad5a894df1841698c824381b414630799adc26caTed Kremenek 1040ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith case Stmt::CXXForRangeStmtClass: 1041ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); 1042ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 10434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 10444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 10451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 10474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 10481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 10504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 10511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 10534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 10541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 10564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 10571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 10594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1061892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek case Stmt::ImplicitCastExprClass: 1062892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); 1063a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 10644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 10654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 10661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 10684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 10691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 107083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek case Stmt::LambdaExprClass: 107183748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return VisitLambdaExpr(cast<LambdaExpr>(S), asc); 107283748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 1073534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith case Stmt::AttributedStmtClass: 1074534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith return Visit(cast<AttributedStmt>(S)->getSubStmt(), asc); 1075534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith 1076115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 1077115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 1078115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 10796a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::NullStmtClass: 10806a9065a39ab15383082b914af28759da1652db18Ted Kremenek return Block; 10816a9065a39ab15383082b914af28759da1652db18Ted Kremenek 10824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 10831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 10841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10858e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek case Stmt::ObjCAutoreleasePoolStmtClass: 10868e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S)); 10878e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 10884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 10894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 10901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 10924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 10931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 10954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 10961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 10984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 10991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11006a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::OpaqueValueExprClass: 11014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11034b9c2d235fb9449e249d74f48ecfec601650de93John McCall case Stmt::PseudoObjectExprClass: 11044b9c2d235fb9449e249d74f48ecfec601650de93John McCall return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S)); 11054b9c2d235fb9449e249d74f48ecfec601650de93John McCall 11064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 11074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 11081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1109f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne case Stmt::UnaryExprOrTypeTraitExprClass: 1110f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), 1111f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne asc); 11121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 1114852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 11151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 11174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 11181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111999cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan case Stmt::UnaryOperatorClass: 112099cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan return VisitUnaryOperator(cast<UnaryOperator>(S), asc); 112199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 11224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 11234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 11244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 11254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1127852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 11283179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, S)) { 11294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1130247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 11316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 11321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 11344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 11379c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) { 1138534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith CFGBlock *lastBlock = Block; 11396b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek for (Stmt::child_range I = Terminator->children(); I; ++I) 11406b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (Stmt *child = *I) 11416b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (CFGBlock *b = Visit(child)) 11426b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek lastBlock = b; 11436b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek 11446b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek return lastBlock; 11454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1147852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 1148852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 11494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 11506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11513179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, A)) { 11524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1153247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, A); 11546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 11556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115999cae5b67b9711ca260e5b364a878a1a91183632Zhanyong WanCFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, 1160892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek AddStmtChoice asc) { 11613179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, U)) { 116299cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan autoCreateBlock(); 1163247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, U); 116499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan } 116599cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1166892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(U->getSubExpr(), AddStmtChoice()); 116799cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan} 116899cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1169852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 1170852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 11714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (B->isLogicalOp()) { // && or || 11729c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1173247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, B); 11741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1175d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 11764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 11771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the LHS 11799c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = createBlock(false); 11804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LHSBlock->setTerminator(B); 11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // create the block evaluating the RHS 11834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = ConfluenceBlock; 11844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = NULL; 11859c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = addStmt(B->getRHS()); 1186862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 1187862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek if (RHSBlock) { 1188d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1189862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek return 0; 119036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 1191862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // Create an empty block for cases where the RHS doesn't require 1192862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek // any explicit statements in the CFG. 1193862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek RHSBlock = createBlock(); 1194862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek } 11951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11968c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Generate the blocks for evaluating the LHS. 11978c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis Block = LHSBlock; 11988c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis CFGBlock *EntryLHSBlock = addStmt(B->getLHS()); 11998c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 120000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 12010a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(B->getLHS()); 12022de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr)) 1203941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek KnownVal.negate(); 120400998a068e50945118f334c98af05ed44d7c22a6Mike Stump 12054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now link the LHSBlock with RHSBlock. 12062de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall if (B->getOpcode() == BO_LOr) { 12070a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 12080a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 12091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else { 12102de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(B->getOpcode() == BO_LAnd); 12110a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 12120a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 121319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 12141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12158c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return EntryLHSBlock; 12161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 121736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 121836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->getOpcode() == BO_Comma) { // , 12196dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 1220247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 12214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 12224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 12236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 122436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 122536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->isAssignmentOp()) { 12263179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1227fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 1228247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1229fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 1230892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(B->getLHS()); 1231e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 1232fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 12331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12343179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1235e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 1236247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1237e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 1238e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 1239a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *RBlock = Visit(B->getRHS()); 1240a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *LBlock = Visit(B->getLHS()); 1241a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr 1242a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // containing a DoStmt, and the LHS doesn't create a new block, then we should 1243a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // return RBlock. Otherwise we'll incorrectly return NULL. 1244a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu return (LBlock ? LBlock : RBlock); 12454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 124755331da3211151aa67277aa095b7d301342200d4Ted KremenekCFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) { 12483179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 1249721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 1250247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 1251721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 1252721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 12534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1254cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 12554f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 12564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 12574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 1258d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1259d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 12624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 12634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 12641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 12664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 12679ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (BreakJumpTarget.block) { 12689ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B); 12699ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, BreakJumpTarget.block); 1270f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 12714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 12721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 12754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12778026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redlstatic bool CanThrow(Expr *E, ASTContext &Ctx) { 12784c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 12794c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 12804c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 12814c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 12824c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 1283ad5a894df1841698c824381b414630799adc26caTed Kremenek 12844c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 12854c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 12864c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 1287e6975e9b0985ad7f7ff9187e38d95bfe9ac4181bRichard Smith if (Proto->getExceptionSpecType() != EST_Uninstantiated && 1288e6975e9b0985ad7f7ff9187e38d95bfe9ac4181bRichard Smith Proto->isNothrow(Ctx)) 12894c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 12904c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 12914c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 12924c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 12934c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1294852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 12951de85338543dd6228eb518185e385d94d377f4cbJohn McCall // Compute the callee type. 12961de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType calleeType = C->getCallee()->getType(); 12971de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (calleeType == Context->BoundMemberTy) { 12981de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType boundType = Expr::findBoundMemberType(C->getCallee()); 12991de85338543dd6228eb518185e385d94d377f4cbJohn McCall 13001de85338543dd6228eb518185e385d94d377f4cbJohn McCall // We should only get a null bound type if processing a dependent 13011de85338543dd6228eb518185e385d94d377f4cbJohn McCall // CFG. Recover by assuming nothing. 13021de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (!boundType.isNull()) calleeType = boundType; 13032455636163fdd18581d7fdae816433f886d88213Mike Stump } 13042455636163fdd18581d7fdae816433f886d88213Mike Stump 13051de85338543dd6228eb518185e385d94d377f4cbJohn McCall // If this is a call to a no-return function, this stops the block here. 13061de85338543dd6228eb518185e385d94d377f4cbJohn McCall bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); 13071de85338543dd6228eb518185e385d94d377f4cbJohn McCall 13084c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 1309079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1310079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 13114e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (Context->getLangOpts().Exceptions) { 13126c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 13134c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 1314079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 1315079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1316079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 13172455636163fdd18581d7fdae816433f886d88213Mike Stump if (FD->hasAttr<NoReturnAttr>()) 13182455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 1319079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 13204c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 1321079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 13222455636163fdd18581d7fdae816433f886d88213Mike Stump 13238026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (!CanThrow(C->getCallee(), *Context)) 13244c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 13254c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 132694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan if (!NoReturn && !AddEHEdge) 132794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan return VisitStmt(C, asc.withAlwaysAdd(true)); 13281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1329079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1330079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1331d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1332079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1333079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 13341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1335dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (NoReturn) 1336dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 1337dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 1338dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createBlock(); 1339dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 1340247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 13412455636163fdd18581d7fdae816433f886d88213Mike Stump 13424c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1343079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1344079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 13450a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 1346079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 13470a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 1348079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 13491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13502455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1351d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1352d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1353852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1354852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 13559c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1356247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1357d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13583fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 13591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 136094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 13613fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 13623fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 13639c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd); 1364d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13653fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 13661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13673fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 13683fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 13699c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd); 1370d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 13713fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 13721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13733fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 137400998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 13750a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 13760a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 13770a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 13783fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 13791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 13803fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 13811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13839c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) { 1384fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 13859c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LastBlock = Block; 13864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 13874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 13884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1389334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1390334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1391334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1392334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 13931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1394e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1395e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 13961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1397079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 13984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 13994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 14001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 140156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallCFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, 1402852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 140356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); 140456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL); 140556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 1406f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1407f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 14089c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1409247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1410d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1411f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 14121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 141394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 1414115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1415f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1416f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1417f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1418f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1419f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1420f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 14219c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = 0; 142256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const Expr *trueExpr = C->getTrueExpr(); 142356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (trueExpr != opaqueValue) { 142456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); 1425d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1426f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1427f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1428f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 1429f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek else 1430f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek LHSBlock = ConfluenceBlock; 14311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1432f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1433f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 14349c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); 1435d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1436f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 14371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1438f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1439f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 14401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 144100998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 14420a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 1443f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 14440a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1445f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 144656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Expr *condExpr = C->getCond(); 1447d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1448f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (opaqueValue) { 1449f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Run the condition expression if it's not trivially expressed in 1450f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // terms of the opaque value (or if there is no opaque value). 1451f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (condExpr != opaqueValue) 1452f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addStmt(condExpr); 1453d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1454f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Before that, run the common subexpression if there was one. 1455f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // At least one of this or the above will be run. 1456f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(BCO->getCommon()); 1457f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek } 1458f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek 1459f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(condExpr); 1460f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1461f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 14624f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 1463bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // Check if the Decl is for an __label__. If so, elide it from the 1464bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // CFG entirely. 1465bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek if (isa<LabelDecl>(*DS->decl_begin())) 1466bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek return Block; 1467bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek 146829c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // This case also handles static_asserts. 14698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (DS->isSingleDecl()) 14708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitDeclSubExpr(DS); 14711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 14731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy. 14755f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<Decl*,10> BufTy; 14764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BufTy Buf(DS->decl_begin(), DS->decl_end()); 14771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) { 14794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 14804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 14814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 14821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 14844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 14854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 14864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 14871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 14884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 14891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 14918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = VisitDeclSubExpr(DSNew); 14924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 14931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 14954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 14961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 14988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski/// DeclStmts and initializers in them. 14999c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { 15008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert(DS->isSingleDecl() && "Can handle single declarations only."); 150129c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek Decl *D = DS->getSingleDecl(); 150229c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 150329c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek if (isa<StaticAssertDecl>(D)) { 150429c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // static_asserts aren't added to the CFG because they do not impact 150529c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // runtime semantics. 150629c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek return Block; 150729c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek } 150829c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 15098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 15101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!VD) { 15128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1513892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 15144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 15158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 15161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 15188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 15198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 15208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 15218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 15224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 15238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 15248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = VD->getType()->isReferenceType(); 15254765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 15268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 15278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors && HasTemporaries) { 15288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 15294765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 15308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 15318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 15328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 15338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 15348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1535892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 1536550f2234fc9218914c325041067052342dfce553Ted Kremenek 1537550f2234fc9218914c325041067052342dfce553Ted Kremenek // Keep track of the last non-null block, as 'Block' can be nulled out 1538550f2234fc9218914c325041067052342dfce553Ted Kremenek // if the initializer expression is something like a 'while' in a 1539550f2234fc9218914c325041067052342dfce553Ted Kremenek // statement-expression. 1540550f2234fc9218914c325041067052342dfce553Ted Kremenek CFGBlock *LastBlock = Block; 15411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 1543550f2234fc9218914c325041067052342dfce553Ted Kremenek if (HasTemporaries) { 15448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 15458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 1546550f2234fc9218914c325041067052342dfce553Ted Kremenek ExprWithCleanups *EC = cast<ExprWithCleanups>(Init); 1547550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(EC->getSubExpr())) 1548550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1549550f2234fc9218914c325041067052342dfce553Ted Kremenek } 1550550f2234fc9218914c325041067052342dfce553Ted Kremenek else { 1551550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(Init)) 1552550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1553550f2234fc9218914c325041067052342dfce553Ted Kremenek } 15544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 15551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 1557f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); 1558f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 15594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = addStmt(VA->getSizeExpr()); 15601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1561fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1562fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1563fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1564fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 1565550f2234fc9218914c325041067052342dfce553Ted Kremenek return Block ? Block : LastBlock; 1566d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1567fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 15689c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { 15696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 15706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 15716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 15726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 15736c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 15746c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 15756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 157604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 157704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 157804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 157904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 158004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 158104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 15829c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 158304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 158404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 158504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 158604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 158704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 1588fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // The block we were processing is now finished. Make it the successor 15896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 15906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1591d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1592d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15934e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1594c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 15956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1596b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 15979c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ElseBlock = Succ; 15986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 15999c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Else = I->getElse()) { 1600d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 16016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1602d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 16036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1604d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 160504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 160604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 160704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 160804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 160904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 161004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 16114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 16126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1613b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1614b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 16154e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1616d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16174e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 16184e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1619c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 16206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1621b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 16229c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ThenBlock; 1623d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 16249c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *Then = I->getThen(); 16256db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1626d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 16276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 162804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 162904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 163004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 163104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 163204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 163304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 16344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 16356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1636dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1637dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1638dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1639dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1640dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 16410a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ThenBlock, sv.get()); 16426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1643d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16444e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 16456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 16460cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1647d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 16486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1649d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 16506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1651d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1652d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 16536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 165400998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 16550a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(I->getCond()); 165600998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1657d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 16580a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 16590a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 16606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 16626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 16636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 166461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek Block = addStmt(I->getCond()); 1665ad5a894df1841698c824381b414630799adc26caTed Kremenek 166661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 166761dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 166861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 166961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 167061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 1671d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, I->getConditionVariableDeclStmt()); 167261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek addStmt(Init); 167361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 167461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1675ad5a894df1841698c824381b414630799adc26caTed Kremenek 167661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek return Block; 1677d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 16786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16809c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) { 16816c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1682d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 16836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 16846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 16856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 16866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1687d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1688d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1689d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 16906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1691d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 1692fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 16930a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 16946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 16966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1697852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1698d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 16990cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 17009c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { 1701d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 17024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 1703ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner CFGBlock *LabelBlock = Block; 17046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 17064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 17076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1708ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner assert(LabelMap.find(L->getDecl()) == LabelMap.end() && 1709ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner "label already in map"); 1710ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); 17116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 17136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 17146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 17156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 17169cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1717d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17184e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1721d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 17226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1723d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1724d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 17256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1726d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1727d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 172831dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 172983748e2f41ea0ac7c954946feb5da9ccc6ab8becTed KremenekCFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { 173083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *LastBlock = VisitNoRecurse(E, asc); 173183748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), 173283748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek et = E->capture_init_end(); it != et; ++it) { 173383748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Expr *Init = *it) { 173483748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *Tmp = Visit(Init); 173583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Tmp != 0) 173683748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek LastBlock = Tmp; 173783748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 173883748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 173983748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return LastBlock; 174083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek} 174183748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 17429c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { 17436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 17446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 17454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1746d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1747d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 17486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1750d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 17516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1752d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1753d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1754f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1755f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1756f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 17579ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, JT.scopePosition, G); 17589ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, JT.block); 1759f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1760d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 17616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1762d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1763d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 17649c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { 17659c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 17666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 176747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 176847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 176947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 177047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 177147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 177247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 177347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 17749c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Init = F->getInit()) 177547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1776f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1777f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 17789c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = F->getConditionVariable()) 177947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 178047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 178147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 178247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 178347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1784fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1785fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1786d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1787d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17884e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1789d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 17904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 17914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 17926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17933f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 17943f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 1795f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 179647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 17973f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 17986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 17996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 18006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 18019c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 18029c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 18036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 180449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 18056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(F); 18066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 18086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 18099c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = F->getCond()) { 181049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 181149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 18129ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (badCFG) 18139ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek return 0; 18148f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek assert(Block == EntryConditionBlock || 18158f3b834471b158d65d490e3458fa16ba659ec105Ted Kremenek (Block == 0 && EntryConditionBlock == Succ)); 181658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek 181758b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // If this block contains a condition variable, add both the condition 181858b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek // variable and initializer to the CFG. 181958b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (VarDecl *VD = F->getConditionVariable()) { 182058b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek if (Expr *Init = VD->getInit()) { 182158b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek autoCreateBlock(); 1822d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, F->getConditionVariableDeclStmt()); 182358b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek EntryConditionBlock = addStmt(Init); 182458b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek assert(Block == EntryConditionBlock); 182558b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 182658b87feeaedce7ef09c2931a39d82e5aea189f41Ted Kremenek } 1827ad5a894df1841698c824381b414630799adc26caTed Kremenek 18284e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 1829d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18304e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18314e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 183249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 1833d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 18346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 18356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 183649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 18376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 183800998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 1839941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek TryResult KnownVal(true); 18401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 184100998a068e50945118f334c98af05ed44d7c22a6Mike Stump if (F->getCond()) 18420a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek KnownVal = tryEvaluateBool(F->getCond()); 184300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1844d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1845d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 18466db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 18476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18483f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current values for Block, Succ, and continue targets. 1849f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 1850f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 18516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1852af603f742491dc4707138c0293d295171fdd51baTed Kremenek // Create a new block to contain the (bottom) of the loop body. 1853af603f742491dc4707138c0293d295171fdd51baTed Kremenek Block = NULL; 185447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 185547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 185647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 18576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18589c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInc()) { 18596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 18606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 18614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 18626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else { 18636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // No increment code. Create a special, empty, block that is used as the 18646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // target block for "looping back" to the start of the loop. 18653575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Succ == EntryConditionBlock); 186647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski Succ = Block ? Block : createBlock(); 1867e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 18686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18693575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 18703575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 18713575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1872d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18734e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18743575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 18753575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 18766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 187747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 18786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18793575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // The starting block for the loop increment is the block that should 18803575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 18819ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek ContinueJumpTarget.block->setLoopTarget(F); 18823575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 188347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 188447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 188547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 188647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 188747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 18886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 18896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 18909c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(F->getBody()); 1891af603f742491dc4707138c0293d295171fdd51baTed Kremenek 1892af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 18939ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block;//can happen for "for (...;...;...);" 1894d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 1895941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 18966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1897941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // This new body block is a successor to our "exit" condition block. 18980a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 1899d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 19006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1901941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 1902941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 19030a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 19046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1905d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 19066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 19079c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInit()) { 1908d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 190949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 19102bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 191136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 191236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // There is no loop initialization. We are thus basically a while loop. 191336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // NULL out Block to force lazy block construction. 191436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Block = NULL; 191536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Succ = EntryConditionBlock; 191636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return EntryConditionBlock; 1917d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1918d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1919115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 19203179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, M)) { 1921115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 1922247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, M); 1923115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 1924892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(M->getBase()); 1925115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 1926115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 19279c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { 1928514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 1929514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 1930514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1931514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 1932514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1933514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1934514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1935514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 1936514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 1937514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1938514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 19394cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 1940514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 1941514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 1942514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 1943514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 1944514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 1945514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 1946514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 1947514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1948514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 1949514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1950514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 1951514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 1952514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1953514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 1954514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 19556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 19566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 19576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 1958514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 19596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19609c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = 0; 19616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1962514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 1963d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19644e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1965514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 1966514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 19674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 19684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 19696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19704cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 19719c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 19726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19734cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 19746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 19756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 19776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 19786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 1979892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(ExitConditionBlock, S); 19804cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 19816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19824cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 1983fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // generate new blocks as necessary. We DON'T add the statement by default to 19846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 1985012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek CFGBlock *EntryConditionBlock = Visit(S->getElement(), 1986012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek AddStmtChoice::NotAlwaysAdd); 19876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1988d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19894e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19904e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 19914e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 19926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 19946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 19954cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 19966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19974cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 19986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 19994cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 2000f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Succ(Succ); 2001f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2002f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 20036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2004f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 2005f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 20066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20079c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(S->getBody()); 20086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20094cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 20104cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" 20114e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2012d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20134e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20144e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 20156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20164cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 20170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, BodyBlock); 20184cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 20196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20204cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 20214cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 20220a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopSuccessor); 20234cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 2024514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 20254cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 2026514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 20276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 20286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20298e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted KremenekCFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { 20308e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // Inline the body. 20318e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return addStmt(S->getSubStmt()); 20328e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // TODO: consider adding cleanups for the end of @autoreleasepool scope. 20338e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek} 20348e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 20359c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 2036b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 20376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2038b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 20394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 20406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2041da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 2042da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 2043da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 2044d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2045da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 20466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2047da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 2048fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 2049da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 20506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20514beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 20524beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 2053247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 20544beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 2055b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 20564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 2057b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 20586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20599c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { 20604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 206190658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 2062e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 2063514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 20644b9c2d235fb9449e249d74f48ecfec601650de93John McCallCFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { 20654b9c2d235fb9449e249d74f48ecfec601650de93John McCall autoCreateBlock(); 20664b9c2d235fb9449e249d74f48ecfec601650de93John McCall 20674b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Add the PseudoObject as the last thing. 20684b9c2d235fb9449e249d74f48ecfec601650de93John McCall appendStmt(Block, E); 20694b9c2d235fb9449e249d74f48ecfec601650de93John McCall 20704b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *lastBlock = Block; 20714b9c2d235fb9449e249d74f48ecfec601650de93John McCall 20724b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Before that, evaluate all of the semantics in order. In 20734b9c2d235fb9449e249d74f48ecfec601650de93John McCall // CFG-land, that means appending them in reverse order. 20744b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (unsigned i = E->getNumSemanticExprs(); i != 0; ) { 20754b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *Semantic = E->getSemanticExpr(--i); 20764b9c2d235fb9449e249d74f48ecfec601650de93John McCall 20774b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If the semantic is an opaque value, we're being asked to bind 20784b9c2d235fb9449e249d74f48ecfec601650de93John McCall // it to its source expression. 20794b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) 20804b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantic = OVE->getSourceExpr(); 20814b9c2d235fb9449e249d74f48ecfec601650de93John McCall 20824b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (CFGBlock *B = Visit(Semantic)) 20834b9c2d235fb9449e249d74f48ecfec601650de93John McCall lastBlock = B; 20844b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 20854b9c2d235fb9449e249d74f48ecfec601650de93John McCall 20864b9c2d235fb9449e249d74f48ecfec601650de93John McCall return lastBlock; 20874b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 20884b9c2d235fb9449e249d74f48ecfec601650de93John McCall 20899c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { 20909c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 20916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 209205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 209305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 209405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 209505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 209605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 209705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 2098f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 20999c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 210005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 210105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 210205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 2103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2104fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 2105fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 2106d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2107d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21084e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2109d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 21106b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek Block = 0; 21114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 21124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 21136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 21156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 21166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 21179c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 21189c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 21196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 212049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 212149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek ExitConditionBlock->setTerminator(W); 21226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 21246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. Thus we update 21256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "Succ" after adding the condition. 21269c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = W->getCond()) { 212749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 212849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 2129a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // The condition might finish the current 'Block'. 2130a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu Block = EntryConditionBlock; 2131ad5a894df1841698c824381b414630799adc26caTed Kremenek 21324ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // If this block contains a condition variable, add both the condition 21334ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // variable and initializer to the CFG. 21344ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 21354ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek if (Expr *Init = VD->getInit()) { 21364ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek autoCreateBlock(); 2137d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, W->getConditionVariableDeclStmt()); 21384ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek EntryConditionBlock = addStmt(Init); 21394ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek assert(Block == EntryConditionBlock); 21404ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 21414ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek } 21424ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek 21434e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2144d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21454e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21464e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 214749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 21486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 21506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 215149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 21526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 215300998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 21540a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(W->getCond()); 215500998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2156d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 2157d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 2158f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 2159d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2160d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2161f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2162f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2163f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 2164f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 21656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 21666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 2167f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Block = 0; 2168f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(Succ == EntryConditionBlock); 2169f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ = createBlock(); 2170f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek Succ->setLoopTarget(W); 2171f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 21726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2173d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 217405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 21756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2176d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2177f752fcfae84fbf21b78383bf2461633382d51844Ted Kremenek Block = NULL; 21786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 217905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 218005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 218105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 218205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 218305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 218405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 218505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 218605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2187d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 21889c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(W->getBody()); 21896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2190af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 21919ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;" 21924e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2193d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21944e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21954e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 21966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2197941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 21980a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 2199bf15b278a439d73b605ec00a8d3977ef305712f4Ted Kremenek } 22006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2201941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. (the 2202941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // false branch). 22030a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 22046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 22066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 2207d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 22086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22094ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 22105482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 221149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 2212d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 22131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22159c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { 22164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 22174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 22184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 22194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 22206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22219c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { 22222fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 22232fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 22246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22256c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2226d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 22286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22292fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 22302fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 22316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22322fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 22330a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 22346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 22366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 2237852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 22382fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 2239989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 22409c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { 22416c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2242d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22430979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 22440979d80615df97c675423de631c1b884819f4712Mike Stump 22450979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 22460979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 22470979d80615df97c675423de631c1b884819f4712Mike Stump 22485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 22495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 22500a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 2251ad5a894df1841698c824381b414630799adc26caTed Kremenek else 22525d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 22530a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 22540979d80615df97c675423de631c1b884819f4712Mike Stump 22550979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 22560979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 2257852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 22580979d80615df97c675423de631c1b884819f4712Mike Stump} 22590979d80615df97c675423de631c1b884819f4712Mike Stump 22609c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { 22619c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 22626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22638f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 22648f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 2265d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2266d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22674e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2268d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 22694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 22704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 22716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 22736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 22746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 22759c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 22769c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 22776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 227849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 22796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 22806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 22826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 22839c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) { 228449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 228549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 22864e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2287d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22884e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 22894e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 229049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 22916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22925482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 229349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 229449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 229500998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 22960a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(D->getCond()); 229700998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2298d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 22999c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = NULL; 2300d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 23016db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 23026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2303d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2304f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2305f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2306f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 23076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2308d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 2309f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 23106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2311d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 2312f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 23136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2314d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2315b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 23166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 231705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 231805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 231905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 232005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 232105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2322d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 23234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 23246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2325af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 2326a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 23274e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2328d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23294e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 23304e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 23316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2332d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 2333d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 2334d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 2335d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 2336d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 2337d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 2338d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 2339d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 2340d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 2341d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 2342d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 2343d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 23440a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopBackBlock); 2345d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 2346d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 23470a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, NULL); 2348b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 23496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2350941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 2351941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 23520a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 23536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 23556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 2356d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 23576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2358d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 23595482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 2360d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 2361d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2362d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 23639c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { 2364d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 2365d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 2366d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2367d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 23686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2369d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 2370d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 2371d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 23726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2373d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 2374235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 23759ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (ContinueJumpTarget.block) { 23769ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C); 23779ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, ContinueJumpTarget.block); 2378f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 2379235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 23806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2381d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 2382d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 23831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2384f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter CollingbourneCFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 2385f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc) { 238613fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 23873179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 238813fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2389892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, E); 239013fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 23911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 239397e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek CFGBlock *lastBlock = Block; 239497e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek 23954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 2396f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); 23974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 239897e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek lastBlock = addStmt(VA->getSizeExpr()); 2399f91a5b008d1a63630ae483247204c2651e512fa1Ted Kremenek } 240097e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek return lastBlock; 2401d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 24021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 24044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 24059c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 24063179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, SE)) { 240713fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2408892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, SE); 240913fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 24104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 24114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2412d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 24139c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { 24146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 24156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 24169c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchSuccessor = NULL; 24176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24188ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 24198ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 24208ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 24218ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 24228ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 24238ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 24249c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 24258ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 24268ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 24278ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 24288ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 24298ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2430d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2431d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24324e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2433d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 24346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2435d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2436d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2437d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2438eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2439f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2440eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 24416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 24426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 24436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2444eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 24456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2446d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2447d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 24486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2449d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2450d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2451d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2452f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 24536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 24556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 24566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 24576db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 245849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 24598ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2460e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // For pruning unreachable case statements, save the current state 2461e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // for tracking the condition value. 2462e71f3d587844110d836c82250830b27b1651afdbTed Kremenek SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered, 2463e71f3d587844110d836c82250830b27b1651afdbTed Kremenek false); 24640498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2465e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Determine if the switch condition can be explicitly evaluated. 2466e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 24670498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult result; 2468e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek bool b = tryEvaluate(Terminator->getCond(), result); 2469e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, 2470e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek b ? &result : 0); 24710498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 24728ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 24738ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 24748ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 24758ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 24768ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2477d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 24784e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2479d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24804e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 24814e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 248249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 24836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 2484432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // following the switch body. Moreover, take into account if all the 2485432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // cases of a switch are covered (e.g., switching on an enum value). 2486e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2487432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek switchExclusivelyCovered || Terminator->isAllEnumCasesCovered() 2488432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek ? 0 : DefaultCaseBlock); 24896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 249049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2491411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 2492d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 24936b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek Block = addStmt(Terminator->getCond()); 2494ad5a894df1841698c824381b414630799adc26caTed Kremenek 24956b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 24966b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 24976b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 24986b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 24996b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 2500d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, Terminator->getConditionVariableDeclStmt()); 25016b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek addStmt(Init); 25026b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 25036b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2504ad5a894df1841698c824381b414630799adc26caTed Kremenek 25056b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek return Block; 2506d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2507e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2508e71f3d587844110d836c82250830b27b1651afdbTed Kremenekstatic bool shouldAddCase(bool &switchExclusivelyCovered, 2509e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const Expr::EvalResult *switchCond, 2510e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const CaseStmt *CS, 2511e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ASTContext &Ctx) { 2512e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (!switchCond) 2513e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek return true; 2514e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek 2515e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool addCase = false; 25160498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2517e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!switchExclusivelyCovered) { 2518e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (switchCond->Val.isInt()) { 2519e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the LHS of the case value. 252085df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx); 2521e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const llvm::APSInt &condInt = switchCond->Val.getInt(); 2522e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2523e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (condInt == lhsInt) { 2524e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2525e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2526e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2527e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else if (condInt < lhsInt) { 2528e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (const Expr *RHS = CS->getRHS()) { 2529e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the RHS of the case value. 253085df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx); 253185df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (V2 <= condInt) { 2532e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2533e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2534e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2535e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2536e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2537e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2538e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else 2539e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2540e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2541e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return addCase; 2542e71f3d587844110d836c82250830b27b1651afdbTed Kremenek} 2543d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 25449c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) { 25456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 25466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 25470fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 25480498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 25490fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 25500fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 25510fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 25520fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 25530fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 25540a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek CFGBlock *currentBlock = createBlock(false); 25550a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek currentBlock->setLabel(CS); 25560fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 25570fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 25580a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, currentBlock); 25590fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 25600a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TopBlock = currentBlock; 25610fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2562e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2563e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2564e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2565e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? currentBlock : 0); 25660fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2567e71f3d587844110d836c82250830b27b1651afdbTed Kremenek LastBlock = currentBlock; 25680fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 25690fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 25700fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 257129ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 25720fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 25730fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 25741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25759c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CaseBlock = Block; 25764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 25774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 25786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 25806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 25814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 25824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2583d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25844e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 25856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 25876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 25884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2589e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2590e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2591e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2592e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? CaseBlock : 0); 25936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2594d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2595d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 25966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25970fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 25980a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, CaseBlock); 25990fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 260036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 26010fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 26020fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 26030fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 26046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26050fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2606d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 26076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26089c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) { 26094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 26104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 26111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2612eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 26134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 26144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 26154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 26166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 26186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2619411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 26201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2621d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 26224e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2623eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 26246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 26256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 26266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 26276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 26286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 26296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2630eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2631eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 26326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2633eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2634eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 26356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2637295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2638d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 26395d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 26405d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 26415d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 26429c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TrySuccessor = NULL; 26435d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26445d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2645d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 26465d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 26475d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 26485d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 26495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2650a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 26515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26525d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2653f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 26545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2655f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 26565d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2657a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 26585d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 26595d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 26605d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 26615d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2662a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2663a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2664a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 26655d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 26665d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 26675d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 26685d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 26695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 26705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 26710a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, CatchBlock); 26725d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2673a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2674a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 26750a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2676a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 26770a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2678a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 26795d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26805d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 26815d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 26825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2683f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2684f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock, NewTryTerminatedBlock); 2685f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek cfg->addTryDispatchBlock(TryTerminatedBlock); 2686f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 26876db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 26885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 26893fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek Block = addStmt(Terminator->getTryBlock()); 26905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return Block; 26915d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 26925d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26939c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { 26945d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 26955d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 26965d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 26970e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 26980e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 26990e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 27000e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 27010e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 27020e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 27039c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = CS->getExceptionDecl()) { 27040e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 27050e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 27060e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 27070e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 27080e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 27095d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 27105d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 27115d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 27129c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CatchBlock = Block; 27135d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 27145d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 2715337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2716337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // CXXCatchStmt is more than just a label. They have semantic meaning 2717337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // as well, as they implicitly "initialize" the catch variable. Add 2718337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // it to the CFG as a CFGElement so that the control-flow of these 2719337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // semantics gets captured. 2720337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek appendStmt(CatchBlock, CS); 2721337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2722337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Also add the CXXCatchStmt as a label, to mirror handling of regular 2723337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // labels. 27245d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 27255d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2726337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Bail out if the CFG is bad. 2727d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 27285d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 27295d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 27305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 27315d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 27325d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 27335d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 27345d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 27355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 27369c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { 2737ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // C++0x for-range statements are specified as [stmt.ranged]: 2738ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // 2739ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // { 2740ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // auto && __range = range-init; 2741ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for ( auto __begin = begin-expr, 2742ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __end = end-expr; 2743ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __begin != __end; 2744ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // ++__begin ) { 2745ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for-range-declaration = *__begin; 2746ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // statement 2747ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2748ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2749ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2750ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save local scope position before the addition of the implicit variables. 2751ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 2752ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2753ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Create local scopes and destructors for range, begin and end variables. 2754ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *Range = S->getRangeStmt()) 2755ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(Range); 2756ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *BeginEnd = S->getBeginEndStmt()) 2757ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(BeginEnd); 2758ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S); 2759ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2760ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LocalScope::const_iterator ContinueScopePos = ScopePos; 2761ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2762ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // "for" is a control-flow statement. Thus we stop processing the current 2763ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // block. 27649c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 2765ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Block) { 2766ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2767ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2768ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Block; 2769ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } else 2770ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Succ; 2771ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2772ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current value for the break targets. 2773ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // All breaks should go to the code following the loop. 2774ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2775ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 2776ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2777ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The block for the __begin != __end expression. 27789c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConditionBlock = createBlock(false); 2779ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ConditionBlock->setTerminator(S); 2780ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2781ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now add the actual condition to the condition block. 2782ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Expr *C = S->getCond()) { 2783ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = ConditionBlock; 2784ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *BeginConditionBlock = addStmt(C); 2785ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2786ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2787ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(BeginConditionBlock == ConditionBlock && 2788ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith "condition block in for-range was unexpectedly complex"); 2789ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith (void)BeginConditionBlock; 2790ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2791ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2792ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The condition block is the implicit successor for the loop body as well as 2793ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // any code above the loop. 2794ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = ConditionBlock; 2795ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2796ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // See if this is a known constant. 2797ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith TryResult KnownVal(true); 2798ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2799ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (S->getCond()) 2800ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith KnownVal = tryEvaluateBool(S->getCond()); 2801ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2802ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now create the loop body. 2803ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith { 2804ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(S->getBody()); 2805ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2806ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current values for Block, Succ, and continue targets. 2807ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2808ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 2809ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2810ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Generate increment code in its own basic block. This is the target of 2811ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // continue statements. 2812ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2813ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = addStmt(S->getInc()); 2814ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 2815ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2816ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The starting block for the loop increment is the block that should 2817ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // represent the 'loop target' for looping back to the start of the loop. 2818ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget.block->setLoopTarget(S); 2819ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2820ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Finish up the increment block and prepare to start the loop body. 2821ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(Block); 2822ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2823ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2824ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2825ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2826ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2827ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add implicit scope and dtors for loop variable. 2828ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeAndDtors(S->getLoopVarStmt()); 2829ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2830ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Populate a new block to contain the loop body and loop variable. 2831ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getBody()); 2832ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2833ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2834ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getLoopVarStmt()); 2835ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2836ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2837ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2838ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // This new body block is a successor to our condition block. 2839ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : Block); 2840ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2841ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2842ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Link up the condition block with the code that follows the loop (the 2843ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // false branch). 2844ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor); 2845ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2846ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add the initialization statements. 2847ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = createBlock(); 2848b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith addStmt(S->getBeginEndStmt()); 2849b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith return addStmt(S->getRangeStmt()); 2850ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith} 2851ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 28524765fa05b5652fcc4356371c2f481d0ea9a1b007John McCallCFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, 28538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc) { 28548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (BuildOpts.AddImplicitDtors) { 28558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If adding implicit destructors visit the full expression for adding 28568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // destructors of temporaries. 28578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(E->getSubExpr()); 28588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 28598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Full expression has to be added as CFGStmt so it will be sequenced 28608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before destructors of it's temporaries. 286194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(true); 28628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 28638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(E->getSubExpr(), asc); 28648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 28658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 2866a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 2867a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 28683179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2869a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2870247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2871a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 2872a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 287394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 2874a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2875a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2876a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2877a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 287881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, 287981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 288081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 288197a72c35a62304c3781aa280e28cb97a59afd585Zhongxing Xu appendStmt(Block, C); 288294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 288381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 288481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 288581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2886a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 2887a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 28883179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2889a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2890247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2891a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 289294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 2893a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2894a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2895a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2896a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 289781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 289881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 289981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 2900247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 290181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 290281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 290381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 2904a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, 2905a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 29063179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2907a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2908247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2909a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2910892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(E->getSubExpr(), AddStmtChoice()); 2911a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2912a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 29139c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) { 29146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 29159c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *IBlock = cfg->getIndirectGotoBlock(); 29166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 291719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 291819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 291919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 292019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 29216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 292219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 292319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 2924d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 29254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 29264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 292719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 292819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 29290a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, IBlock); 293019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 293119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 293219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 29338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) { 29348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskitryAgain: 29358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!E) { 29368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski badCFG = true; 29378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 29388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski switch (E->getStmtClass()) { 29408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski default: 29418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitChildrenForTemporaryDtors(E); 29428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::BinaryOperatorClass: 29448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E)); 29458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXBindTemporaryExprClass: 29478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXBindTemporaryExprForTemporaryDtors( 29488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<CXXBindTemporaryExpr>(E), BindToTemporary); 29498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 295056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 29518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ConditionalOperatorClass: 29528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitConditionalOperatorForTemporaryDtors( 295356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall cast<AbstractConditionalOperator>(E), BindToTemporary); 29548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ImplicitCastExprClass: 29568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For implicit cast we want BindToTemporary to be passed further. 29578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<CastExpr>(E)->getSubExpr(); 29588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 29598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ParenExprClass: 29618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<ParenExpr>(E)->getSubExpr(); 29628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 296303e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor 296403e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor case Stmt::MaterializeTemporaryExprClass: 296503e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(); 296603e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor goto tryAgain; 29678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 29698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { 29718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // When visiting children for destructors we want to visit them in reverse 29728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. Because there's no reverse iterator for children must to reverse 29738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // them in helper vector. 29745f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<Stmt *, 4> ChildrenVect; 29758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ChildrenVect ChildrenRev; 29767502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range I = E->children(); I; ++I) { 29778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (*I) ChildrenRev.push_back(*I); 29788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = Block; 29818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(), 29828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski L = ChildrenRev.rend(); I != L; ++I) { 29838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (CFGBlock *R = VisitForTemporaryDtors(*I)) 29848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = R; 29858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 29878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 29888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { 29908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->isLogicalOp()) { 29918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors for temporaries in LHS expression should be called after 29928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // those for RHS expression. Even if this will unnecessarily create a block, 29938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // this block will be used at least by the full expression. 29948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 29958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); 29968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 29978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 29988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 30008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 30018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 30028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (RHSBlock) { 30048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 30058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 30068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If RHS expression did produce destructors we need to connect created 30088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // blocks to CFG in same manner as for binary operator itself. 30098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = createBlock(false); 30108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock->setTerminator(CFGTerminator(E, true)); 30118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For binary operator LHS block is before RHS in list of predecessors 30138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // of ConfluenceBlock. 30148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), 30158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConfluenceBlock->pred_end()); 30168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 30180a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(E->getLHS()); 30198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) 30208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski KnownVal.negate(); 30218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Link LHSBlock with RHSBlock exactly the same way as for binary operator 30238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // itself. 30248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getOpcode() == BO_LOr) { 30250a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 30260a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 30278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 30288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert (E->getOpcode() == BO_LAnd); 30290a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 30300a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 30318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = LHSBlock; 30348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock; 30358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 30388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return ConfluenceBlock; 30398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 304136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (E->isAssignmentOp()) { 30428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For assignment operator (=) LHS expression is visited 30438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before RHS expression. For destructors visit them in reverse order. 30448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 30458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 30468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock ? LHSBlock : RHSBlock; 30478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For any other binary operator RHS expression is visited before 30508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // LHS expression (order of children). For destructors visit them in reverse 30518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. 30528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 30538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 30548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return RHSBlock ? RHSBlock : LHSBlock; 30558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 30568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( 30588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *E, bool BindToTemporary) { 30598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for temporaries in subexpression. 30608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr()); 3061249c9458e2cc5b671634baefe8517d7598883a20Zhongxing Xu if (!BindToTemporary) { 30628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If lifetime of temporary is not prolonged (by assigning to constant 30638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // reference) add destructor for it. 3064c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 3065c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If the destructor is marked as a no-return destructor, we need to create 3066c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // a new block for the destructor which does not have as a successor 3067c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far. Control won't flow out of this block. 3068c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor(); 3069dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) 3070dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 3071dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 3072c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 3073c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 30748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendTemporaryDtor(Block, E); 30758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = Block; 30768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 30788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 30798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( 308156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AbstractConditionalOperator *E, bool BindToTemporary) { 30828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for condition expression. Even if this will 30838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // unnecessarily create a block, this block will be used at least by the full 30848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // expression. 30858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 30868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); 30878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 30888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 308956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (BinaryConditionalOperator *BCO 309056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall = dyn_cast<BinaryConditionalOperator>(E)) { 309156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); 30928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 30938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 30948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 309656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall // Try to add block with destructors for LHS expression. 309756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *LHSBlock = NULL; 309856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Succ = ConfluenceBlock; 309956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Block = NULL; 310056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); 310156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (badCFG) 310256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return NULL; 310356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 31048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for RHS expression; 31058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 31068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 310756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), 310856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall BindToTemporary); 31098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 31108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 31118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock && !LHSBlock) { 31138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If neither LHS nor RHS expression had temporaries to destroy don't create 31148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // more blocks. 31158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 31168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 31178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = createBlock(false); 31208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block->setTerminator(CFGTerminator(E, true)); 31218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 31230a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(E->getCond()); 31248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (LHSBlock) { 31260a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 31278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (KnownVal.isFalse()) { 31280a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, NULL); 31298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 31300a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, ConfluenceBlock); 31318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); 31328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock) 31358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski RHSBlock = ConfluenceBlock; 31360a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 31378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 31398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 31408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3141befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 3142026473c2175424a039f51ca8949937268721b965Ted Kremenek 31436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 31446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 31456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 31469c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFG::createBlock() { 3147026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 3148026473c2175424a039f51ca8949937268721b965Ted Kremenek 3149026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 3150ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 315102f34c5003b2c5067675f89ffce0a84c28faf722Anna Zaks new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this); 3152ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 3153026473c2175424a039f51ca8949937268721b965Ted Kremenek 3154026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 3155ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 3156ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 3157026473c2175424a039f51ca8949937268721b965Ted Kremenek 3158026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 3159ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 3160026473c2175424a039f51ca8949937268721b965Ted Kremenek} 3161026473c2175424a039f51ca8949937268721b965Ted Kremenek 3162026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 3163026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 31649c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFG::buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, 3165b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const BuildOptions &BO) { 3166b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFGBuilder Builder(C, BO); 3167b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek return Builder.buildCFG(D, Statement); 3168fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 3169fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 3170c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekconst CXXDestructorDecl * 3171c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed KremenekCFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { 3172c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek switch (getKind()) { 3173c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Invalid: 3174c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Statement: 3175c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Initializer: 3176c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek llvm_unreachable("getDestructorDecl should only be used with " 3177c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek "ImplicitDtors"); 3178c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::AutomaticObjectDtor: { 3179c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const VarDecl *var = cast<CFGAutomaticObjDtor>(this)->getVarDecl(); 3180c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = var->getType(); 3181697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek ty = ty.getNonReferenceType(); 31824cf225382a8b061dce41733c962d62b6db9721f8Ted Kremenek while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { 3183c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek ty = arrayType->getElementType(); 3184c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek } 3185c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const RecordType *recordType = ty->getAs<RecordType>(); 3186c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXRecordDecl *classDecl = 3187697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek cast<CXXRecordDecl>(recordType->getDecl()); 3188c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return classDecl->getDestructor(); 3189c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3190c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::TemporaryDtor: { 3191c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXBindTemporaryExpr *bindExpr = 3192c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek cast<CFGTemporaryDtor>(this)->getBindTemporaryExpr(); 3193c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXTemporary *temp = bindExpr->getTemporary(); 3194c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return temp->getDestructor(); 3195c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3196c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::BaseDtor: 3197c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::MemberDtor: 3198c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3199c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // Not yet supported. 3200c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return 0; 3201c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3202697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek llvm_unreachable("getKind() returned bogus value"); 3203c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek} 3204c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3205c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekbool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { 3206c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek if (const CXXDestructorDecl *cdecl = getDestructorDecl(astContext)) { 3207c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = cdecl->getType(); 3208c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return cast<FunctionType>(ty)->getNoReturnAttr(); 3209c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3210c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return false; 32113c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek} 32123c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 321363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 321463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek// CFG: Queries for BlkExprs. 321563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 321663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 321763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremeneknamespace { 321886946745225096243f6969dc745267b78fc211a6Ted Kremenek typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy; 321963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 322063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 3221f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenekstatic void FindSubExprAssignments(const Stmt *S, 3222f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek llvm::SmallPtrSet<const Expr*,50>& Set) { 32238a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!S) 322433d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return; 32256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3226f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek for (Stmt::const_child_range I = S->children(); I; ++I) { 3227f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *child = *I; 32288a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!child) 32298a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek continue; 3230ad5a894df1841698c824381b414630799adc26caTed Kremenek 3231f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(child)) 323233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (B->isAssignmentOp()) Set.insert(B); 32336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32348a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek FindSubExprAssignments(child, Set); 323533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 323633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek} 323733d4aab80f31bd06257526fe2883ea920529456bTed Kremenek 323863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekstatic BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { 323963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = new BlkExprMapTy(); 32406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Look for assignments that are used as subexpressions. These are the only 32426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // assignments that we want to *possibly* register as a block-level 32436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression. Basically, if an assignment occurs both in a subexpression and 32446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // at the block-level, it is a block-level expression. 3245f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek llvm::SmallPtrSet<const Expr*,50> SubExprAssignments; 32466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 324763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) 3248ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 32493c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = BI->getAs<CFGStmt>()) 32503c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek FindSubExprAssignments(S->getStmt(), SubExprAssignments); 325186946745225096243f6969dc745267b78fc211a6Ted Kremenek 3252411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { 32536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Iterate over the statements again on identify the Expr* and Stmt* at the 32556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block-level that are block-level expressions. 3256411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 3257b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { 32583c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CFGStmt *CS = BI->getAs<CFGStmt>(); 32593c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (!CS) 3260b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu continue; 3261f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const Expr *Exp = dyn_cast<Expr>(CS->getStmt())) { 3262ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert((Exp->IgnoreParens() == Exp) && "No parens on block-level exps"); 32636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3264f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { 326533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek // Assignment expressions that are not nested within another 32666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression are really "statements" whose value is never used by 32676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // another expression. 3268411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) 326933d4aab80f31bd06257526fe2883ea920529456bTed Kremenek continue; 32709c378f705405d37f49795d5e915989de774fe11fTed Kremenek } else if (const StmtExpr *SE = dyn_cast<StmtExpr>(Exp)) { 32716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Special handling for statement expressions. The last statement in 32726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the statement expression is also a block-level expr. 32739c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CompoundStmt *C = SE->getSubStmt(); 327486946745225096243f6969dc745267b78fc211a6Ted Kremenek if (!C->body_empty()) { 3275ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose const Stmt *Last = C->body_back(); 3276ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (const Expr *LastEx = dyn_cast<Expr>(Last)) 3277ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose Last = LastEx->IgnoreParens(); 327833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3279ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[Last] = x; 328086946745225096243f6969dc745267b78fc211a6Ted Kremenek } 328186946745225096243f6969dc745267b78fc211a6Ted Kremenek } 3282e2dcd783a04f654c50bd8b13fb08a440afbd67e7Ted Kremenek 328333d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3284411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek (*M)[Exp] = x; 328533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 3286b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 32876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3288411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek // Look at terminators. The condition is a block-level expression. 32896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32909c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *S = (*I)->getTerminatorCondition(); 32916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3292390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek if (S && M->find(S) == M->end()) { 3293ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose unsigned x = M->size(); 3294ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[S] = x; 3295411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 3296411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 32976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 329886946745225096243f6969dc745267b78fc211a6Ted Kremenek return M; 329963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 330063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 33019c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt *S) { 330286946745225096243f6969dc745267b78fc211a6Ted Kremenek assert(S != NULL); 330363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } 33046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 330563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap); 330686946745225096243f6969dc745267b78fc211a6Ted Kremenek BlkExprMapTy::iterator I = M->find(S); 33073fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); 330863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 33097dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 331063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekunsigned CFG::getNumBlkExprs() { 331163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap)) 331263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return M->size(); 331336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 331436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // We assume callers interested in the number of BlkExprs will want 331536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // the map constructed if it doesn't already exist. 331636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan BlkExprMap = (void*) PopulateBlkExprMap(*this); 331736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size(); 331863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 331963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 3320274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3321ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 3322ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3323ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3324ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 3325be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 3326ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 33276e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (To && F.IgnoreDefaultsWithCoveredEnums) { 3328ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 3329ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 3330ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 33316e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { 3332ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 33336e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek const Stmt *L = To->getLabel(); 33346e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 33356e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek return true; 3336ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3337ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3338ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3339ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3340ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 3341ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 3342ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3343ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3344274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek// Cleanup: CFG dstor. 3345274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3346274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek 334763f5887f316fb52d243fcbb3631c039de6c4b993Ted KremenekCFG::~CFG() { 334863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap); 334963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 33506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33517dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 33527dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 33537dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 33547dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 335542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 33562bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 3357ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 33583c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 33593c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 336042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 33611cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 33620a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek signed currentBlock; 33630a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek unsigned currentStmt; 3364e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 336542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 33661c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 3367e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 33683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek : currentBlock(0), currentStmt(0), LangOpts(LO) 33693c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek { 337042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 337142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 3372ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 33731cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 33743c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *SE = BI->getAs<CFGStmt>()) { 33753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt= SE->getStmt(); 33761cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 33773c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek StmtMap[stmt] = P; 33783c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 33793c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek switch (stmt->getStmtClass()) { 33803c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::DeclStmtClass: 33813c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P; 33823c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 33833c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::IfStmtClass: { 33843c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable(); 33853c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 33863c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 33873c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 33883c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 33893c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::ForStmtClass: { 33903c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable(); 33913c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 33923c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 33933c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 33943c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 33953c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::WhileStmtClass: { 33963c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 33973c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<WhileStmt>(stmt)->getConditionVariable(); 33983c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 33993c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34003c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34013c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34023c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::SwitchStmtClass: { 34033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 34043c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<SwitchStmt>(stmt)->getConditionVariable(); 34053c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 34063c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34073c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34083c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34093c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::CXXCatchStmtClass: { 34103c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 34113c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<CXXCatchStmt>(stmt)->getExceptionDecl(); 34123c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 34133c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 34143c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34153c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 34163c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek default: 34173c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 34181cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 34191cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 342042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 3421b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 3422fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 34233c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 34246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 342542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 34266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3427e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 34280a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setBlockID(signed i) { currentBlock = i; } 34290a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setStmtID(unsigned i) { currentStmt = i; } 34306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34319c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual bool handledStmt(Stmt *S, raw_ostream &OS) { 34321cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 3433fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 343442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 343542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 34366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34370a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 34380a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek && I->second.second == currentStmt) { 343942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 34403fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 34416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34423fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 34431c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 344442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 34451cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34469c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool handleDecl(const Decl *D, raw_ostream &OS) { 34471cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 34481cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34491cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 34501cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 34511cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34520a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 34530a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek && I->second.second == currentStmt) { 34541cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 34551cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 34561cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 34571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 34581cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 34591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 346042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 3461e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3462e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 3463e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 3464e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 3465ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 34666fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 34676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34689c378f705405d37f49795d5e915989de774fe11fTed Kremenek raw_ostream &OS; 346942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 3470d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 3471d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 34729c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper, 3473e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 3474d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 34756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34769c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIfStmt(IfStmt *I) { 3477d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 3478d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 3479d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 34806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3481d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 34829c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitStmt(Stmt *Terminator) { 34836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 34846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 34856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34869c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitForStmt(ForStmt *F) { 3487d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 34883fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 34893fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3490535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 34919c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = F->getCond()) 34923fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3493535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 34943fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 34953fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3496a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 3497d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 34986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34999c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitWhileStmt(WhileStmt *W) { 3500d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 35019c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = W->getCond()) 35023fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3503d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 35046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35059c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitDoStmt(DoStmt *D) { 3506d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 35079c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) 35083fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 35099da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 35106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35119c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitSwitchStmt(SwitchStmt *Terminator) { 35129da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 3513d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 35149da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 35156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35169c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitCXXTryStmt(CXXTryStmt *CS) { 35175d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 35185d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 35195d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 352056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { 3521d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 35226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 3523805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 35246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35259c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitChooseExpr(ChooseExpr *C) { 3526aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 3527d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 3528a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 3529aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 35306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35319c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt *I) { 35321c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 3533d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 35341c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 35356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3536805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 3537805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 3538805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 3539805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3540805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 35416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3542d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 35436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3544805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 35452de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 3546a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 3547805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 35482de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 3549a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 3550805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3551805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 3552b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid logical operator."); 35536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3554805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 35556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35569c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitExpr(Expr *E) { 3557d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 35586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3559d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3560e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3561e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 35625f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper, 3563079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 35643c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *CS = E.getAs<CFGStmt>()) { 3565f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *S = CS->getStmt(); 35661cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 35681cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35691cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 3570f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) { 3571f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const CompoundStmt *Sub = SE->getSubStmt(); 35721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35737502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall if (Sub->children()) { 35741cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 35751cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 35761cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 35771cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 35781cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 35791cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 35801cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 3581f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 35821cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 35831cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 35841cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 35851cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 35861cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 35871cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 35881c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 35891c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 35901cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 35916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35921cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 359336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (OperatorCall)"; 3594893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 3595893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (isa<CXXBindTemporaryExpr>(S)) { 359636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (BindTemporary)"; 35976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 35983b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) { 35993b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek OS << " (CXXConstructExpr, " << CCE->getType().getAsString() << ")"; 36003b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek } 3601893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) { 3602893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek OS << " (" << CE->getStmtClassName() << ", " 3603893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << CE->getCastKindName() 3604893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ", " << CE->getType().getAsString() 3605893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ")"; 3606893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 36076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36081cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 36091cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 36101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 36114e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 36123c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGInitializer *IE = E.getAs<CFGInitializer>()) { 36133c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXCtorInitializer *I = IE->getInitializer(); 36141cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 36151cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 361600eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet else OS << I->getAnyMember()->getName(); 36176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36181cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 36199c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *IE = I->getInit()) 36201cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 36211cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 36221cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36231cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 36241cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 36251cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 36261cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36273c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGAutomaticObjDtor *DE = E.getAs<CFGAutomaticObjDtor>()){ 36289c378f705405d37f49795d5e915989de774fe11fTed Kremenek const VarDecl *VD = DE->getVarDecl(); 36291cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 36301cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3631b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski const Type* T = VD->getType().getTypePtr(); 36321cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 36331cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 3634b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski else if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 3635b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski T = ET; 36361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36371cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 36381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 36397c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 36403c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGBaseDtor *BE = E.getAs<CFGBaseDtor>()) { 36413c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); 36427c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 36434e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 36447c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 36453c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) { 36463c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const FieldDecl *FD = ME->getFieldDecl(); 36478c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 36488c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski const Type *T = FD->getType().getTypePtr(); 36498c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const Type *ET = T->getArrayElementTypeNoTypeQual()) 36508c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski T = ET; 36518c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 36527c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 36538c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; 36544e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 36558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 36563c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGTemporaryDtor *TE = E.getAs<CFGTemporaryDtor>()) { 36573c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); 36588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()"; 36598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << " (Temporary object destructor)\n"; 36601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 366181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 36626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36639c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void print_block(raw_ostream &OS, const CFG* cfg, 36649c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock &B, 3665682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek StmtPrinterHelper* Helper, bool print_edges, 3666682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) { 36676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3668682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (Helper) 3669682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek Helper->setBlockID(B.getBlockID()); 36706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36717dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 3672682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3673682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::YELLOW, true); 3674682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3675682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n [B" << B.getBlockID(); 36766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 367742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 3678682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (ENTRY)]\n"; 367942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 3680682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (EXIT)]\n"; 368142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 3682682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (INDIRECT GOTO DISPATCH)]\n"; 368342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 3684682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "]\n"; 3685682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3686682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3687682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 36886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36899cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 36909c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) { 369142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 369242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3693682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 36946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36959c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (LabelStmt *L = dyn_cast<LabelStmt>(Label)) 36969cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 36979c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) { 36989cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 3699e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 3700e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 37019cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 37029cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 3703e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 3704e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 37059cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 3706079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 37079cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 3708079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 37095d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 3710a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 3711a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 3712a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 3713a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 3714a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 37155d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 37165d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 37175d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 3718b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid label statement in CFGBlock."); 37196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37209cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 37219cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 37226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3723fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 3724fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 37256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 372642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 372742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 37286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37299cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 373042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3731682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 37326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3733a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 37346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 373542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 373642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 37376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3738682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_elem(OS, Helper, *I); 3739fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 37406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37419cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 374242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 3743682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3744682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::GREEN); 37456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3746682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " T: "; 37476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 374842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 37496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3750e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, Helper, 3751e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 37524ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt())); 3753a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 3754682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3755682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3756682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3757fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 37586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37599cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 37609cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 3761682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.pred_empty()) { 3762682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::BLUE; 3763682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3764682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3765682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Preds " ; 3766682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3767682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3768682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.pred_size() << "):"; 3769682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3770682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3771682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3772682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3773682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3774682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 3775682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 377642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3777682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (i == 8 || (i-8) == 0) 3778682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 37796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3780682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3781682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3782682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3783682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3784682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 37856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3786682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 37879cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 37886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37899cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 3790682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.succ_empty()) { 3791682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::MAGENTA; 3792682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3793682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3794682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Succs "; 3795682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3796682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3797682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.succ_size() << "):"; 3798682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3799682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3800682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3801682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3802682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3803682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 3804682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 3805682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3806682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (i == 8 || (i-8) % 10 == 0) 3807682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 3808682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3809682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (*I) 3810682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3811682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek else 3812682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " NULL"; 3813682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3814682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3815682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3816682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3817682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3818fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 3819fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 38206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 382142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 382242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 382342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 3824682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::dump(const LangOptions &LO, bool ShowColors) const { 3825682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), LO, ShowColors); 3826682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek} 382742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 382842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 3829682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const { 3830e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 38316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 383242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 3833682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getEntry(), &Helper, true, ShowColors); 38346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 383542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 383642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 383742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 3838ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 383942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 38406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3841682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, **I, &Helper, true, ShowColors); 384242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 38436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 384442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 3845682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getExit(), &Helper, true, ShowColors); 3846682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3847d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 38486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 384942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 385042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 3851682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO, 3852682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) const { 3853682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), cfg, LO, ShowColors); 3854e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 385542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 385642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 385742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 38589c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBlock::print(raw_ostream &OS, const CFG* cfg, 3859682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const LangOptions &LO, bool ShowColors) const { 3860e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 3861682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, cfg, *this, &Helper, true, ShowColors); 3862682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3863026473c2175424a039f51ca8949937268721b965Ted Kremenek} 38647dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3865a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 38665f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid CFGBlock::printTerminator(raw_ostream &OS, 38676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 3868e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 38694ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt())); 3870a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 3871a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 38729c378f705405d37f49795d5e915989de774fe11fTed KremenekStmt *CFGBlock::getTerminatorCondition() { 38734ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski Stmt *Terminator = this->Terminator; 3874411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 3875411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 38766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38779c378f705405d37f49795d5e915989de774fe11fTed Kremenek Expr *E = NULL; 38786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3879411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 3880411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 3881411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 38826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3883411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 3884411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 3885411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 38866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3887411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 3888411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 3889411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 38906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3891411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 3892411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 3893411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 38946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3895411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 3896411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 3897411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 38986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3899411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 3900411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 3901411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3903411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 3904411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 3905411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3907411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 3908411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 3909411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 391156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 391256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall E = cast<BinaryConditionalOperator>(Terminator)->getCond(); 391356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall break; 391456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 3915411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 3916411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 3917411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 39186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3919411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 3920411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 3921390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 39226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3923390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 39246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 3925411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 39266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3927411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 3928411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 3929411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 39307dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 39317dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 39327dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 39337dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 393442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 393542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 39366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 393742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 393842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3939e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 394042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 3941e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 394242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 394342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 394442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 394542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 394642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 394742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 39487dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 39497dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 39507dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 3951006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 3952006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 3953006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 39549c378f705405d37f49795d5e915989de774fe11fTed Kremenek static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) { 39557dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3956bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 3957a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 3958a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 3959682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(Out,Graph, *Node, GraphHelper, false, false); 3960a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 39617dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 39627dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 39637dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 39647dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 39657dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 39667dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 39677dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 39687dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 39697dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 39706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 39717dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 3972bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 3973bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 3974bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 39757dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 39767dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 39777dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 3978