CFG.cpp revision 5a1ffe98b04120846a15f7105905b5f363b08635
16960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek //===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===// 2fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 3fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// The LLVM Compiler Infrastructure 4fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 7fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 8fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 9fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 10fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// This file defines the CFG and CFGBuilder classes for representing and 11fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// building Control-Flow Graphs (CFGs) from ASTs. 12fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 13fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 14fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 15b2c60b04a597cc5ba4154837cf8e0a155a376fd7Argyrios Kyrtzidis#include "llvm/Support/SaveAndRestore.h" 16e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h" 17478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer#include "clang/AST/ASTContext.h" 18b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump#include "clang/AST/DeclCXX.h" 19c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek#include "clang/AST/StmtVisitor.h" 2042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#include "clang/AST/PrettyPrinter.h" 21c56c004e0b8030e8ca8614e7febe581221938b75Ted Kremenek#include "clang/AST/CharUnits.h" 22534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith#include "clang/Basic/AttrKinds.h" 237dba8607e59096014b7139ff20ef00870041d518Ted Kremenek#include "llvm/Support/GraphWriter.h" 246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Allocator.h" 256cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/Format.h" 266cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/DenseMap.h" 276cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/SmallPtrSet.h" 280ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek#include "llvm/ADT/OwningPtr.h" 2983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 30fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenekusing namespace clang; 31fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 32fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremeneknamespace { 33fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 349c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic SourceLocation GetEndLoc(Decl *D) { 359c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(D)) 369c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *Ex = VD->getInit()) 37c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek return Ex->getSourceRange().getEnd(); 386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return D->getLocation(); 39c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek} 40ad5a894df1841698c824381b414630799adc26caTed Kremenek 413179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenekclass CFGBuilder; 423179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 4394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// The CFG builder uses a recursive algorithm to build the CFG. When 4494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// we process an expression, sometimes we know that we must add the 4594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// subexpressions as block-level expressions. For example: 4694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// exp1 || exp2 4894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// When processing the '||' expression, we know that exp1 and exp2 5094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// need to be added as block-level expressions, even though they 5194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// might not normally need to be. AddStmtChoice records this 5294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then 5394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// the builder has an option not to add a subexpression as a 5494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// block-level expression. 5594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 56852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekclass AddStmtChoice { 57852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekpublic: 58892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; 595ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 6094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} 615ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 623179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek bool alwaysAdd(CFGBuilder &builder, 633179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek const Stmt *stmt) const; 6494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 6594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// Return a copy of this object, except with the 'always-add' bit 6694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// set as specified. 6794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { 683179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); 6994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan } 7094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 71852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekprivate: 7294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan Kind kind; 73852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek}; 746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 75f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope - Node in tree of local scopes created for C++ implicit 76f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// destructor calls generation. It contains list of automatic variables 77f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// declared in the scope and link to position in previous scope this scope 78f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// began in. 79f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 80f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// The process of creating local scopes is as follows: 81f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null), 82f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Before processing statements in scope (e.g. CompoundStmt) create 83f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope object using CFGBuilder::ScopePos as link to previous scope 84f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// and set CFGBuilder::ScopePos to the end of new scope, 8535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points 86f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// at this VarDecl, 87f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every normal (without jump) end of scope add to CFGBlock destructors 88f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// for objects in the current scope, 89f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every jump add to CFGBlock destructors for objects 90f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// between CFGBuilder::ScopePos and local scope position saved for jump 91f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// target. Thanks to C++ restrictions on goto jumps we can be sure that 92f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// jump target position will be on the path to root from CFGBuilder::ScopePos 93f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// (adding any variable that doesn't need constructor to be called to 94f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope can break this assumption), 95f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 96f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiclass LocalScope { 97f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 98fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek typedef BumpVector<VarDecl*> AutomaticVarsTy; 99f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 100f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// const_iterator - Iterates local scope backwards and jumps to previous 10135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski /// scope on reaching the beginning of currently iterated scope. 102f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski class const_iterator { 103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const LocalScope* Scope; 104f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 105f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// VarIter is guaranteed to be greater then 0 for every valid iterator. 106f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Invalid iterator (with null Scope) has VarIter equal to 0. 107f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski unsigned VarIter; 108f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski public: 110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create invalid iterator. Dereferencing invalid iterator is not allowed. 111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Incrementing invalid iterator is allowed and will result in invalid 112f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// iterator. 113f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator() 114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(NULL), VarIter(0) {} 115f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 116f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create valid iterator. In case when S.Prev is an invalid iterator and 117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// I is equal to 0, this will create invalid iterator. 118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator(const LocalScope& S, unsigned I) 119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(&S), VarIter(I) { 120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Iterator to "end" of scope is not allowed. Handle it by going up 121f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // in scopes tree possibly up to invalid iterator in the root. 122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0 && Scope) 123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 124f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 125f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1269c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *const* operator->() const { 127f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (Scope && "Dereferencing invalid iterator is not allowed"); 128f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 129f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return &Scope->Vars[VarIter - 1]; 130f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1319c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *operator*() const { 132f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this->operator->(); 133f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 134f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1359c378f705405d37f49795d5e915989de774fe11fTed Kremenek const_iterator &operator++() { 136f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (!Scope) 137f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 138f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 139f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 140f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski --VarIter; 141f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0) 142f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 143f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 144f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 14535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator operator++(int) { 14635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator P = *this; 14735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski ++*this; 14835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return P; 14935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 150f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1519c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator==(const const_iterator &rhs) const { 152f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return Scope == rhs.Scope && VarIter == rhs.VarIter; 153f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1549c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator!=(const const_iterator &rhs) const { 155f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return !(*this == rhs); 156f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 15735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 15835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski operator bool() const { 15935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return *this != const_iterator(); 16035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 16135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 16235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int distance(const_iterator L); 163f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski }; 164f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 165f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski friend class const_iterator; 166f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 167f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiprivate: 168fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx; 169fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek 170f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Automatic variables in order of declaration. 171f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AutomaticVarsTy Vars; 172f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Iterator to variable in previous scope that was declared just before 173f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// begin of this scope. 174f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator Prev; 175f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 176f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 177f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Constructs empty scope linked to previous scope in specified place. 178fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek LocalScope(BumpVectorContext &ctx, const_iterator P) 179fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek : ctx(ctx), Vars(ctx, 4), Prev(P) {} 180f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 181f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Begin of scope in direction of CFG building (backwards). 182f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator begin() const { return const_iterator(*this, Vars.size()); } 18335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 1849c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addVar(VarDecl *VD) { 185fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Vars.push_back(VD, ctx); 18635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 187f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 188f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 18935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// distance - Calculates distance from this to L. L must be reachable from this 19035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. 19135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// number of scopes between this and L. 19235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderskiint LocalScope::const_iterator::distance(LocalScope::const_iterator L) { 19335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int D = 0; 19435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator F = *this; 19535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski while (F.Scope != L.Scope) { 1965290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek assert (F != const_iterator() 1975290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek && "L iterator is not reachable from F iterator."); 19835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter; 19935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski F = F.Scope->Prev; 20035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 20135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter - L.VarIter; 20235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return D; 20335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski} 20435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 20535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// BlockScopePosPair - Structure for specifying position in CFG during its 20635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// build process. It consists of CFGBlock that specifies position in CFG graph 20735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// and LocalScope::const_iterator that specifies position in LocalScope graph. 208f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskistruct BlockScopePosPair { 2099ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BlockScopePosPair() : block(0) {} 2109c378f705405d37f49795d5e915989de774fe11fTed Kremenek BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos) 2119ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek : block(b), scopePosition(scopePos) {} 212f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2139ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek CFGBlock *block; 2149ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek LocalScope::const_iterator scopePosition; 215f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 216f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 217e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// TryResult - a class representing a variant over the values 218e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, 219e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// and is used by the CFGBuilder to decide if a branch condition 220e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// can be decided up front during CFG construction. 221e71f3d587844110d836c82250830b27b1651afdbTed Kremenekclass TryResult { 222e71f3d587844110d836c82250830b27b1651afdbTed Kremenek int X; 223e71f3d587844110d836c82250830b27b1651afdbTed Kremenekpublic: 224e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 225e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult() : X(-1) {} 226e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 227e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isTrue() const { return X == 1; } 228e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isFalse() const { return X == 0; } 229e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isKnown() const { return X >= 0; } 230e71f3d587844110d836c82250830b27b1651afdbTed Kremenek void negate() { 231e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(isKnown()); 232e71f3d587844110d836c82250830b27b1651afdbTed Kremenek X ^= 0x1; 233e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 234e71f3d587844110d836c82250830b27b1651afdbTed Kremenek}; 235e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 236a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 237fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 238fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 239fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 240fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 241fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 242fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 243fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 244fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 2456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 2466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 2476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 2486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 249c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 250ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 251f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpTarget; 252f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpSource; 253f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 254e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 2556f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CFG> cfg; 256ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 2579c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Block; 2589c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Succ; 259f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget ContinueJumpTarget; 260f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget BreakJumpTarget; 2619c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchTerminatedBlock; 2629c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *DefaultCaseBlock; 2639c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TryTerminatedBlock; 264e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 265f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Current position in local scope. 266f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 267f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 268f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // LabelMap records the mapping from Label expressions to their jump targets. 269ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy; 2700cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 2716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 2736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 274f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef std::vector<JumpSource> BackpatchBlocksTy; 2750cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 2766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 278ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy; 27919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 2806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28149b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu bool badCFG; 282b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &BuildOpts; 283e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 284e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // State to track for building switch statements. 285e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool switchExclusivelyCovered; 2860498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult *switchCond; 2870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 2880d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; 289a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek const Stmt *lastLookup; 29049b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu 2918c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Caches boolean evaluations of expressions to avoid multiple re-evaluations 2928c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // during construction of branches for chained logical operators. 2936955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy; 2946955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy CachedBoolEvals; 2958c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 2966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 297b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek explicit CFGBuilder(ASTContext *astContext, 298b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &buildOpts) 299b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek : Context(astContext), cfg(new CFG()), // crew a new CFG 300b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek Block(NULL), Succ(NULL), 301b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 302b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), 3030d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek switchExclusivelyCovered(false), switchCond(0), 304a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry(0), lastLookup(0) {} 3056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 306d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 307b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement); 3086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3090d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool alwaysAdd(const Stmt *stmt); 3100d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 3124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 313852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 314852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 3154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 316852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 3174f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 318852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 3193fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 32056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, 32156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AddStmtChoice asc); 3223fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 3236960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 3246960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3256960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 3266960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); 3276960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); 3286960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 3296960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3306960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 3316960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3326960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 3336960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 3344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 3359c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitDeclSubExpr(DeclStmt *DS); 3363fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 3373fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 3386960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); 3393fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 3409c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt *G); 3414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 342a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); 3434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 3444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 3456960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc); 3465c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek CFGBlock *VisitLogicalOperator(BinaryOperator *B); 3473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B, 3483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Stmt *Term, 3493f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *TrueBlock, 3503f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *FalseBlock); 351115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 3524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 3534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 3554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 3566960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); 3574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 3584b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); 3596960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitReturnStmt(ReturnStmt *R); 360852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 3614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 3626960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 3636960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 36499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); 3654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 3664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 367852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 368852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 3699c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitChildren(Stmt *S); 37055331da3211151aa67277aa095b7d301342200d4Ted Kremenek CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); 371cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 3728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Visitors to walk an AST and generate destructors of temporaries in 3738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // full expression. 3748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false); 3758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E); 3768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); 3778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, 3788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 37956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock * 38056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E, 38156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool BindToTemporary); 3828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 383274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 3849c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *NYS() { 3854102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 3864102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 3874102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 3886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 3904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 391dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *createNoReturnBlock(); 392d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 393df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 394df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 395852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 396cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt CFGBlock *addInitializer(CXXCtorInitializer *I); 3976a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 3989c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S); 3997c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 400239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 401239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 402239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 403239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4049c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeForStmt(Stmt *S); 4059c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, LocalScope* Scope = NULL); 4069c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = NULL); 407239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4089c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeAndDtors(Stmt *S); 409ad5a894df1841698c824381b414630799adc26caTed Kremenek 410239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 411d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek void appendStmt(CFGBlock *B, const Stmt *S) { 41274fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek if (alwaysAdd(S) && cachedEntry) 4130d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry->second = B; 4140d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 415ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose // All block-level expressions should have already been IgnoreParens()ed. 416ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); 417d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); 418ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 419cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { 42082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 42182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 4227c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 4237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 4247c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4257c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 4267c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 4277c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { 4298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); 4308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 431c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) { 432c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext()); 433c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 434ad5a894df1841698c824381b414630799adc26caTed Kremenek 4359c378f705405d37f49795d5e915989de774fe11fTed Kremenek void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 43653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 43753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 4380a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void addSuccessor(CFGBlock *B, CFGBlock *S) { 439ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 440ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 442e71f3d587844110d836c82250830b27b1651afdbTed Kremenek /// Try and evaluate an expression to an integer constant. 443e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { 444e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 445e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return false; 446e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return !S->isTypeDependent() && 447f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek !S->isValueDependent() && 44851f4708c00110940ca3f337961915f2ca1668375Richard Smith S->EvaluateAsRValue(outResult, *Context); 449e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4510a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 45200998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 4530a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult tryEvaluateBool(Expr *S) { 45485df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (!BuildOpts.PruneTriviallyFalseEdges || 4558c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis S->isTypeDependent() || S->isValueDependent()) 456e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return TryResult(); 4578c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4588c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) { 4598c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 4608c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Check the cache first. 4616955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S); 4626955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi if (I != CachedBoolEvals.end()) 4638c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return I->second; // already in map; 4649260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi 4659260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi // Retrieve result at first, or the map might be updated. 4669260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi TryResult Result = evaluateAsBooleanConditionNoCache(S); 4679260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi CachedBoolEvals[S] = Result; // update or insert 4689260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi return Result; 4698c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4703d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek else { 4713d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek switch (Bop->getOpcode()) { 4723d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek default: break; 4733d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // For 'x & 0' and 'x * 0', we can determine that 4743d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // the value is always false. 4753d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek case BO_Mul: 4763d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek case BO_And: { 4773d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // If either operand is zero, we know the value 4783d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // must be false. 4793d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek llvm::APSInt IntVal; 4803d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) { 4813d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (IntVal.getBoolValue() == false) { 4823d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek return TryResult(false); 4833d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 4843d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 4853d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) { 4863d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (IntVal.getBoolValue() == false) { 4873d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek return TryResult(false); 4883d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 4893d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 4903d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 4913d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek break; 4923d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 4933d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 4948c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4958c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4968c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return evaluateAsBooleanConditionNoCache(S); 4978c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 4988c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 4998c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis /// \brief Evaluate as boolean \param E without using the cache. 5008c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult evaluateAsBooleanConditionNoCache(Expr *E) { 5018c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) { 5028c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 5038c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult LHS = tryEvaluateBool(Bop->getLHS()); 5048c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isKnown()) { 5058c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We were able to evaluate the LHS, see if we can get away with not 5068c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 5078c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 5088c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue(); 5098c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5108c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 5118c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 5128c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->getOpcode() == BO_LOr) 5138c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() || RHS.isTrue(); 5148c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis else 5158c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() && RHS.isTrue(); 5168c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5178c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } else { 5188c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 5198c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 5208c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We can't evaluate the LHS; however, sometimes the result 5218c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. 5228c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 5238c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return RHS.isTrue(); 5248c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5258c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5268c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5278c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 5288c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5298c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5308c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5318c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis bool Result; 5328c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (E->EvaluateAsBooleanCondition(Result, *Context)) 5338c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return Result; 5348c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5358c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 53600998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 537e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 538d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 5396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5400d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekinline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, 5410d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const Stmt *stmt) const { 5420d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return builder.alwaysAdd(stmt) || kind == AlwaysAdd; 5430d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek} 544a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 5450d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekbool CFGBuilder::alwaysAdd(const Stmt *stmt) { 54674fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek bool shouldAdd = BuildOpts.alwaysAdd(stmt); 54774fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek 5480d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!BuildOpts.forcedBlkExprs) 54974fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 550a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 551a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (lastLookup == stmt) { 552a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (cachedEntry) { 553a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry->first == stmt); 554a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek return true; 555a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 55674fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 557a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 5580d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 559a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek lastLookup = stmt; 560a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 561a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // Perform the lookup! 5620d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; 5630d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 564a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (!fb) { 565a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // No need to update 'cachedEntry', since it will always be null. 566a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry == 0); 56774fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 568a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 5690d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 5700d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); 571a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (itr == fb->end()) { 572a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry = 0; 57374fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 574a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 575a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 5760d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry = &*itr; 5770d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return true; 5783179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek} 5793179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 580898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 581898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 582f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCallstatic const VariableArrayType *FindVA(const Type *t) { 583f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { 584f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) 585610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 586610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 5876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 588610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 589610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 5906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 591610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 592610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 5936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 5956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 5966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 5976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 5986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 5999c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { 6000ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 6014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 6024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 603d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 6046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 6056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 6066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 60749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 608ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 60949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 6106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6117c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 6127c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 6137c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 6147c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 615d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 6161b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 6171b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6181b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 6191b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 6201b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 62182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 622b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 62382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 62482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 62582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 62682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 62782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 62882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 629b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 6306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 63182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 63282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 63382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6341b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 6351b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 6361b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 6371b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 638c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 6399c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = I->block; 6409c378f705405d37f49795d5e915989de774fe11fTed Kremenek GotoStmt *G = cast<GotoStmt>(B->getTerminator()); 6411b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 6426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6431b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 6441b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 6451b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 646d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 647f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 6489ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, 6499ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek JT.scopePosition); 6509ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, JT.block); 6511b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 6526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6531b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 6549c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (CFGBlock *B = cfg->getIndirectGotoBlock()) 6551b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 6561b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 6571b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6581b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 6591b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 6601b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6611b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 6621b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 6631b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 6641b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6659ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, LI->second.block); 666c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 6676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 669322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 6706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6711b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 672d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 6736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 674d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 675d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 6769c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::createBlock(bool add_successor) { 6779c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = cfg->createBlock(); 6784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 6790a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(B, Succ); 680d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 681d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 6826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 683dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// createNoReturnBlock - Used to create a block is a 'noreturn' point in the 684dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// CFG. It is *not* connected to the current (global) successor, and instead 685dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// directly tied to the exit block in order to be reachable. 686dba3fb5413437dc613734fa4ffac892b11a37d25Chandler CarruthCFGBlock *CFGBuilder::createNoReturnBlock() { 687dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *B = createBlock(false); 68883754162f698a5dafad93fb89be0953651a604d0Chandler Carruth B->setHasNoReturnElement(); 689dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth addSuccessor(B, &cfg->getExit()); 690dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth return B; 691dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth} 692dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 69382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 694cbb67480094b3bcb5b715acd827cbad55e2a204cSean HuntCFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { 69582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 69682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 69782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 6998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 70082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 7028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 7038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Expr *Init = I->getInit(); 7048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 70500eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet if (FieldDecl *FD = I->getAnyMember()) 7068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = FD->getType()->isReferenceType(); 7074765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 70882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7095a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors && HasTemporaries) { 7108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 7114765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 7128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 7138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 71482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 7158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 7168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 7178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendInitializer(Block, I); 7188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 7198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 720892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek if (HasTemporaries) { 7218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 7228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 723892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 724892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek } 725892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(Init); 7268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 7278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 72882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 72982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 73082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7312d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// \brief Retrieve the type of the temporary object whose lifetime was 7322d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// extended by a local reference with the given initializer. 7332d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregorstatic QualType getReferenceInitTemporaryType(ASTContext &Context, 7342d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor const Expr *Init) { 7352d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (true) { 7362d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip parentheses. 7372d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = Init->IgnoreParens(); 7382d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7392d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through cleanups. 7402d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) { 7412d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = EWC->getSubExpr(); 7422d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7432d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7442d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7452d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through the temporary-materialization expression. 7462d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MaterializeTemporaryExpr *MTE 7472d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor = dyn_cast<MaterializeTemporaryExpr>(Init)) { 7482d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = MTE->GetTemporaryExpr(); 7492d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7502d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7512d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7522d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip derived-to-base and no-op casts. 7532d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const CastExpr *CE = dyn_cast<CastExpr>(Init)) { 7542d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if ((CE->getCastKind() == CK_DerivedToBase || 7552d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_UncheckedDerivedToBase || 7562d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_NoOp) && 7572d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init->getType()->isRecordType()) { 7582d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = CE->getSubExpr(); 7592d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7602d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7612d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7622d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7632d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip member accesses into rvalues. 7642d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) { 7652d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (!ME->isArrow() && ME->getBase()->isRValue()) { 7662d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = ME->getBase(); 7672d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7682d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7692d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7702d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7712d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor break; 7722d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7732d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7742d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor return Init->getType(); 7752d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor} 7762d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 777239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 778239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 779239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 7806a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 7819c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S) { 782239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 7836a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 7846a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 785239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 7866a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 787239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 788c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // We need to append the destructors in reverse order, but any one of them 789c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // may be a no-return destructor which changes the CFG. As a result, buffer 790c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // this sequence up and replay them in reverse order when appending onto the 791c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // CFGBlock(s). 792c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth SmallVector<VarDecl*, 10> Decls; 793c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.reserve(B.distance(E)); 794c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 795c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.push_back(*I); 796c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 797c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(), 798c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth E = Decls.rend(); 799c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth I != E; ++I) { 800c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If this destructor is marked as a no-return destructor, we need to 801c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // create a new block for the destructor which does not have as a successor 802c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far: control won't flow out of this block. 80388237bf587581026dcfc8386abf055cb201aa487Ted Kremenek QualType Ty = (*I)->getType(); 80488237bf587581026dcfc8386abf055cb201aa487Ted Kremenek if (Ty->isReferenceType()) { 8052d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit()); 8062d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 80788237bf587581026dcfc8386abf055cb201aa487Ted Kremenek Ty = Context->getBaseElementType(Ty); 80888237bf587581026dcfc8386abf055cb201aa487Ted Kremenek 809c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); 81023661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) 811dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 812dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 813c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 814c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 815c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth appendAutomaticObjDtor(Block, *I, S); 816c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 817239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 818239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 8197c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 8207c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 8217c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 8227c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 8237c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 8247c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 8257c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8267c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 8277c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 8287c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 8297c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 8307c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 8317c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 8327c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 8337c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8347c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8357c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8367c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 8377c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 8387c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 83923661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!BI->isVirtual()) { 84023661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 84123661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 84223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie autoCreateBlock(); 84323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie appendBaseDtor(Block, BI); 84423661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 84523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 8467c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8477c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8487c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 8497c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 8507c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 8518c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski // Check for constant size array. Set type to array element type. 8528c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QualType QT = FI->getType(); 8538c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 8548c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (AT->getSize() == 0) 8558c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski continue; 8568c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QT = AT->getElementType(); 8578c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski } 8588c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 8598c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 8607c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 8617c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 862581deb3da481053c4993c7600f97acf7768caac5David Blaikie appendMemberDtor(Block, *FI); 8637c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8647c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8657c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 8667c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 867239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 868239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 869239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 870239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 871fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); 872fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Scope = alloc.Allocate<LocalScope>(); 873fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx(alloc); 874fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek new (Scope) LocalScope(ctx, ScopePos); 875239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 876239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 877239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 878239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 879239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 88002acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 8819c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeForStmt(Stmt *S) { 882239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 88302acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 88402acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 88502acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 886239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 887239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 888ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { 889239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 890239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 891a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth Stmt *SI = (*BI)->stripLabelLikeStatements(); 892ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) 893239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 894239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 89502acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 896239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 897239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 898239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 899239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 900a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements())) 901b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 902239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 903239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 904239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 905239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 9069c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS, 907b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 908239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 909239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 910239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 911239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 912239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 9139c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(*DI)) 914239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 915239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 916239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 917239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 918239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 919239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 920239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 921239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 9229c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, 923b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 924239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 925239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 926239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 927239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 928239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 929239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 930239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 931239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 932239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 933239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 934239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 935239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 936239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 937239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 9382d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (QT.getTypePtr()->isReferenceType()) { 93903e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor if (!VD->extendsLifetimeOfTemporary()) 940239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 9412d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 9422d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor QT = getReferenceInitTemporaryType(*Context, VD->getInit()); 943239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 944239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 945b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check for constant size array. Set type to array element type. 9462d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 947b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (AT->getSize() == 0) 948b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski return Scope; 949b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski QT = AT->getElementType(); 950b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski } 9514e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 952b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 9539c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 95423661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 9554e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 9564e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 9574e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 9584e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 9594e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 960239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 961239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 962239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 963239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 964239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 9659c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeAndDtors(Stmt *S) { 966239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 967239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 968239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 969239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 97002acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 971239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 972239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 973239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 97453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 97553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 97653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 97753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 97853de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 979c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// FIXME: This mechanism for adding automatic destructors doesn't handle 980c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// no-return destructors properly. 9819c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 98253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 983c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth BumpVectorContext &C = cfg->getBumpVectorContext(); 984c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth CFGBlock::iterator InsertPos 985c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); 986c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 987c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, 988c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Blk->getTerminator()); 98953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 99053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 9914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 9926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 9936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 9949c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 995f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 996f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 997f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 998f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 999ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 1000ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (Expr *E = dyn_cast<Expr>(S)) 1001ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose S = E->IgnoreParens(); 1002ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 10034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 10044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 1005852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 10064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 1008852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 10091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 101156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); 101256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 10134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 1014852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 10151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 101755331da3211151aa67277aa095b7d301342200d4Ted Kremenek return VisitNoRecurse(cast<Expr>(S), asc); 10184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 10204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 10211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 1023a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 10241de85338543dd6228eb518185e385d94d377f4cbJohn McCall case Stmt::CXXMemberCallExprClass: 10259fcce65e7e1307b5b8da9be13e4092d6bb94dc1dRichard Smith case Stmt::UserDefinedLiteralClass: 1026852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 10271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 10294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 10304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 1032852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 10331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 10354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 10361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 1038852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 10391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 10414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 10421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1043021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 1044021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 1045021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 10464765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall case Stmt::ExprWithCleanupsClass: 10474765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc); 104847e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 1049b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose case Stmt::CXXDefaultArgExprClass: 1050b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // FIXME: The expression inside a CXXDefaultArgExpr is owned by the 1051b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // called function's declaration, not by the caller. If we simply add 1052b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // this expression to the CFG, we could end up with the same Expr 1053b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // appearing multiple times. 1054b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // PR13385 / <rdar://problem/12156507> 1055b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose return VisitStmt(S, asc); 1056b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose 1057a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXBindTemporaryExprClass: 1058a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); 1059a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 106081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXConstructExprClass: 106181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); 106281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 1063a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXFunctionalCastExprClass: 1064a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); 1065a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 106681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXTemporaryObjectExprClass: 106781bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); 106881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 1069021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 1070021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 1071ad5a894df1841698c824381b414630799adc26caTed Kremenek 1072021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 1073021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 1074ad5a894df1841698c824381b414630799adc26caTed Kremenek 1075ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith case Stmt::CXXForRangeStmtClass: 1076ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); 1077ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 10784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 10794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 10801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 10824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 10831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 10854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 10861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 10884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 10891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 10914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 10921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 10944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 10951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1096892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek case Stmt::ImplicitCastExprClass: 1097892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); 1098a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 10994f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 11004f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 11011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 11034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 11041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek case Stmt::LambdaExprClass: 110683748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return VisitLambdaExpr(cast<LambdaExpr>(S), asc); 110783748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 1108115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 1109115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 1110115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 11116a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::NullStmtClass: 11126a9065a39ab15383082b914af28759da1652db18Ted Kremenek return Block; 11136a9065a39ab15383082b914af28759da1652db18Ted Kremenek 11144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 11151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 11161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11178e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek case Stmt::ObjCAutoreleasePoolStmtClass: 11188e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S)); 11198e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 11204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 11214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 11221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 11244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 11251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 11274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 11281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 11304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 11311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11326a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::OpaqueValueExprClass: 11334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11354b9c2d235fb9449e249d74f48ecfec601650de93John McCall case Stmt::PseudoObjectExprClass: 11364b9c2d235fb9449e249d74f48ecfec601650de93John McCall return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S)); 11374b9c2d235fb9449e249d74f48ecfec601650de93John McCall 11384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 11394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 11401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1141f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne case Stmt::UnaryExprOrTypeTraitExprClass: 1142f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), 1143f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne asc); 11441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 1146852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 11471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 11494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 11501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan case Stmt::UnaryOperatorClass: 115299cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan return VisitUnaryOperator(cast<UnaryOperator>(S), asc); 115399cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 11544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 11554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 11564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 11574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1159852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 11603179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, S)) { 11614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1162247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 11636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 11641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 11664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 11699c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) { 1170534986f2b21e6050bf00163cd6423fd92155a6edRichard Smith CFGBlock *lastBlock = Block; 11716b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek for (Stmt::child_range I = Terminator->children(); I; ++I) 11726b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (Stmt *child = *I) 11736b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek if (CFGBlock *b = Visit(child)) 11746b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek lastBlock = b; 11756b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek 11766b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek return lastBlock; 11774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1179852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 1180852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 11814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 11826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11833179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, A)) { 11844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1185247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, A); 11866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 11876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 11884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 11901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 119199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong WanCFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, 1192892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek AddStmtChoice asc) { 11933179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, U)) { 119499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan autoCreateBlock(); 1195247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, U); 119699cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan } 119799cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1198892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(U->getSubExpr(), AddStmtChoice()); 119999cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan} 120099cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 12015c3ea5c57971317c35b120ef0a2a2c79bd171008Ted KremenekCFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) { 12025c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 12035c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek appendStmt(ConfluenceBlock, B); 12041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12055c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (badCFG) 12065c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek return 0; 12071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(B, 0, ConfluenceBlock, ConfluenceBlock).first; 12093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek} 1210862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 12113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenekstd::pair<CFGBlock*, CFGBlock*> 12123f635c08b2d0b2d5bafb38da09589cb238407faaTed KremenekCFGBuilder::VisitLogicalOperator(BinaryOperator *B, 12133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Stmt *Term, 12143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *TrueBlock, 12153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *FalseBlock) { 12163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Introspect the RHS. If it is a nested logical operation, we recursively 12183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // build the CFG using this function. Otherwise, resort to default 12193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // CFG construction behavior. 12203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *RHS = B->getRHS()->IgnoreParens(); 12213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *RHSBlock, *ExitBlock; 12223f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12233f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 12243f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS)) 12253f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B_RHS->isLogicalOp()) { 12263f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(RHSBlock, ExitBlock) = 12273f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock); 12283f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 12293f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 12301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12313f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The RHS is not a nested logical operation. Don't push the terminator 12323f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // down further, but instead visit RHS and construct the respective 12333f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // pieces of the CFG, and link up the RHSBlock with the terminator 12343f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // we have been provided. 12353f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitBlock = RHSBlock = createBlock(false); 12363f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12373f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!Term) { 12383f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(TrueBlock == FalseBlock); 12393f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, TrueBlock); 12403f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 12413f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else { 12423f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek RHSBlock->setTerminator(Term); 12433f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal = tryEvaluateBool(RHS); 12443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, KnownVal.isFalse() ? NULL : TrueBlock); 12453f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, KnownVal.isTrue() ? NULL : FalseBlock); 12463f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 12473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = RHSBlock; 12493f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek RHSBlock = addStmt(RHS); 12505c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } 12513f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek while (false); 12523f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12533f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (badCFG) 12543f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair((CFGBlock*)0, (CFGBlock*)0); 12558c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 12565c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // Generate the blocks for evaluating the LHS. 12573f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *LHS = B->getLHS()->IgnoreParens(); 12583f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12593f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS)) 12603f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B_LHS->isLogicalOp()) { 12613f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B->getOpcode() == BO_LOr) 12623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek FalseBlock = RHSBlock; 12633f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else 12643f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TrueBlock = RHSBlock; 12653f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // For the LHS, treat 'B' as the terminator that we want to sink 12673f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // into the nested branch. The RHS always gets the top-most 12683f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // terminator. 12693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock); 12703f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 12713f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Create the block evaluating the LHS. 12733f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // This contains the '&&' or '||' as the terminator. 12743f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *LHSBlock = createBlock(false); 12753f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek LHSBlock->setTerminator(B); 12763f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12775c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek Block = LHSBlock; 12783f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryLHSBlock = addStmt(LHS); 12793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12803f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (badCFG) 12813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair((CFGBlock*)0, (CFGBlock*)0); 12825c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek 12835c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // See if this is a known constant. 12843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal = tryEvaluateBool(LHS); 12855c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek 12865c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // Now link the LHSBlock with RHSBlock. 12875c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (B->getOpcode() == BO_LOr) { 12883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : TrueBlock); 12893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : RHSBlock); 12905c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } else { 12915c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek assert(B->getOpcode() == BO_LAnd); 12925c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 12933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : FalseBlock); 12945c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } 129500998a068e50945118f334c98af05ed44d7c22a6Mike Stump 12963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair(EntryLHSBlock, ExitBlock); 12975c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek} 12981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13005c3ea5c57971317c35b120ef0a2a2c79bd171008Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 13015c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek AddStmtChoice asc) { 13025c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // && or || 13035c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (B->isLogicalOp()) 13045c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek return VisitLogicalOperator(B); 130536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 130636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->getOpcode() == BO_Comma) { // , 13076dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 1308247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 13094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 13104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 13116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 131236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 131336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->isAssignmentOp()) { 13143179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1315fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 1316247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1317fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 1318892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(B->getLHS()); 1319e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 1320fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 13211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13223179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1323e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 1324247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1325e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 1326e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 1327a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *RBlock = Visit(B->getRHS()); 1328a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *LBlock = Visit(B->getLHS()); 1329a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr 1330a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // containing a DoStmt, and the LHS doesn't create a new block, then we should 1331a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // return RBlock. Otherwise we'll incorrectly return NULL. 1332a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu return (LBlock ? LBlock : RBlock); 13334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 13346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 133555331da3211151aa67277aa095b7d301342200d4Ted KremenekCFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) { 13363179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 1337721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 1338247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 1339721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 1340721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 13414f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1342cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 13434f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 13444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 13454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 1346d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1347d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 13481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 13504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 13514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 13521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 13544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 13559ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (BreakJumpTarget.block) { 13569ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B); 13579ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, BreakJumpTarget.block); 1358f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 13594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 13601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 13634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 13641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13658026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redlstatic bool CanThrow(Expr *E, ASTContext &Ctx) { 13664c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 13674c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 13684c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 13694c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 13704c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 1371ad5a894df1841698c824381b414630799adc26caTed Kremenek 13724c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 13734c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 13744c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 1375b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) && 1376e6975e9b0985ad7f7ff9187e38d95bfe9ac4181bRichard Smith Proto->isNothrow(Ctx)) 13774c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 13784c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 13794c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 13804c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 13814c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1382852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 13831de85338543dd6228eb518185e385d94d377f4cbJohn McCall // Compute the callee type. 13841de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType calleeType = C->getCallee()->getType(); 13851de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (calleeType == Context->BoundMemberTy) { 13861de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType boundType = Expr::findBoundMemberType(C->getCallee()); 13871de85338543dd6228eb518185e385d94d377f4cbJohn McCall 13881de85338543dd6228eb518185e385d94d377f4cbJohn McCall // We should only get a null bound type if processing a dependent 13891de85338543dd6228eb518185e385d94d377f4cbJohn McCall // CFG. Recover by assuming nothing. 13901de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (!boundType.isNull()) calleeType = boundType; 13912455636163fdd18581d7fdae816433f886d88213Mike Stump } 13922455636163fdd18581d7fdae816433f886d88213Mike Stump 13931de85338543dd6228eb518185e385d94d377f4cbJohn McCall // If this is a call to a no-return function, this stops the block here. 13941de85338543dd6228eb518185e385d94d377f4cbJohn McCall bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); 13951de85338543dd6228eb518185e385d94d377f4cbJohn McCall 13964c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 1397079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1398079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 13994e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (Context->getLangOpts().Exceptions) { 14006c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 14014c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 1402079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 1403079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1404079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 14052455636163fdd18581d7fdae816433f886d88213Mike Stump if (FD->hasAttr<NoReturnAttr>()) 14062455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 1407079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 14084c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 1409079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 14102455636163fdd18581d7fdae816433f886d88213Mike Stump 14118026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (!CanThrow(C->getCallee(), *Context)) 14124c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 14134c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 141494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan if (!NoReturn && !AddEHEdge) 141594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan return VisitStmt(C, asc.withAlwaysAdd(true)); 14161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1417079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1418079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1419d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1420079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1421079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 14221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1423dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (NoReturn) 1424dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 1425dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 1426dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createBlock(); 1427dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 1428247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 14292455636163fdd18581d7fdae816433f886d88213Mike Stump 14304c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1431079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1432079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 14330a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 1434079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 14350a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 1436079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 14371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14382455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1439d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1440d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1441852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1442852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 14439c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1444247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1445d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14463fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 14471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 144894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 14493fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 14503fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 14519c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd); 1452d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14533fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 14541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14553fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 14563fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 14579c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd); 1458d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 14593fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 14601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14613fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 146200998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 14630a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 14640a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 14650a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 14663fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 14671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 14683fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 14691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14719c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) { 1472fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 14739c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LastBlock = Block; 14744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 14754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 14764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1477334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1478334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1479334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1480334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 14811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1482e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1483e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 14841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1485079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 14864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 14874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 14881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 148956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallCFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, 1490852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 149156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); 149256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL); 149356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 1494f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1495f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 14969c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1497247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1498d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1499f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 15001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 150194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 1502115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1503f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1504f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1505f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1506f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1507f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1508f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 15099c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = 0; 151056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const Expr *trueExpr = C->getTrueExpr(); 151156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (trueExpr != opaqueValue) { 151256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); 1513d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1514f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1515f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1516f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 1517f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek else 1518f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek LHSBlock = ConfluenceBlock; 15191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1520f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1521f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 15229c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); 1523d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1524f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 15251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152656df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith // If the condition is a logical '&&' or '||', build a more accurate CFG. 152756df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 152856df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens())) 152956df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (Cond->isLogicalOp()) 153056df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first; 153156df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith 1532f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1533f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 15341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 153500998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 15360a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 1537f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 15380a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1539f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 154056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Expr *condExpr = C->getCond(); 1541d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1542f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (opaqueValue) { 1543f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Run the condition expression if it's not trivially expressed in 1544f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // terms of the opaque value (or if there is no opaque value). 1545f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (condExpr != opaqueValue) 1546f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addStmt(condExpr); 1547d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1548f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Before that, run the common subexpression if there was one. 1549f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // At least one of this or the above will be run. 1550f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(BCO->getCommon()); 1551f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek } 1552f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek 1553f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(condExpr); 1554f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1555f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 15564f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 1557bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // Check if the Decl is for an __label__. If so, elide it from the 1558bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // CFG entirely. 1559bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek if (isa<LabelDecl>(*DS->decl_begin())) 1560bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek return Block; 1561bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek 156229c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // This case also handles static_asserts. 15638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (DS->isSingleDecl()) 15648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitDeclSubExpr(DS); 15651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 15671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1568fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose // Build an individual DeclStmt for each decl. 1569fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(), 1570fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose E = DS->decl_rend(); 1571fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose I != E; ++I) { 15724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 15734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 15744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 15751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 15774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 15784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 15794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 15801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 15814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 15821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 15848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = VisitDeclSubExpr(DSNew); 15854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 15861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 15884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 15891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 15918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski/// DeclStmts and initializers in them. 15929c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { 15938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert(DS->isSingleDecl() && "Can handle single declarations only."); 159429c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek Decl *D = DS->getSingleDecl(); 159529c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 159629c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek if (isa<StaticAssertDecl>(D)) { 159729c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // static_asserts aren't added to the CFG because they do not impact 159829c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // runtime semantics. 159929c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek return Block; 160029c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek } 160129c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek 16028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 16031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!VD) { 16058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1606892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 16074f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 16088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 16091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 16118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 16128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 16138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 16148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 16154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 16168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 16178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = VD->getType()->isReferenceType(); 16184765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 16198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 16205a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors && HasTemporaries) { 16218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 16224765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 16238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 16248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 16258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 16268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 16278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1628892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 1629550f2234fc9218914c325041067052342dfce553Ted Kremenek 1630550f2234fc9218914c325041067052342dfce553Ted Kremenek // Keep track of the last non-null block, as 'Block' can be nulled out 1631550f2234fc9218914c325041067052342dfce553Ted Kremenek // if the initializer expression is something like a 'while' in a 1632550f2234fc9218914c325041067052342dfce553Ted Kremenek // statement-expression. 1633550f2234fc9218914c325041067052342dfce553Ted Kremenek CFGBlock *LastBlock = Block; 16341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 1636550f2234fc9218914c325041067052342dfce553Ted Kremenek if (HasTemporaries) { 16378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 16388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 1639550f2234fc9218914c325041067052342dfce553Ted Kremenek ExprWithCleanups *EC = cast<ExprWithCleanups>(Init); 1640550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(EC->getSubExpr())) 1641550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1642550f2234fc9218914c325041067052342dfce553Ted Kremenek } 1643550f2234fc9218914c325041067052342dfce553Ted Kremenek else { 1644550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(Init)) 1645550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1646550f2234fc9218914c325041067052342dfce553Ted Kremenek } 16474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 16481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 1650f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); 1651f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 16524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = addStmt(VA->getSizeExpr()); 16531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1654fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1655fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1656fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1657fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 1658550f2234fc9218914c325041067052342dfce553Ted Kremenek return Block ? Block : LastBlock; 1659d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1660fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 16619c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { 16626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 16636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 16646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 16656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 16666c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 16676c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 16686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 166904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 167004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 167104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 167204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 167304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 167404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 16759c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 167604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 167704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 167804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 167904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 168004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 1681fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // The block we were processing is now finished. Make it the successor 16826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 16836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1684d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1685d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 16864e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1687c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 16886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1689b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 16909c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ElseBlock = Succ; 16916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 16929c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Else = I->getElse()) { 1693d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 16946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1695d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 16966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1697d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 169804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 169904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 170004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 170104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 170204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 170304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 17044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 17056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1706b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1707b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 17084e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1709d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17104e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17114e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1712c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 17136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1714b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 17159c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ThenBlock; 1716d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 17179c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *Then = I->getThen(); 17186db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1719d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 17206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 172104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 172204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 172304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 172404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 172504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 172604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 17274f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 17286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1729dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1730dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1731dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1732dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1733dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 17340a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ThenBlock, sv.get()); 17356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1736d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17374e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 17386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 17390cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1740d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 17413f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by 17423f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // having these handle the actual control-flow jump. Note that 17433f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)" 17443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // we resort to the old control-flow behavior. This special handling 17453f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // removes infeasible paths from the control-flow graph by having the 17463f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // control-flow transfer of '&&' or '||' go directly into the then/else 17473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // blocks directly. 17483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!I->getConditionVariable()) 174956df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 175056df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens())) 17513f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) 17523f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first; 17533f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 17546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1755d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 17566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1757d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1758d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 17596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 176000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 17610a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(I->getCond()); 176200998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1763d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 17640a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 17650a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 17666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 17686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 17696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 177061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek Block = addStmt(I->getCond()); 1771ad5a894df1841698c824381b414630799adc26caTed Kremenek 177261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 177361dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 177461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 177561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 177661dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 1777d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, I->getConditionVariableDeclStmt()); 177861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek addStmt(Init); 177961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 178061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1781ad5a894df1841698c824381b414630799adc26caTed Kremenek 178261dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek return Block; 1783d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 17846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17869c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) { 17876c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1788d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 17896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 17906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 17916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 17926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1793d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1794d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1795d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 17966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1797d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // The Exit block is the only successor. 1798fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 17990a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 18006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 18026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1803852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1804d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 18050cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 18069c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { 1807d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 18084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 1809ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner CFGBlock *LabelBlock = Block; 18106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 18124f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 18136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1814ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner assert(LabelMap.find(L->getDecl()) == LabelMap.end() && 1815ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner "label already in map"); 1816ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); 18176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 18196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 18206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 18216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 18229cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1823d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18244e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1827d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 18286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1829d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1830d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 18316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1832d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1833d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 183431dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 183583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed KremenekCFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { 183683748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *LastBlock = VisitNoRecurse(E, asc); 183783748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), 183883748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek et = E->capture_init_end(); it != et; ++it) { 183983748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Expr *Init = *it) { 184083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *Tmp = Visit(Init); 184183748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Tmp != 0) 184283748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek LastBlock = Tmp; 184383748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 184483748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 184583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return LastBlock; 184683748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek} 184783748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 18489c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { 18496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 18506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 18514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1852d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1853d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 18546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1856d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 18576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1858d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1859d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1860f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1861f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1862f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 18639ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, JT.scopePosition, G); 18649ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, JT.block); 1865f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1866d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 18676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1868d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1869d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 18709c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { 18719c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 18726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 187347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 187447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 187547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 187647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 187747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 187847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 187947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 18809c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Init = F->getInit()) 188147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1882f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1883f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 18849c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = F->getConditionVariable()) 188547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 188647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 188747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 188847575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 188947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1890fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1891fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 1892d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 1893d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18944e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1895d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 18964f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 18974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 18986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18993f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 19003f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 1901f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 190247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 19033f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 19043f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *BodyBlock = 0, *TransitionBlock = 0; 190500998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1906d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 1907d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 19086db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 19096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19103f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Save the current values for Block, Succ, continue and break targets. 19113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 19123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 19136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Create an empty block to represent the transition block for looping back 19153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // to the head of the loop. If we have increment code, it will 19163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // go in this block as well. 19173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = Succ = TransitionBlock = createBlock(false); 19183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TransitionBlock->setLoopTarget(F); 19196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19209c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInc()) { 19216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 19226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 19234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 1924e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 19256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19263575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 19273575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 19283575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 1929d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19304e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19313575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 19323575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 19336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19343f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The starting block for the loop increment is the block that should 19353f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 19363f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 19373f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ContinueJumpTarget.block->setLoopTarget(F); 19386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19393f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Loop body should end with destructor of Condition variable (if any). 19403f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 19413575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 194247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 194347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 194447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 194547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 194647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 19476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 19486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 19493f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = addStmt(F->getBody()); 1950af603f742491dc4707138c0293d295171fdd51baTed Kremenek 19513f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!BodyBlock) { 19523f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // In the case of "for (...;...;...);" we can have a null BodyBlock. 19533f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Use the continue jump target as the proxy for the body. 19543f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = ContinueJumpTarget.block; 19553f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 1956d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 1957941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 19583f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 19593f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 19603f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because of short-circuit evaluation, the condition of the loop can span 19613f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 19623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // evaluate the condition. 19633f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0; 19643f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 19653f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 19663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *C = F->getCond(); 19673f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 19683f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle logical operators, which have a slightly 19693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // more optimal CFG representation. 197056df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 197156df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : 0)) 19723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) { 19733f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(EntryConditionBlock, ExitConditionBlock) = 19743f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor); 19753f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 19763f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 19776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19783f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The default case when not handling logical operators. 19793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = ExitConditionBlock = createBlock(false); 19803f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitConditionBlock->setTerminator(F); 19813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 19823f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // See if this is a known constant. 19833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal(true); 19843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 19853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (C) { 19863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Now add the actual condition to the condition block. 19873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because the condition itself may contain control-flow, new blocks may 19883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // be created. Thus we update "Succ" after adding the condition. 19893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = ExitConditionBlock; 19903f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(C); 19913f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 19923f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // If this block contains a condition variable, add both the condition 19933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // variable and initializer to the CFG. 19943f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (VarDecl *VD = F->getConditionVariable()) { 19953f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Expr *Init = VD->getInit()) { 19963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek autoCreateBlock(); 19973f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek appendStmt(Block, F->getConditionVariableDeclStmt()); 19983f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(Init); 19993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(Block == EntryConditionBlock); 20003f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20013f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20023f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20033f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Block && badCFG) 20043f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 20053f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20063f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek KnownVal = tryEvaluateBool(C); 20073f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Add the loop body entry as a successor to the condition. 20100a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 20113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the condition block with the code that follows the loop. (the 20123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // false branch). 20133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 20146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } while (false); 20163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the loop-back block to the entry condition block. 20183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(TransitionBlock, EntryConditionBlock); 20193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The condition block is the implicit successor for any code above the loop. 20213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Succ = EntryConditionBlock; 20226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2023d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 20246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 20259c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInit()) { 2026d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 202749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 20282bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 202936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 203036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // There is no loop initialization. We are thus basically a while loop. 203136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // NULL out Block to force lazy block construction. 203236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Block = NULL; 203336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Succ = EntryConditionBlock; 203436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return EntryConditionBlock; 2035d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2036d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2037115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 20383179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, M)) { 2039115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 2040247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, M); 2041115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 2042892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(M->getBase()); 2043115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 2044115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 20459c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { 2046514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 2047514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 2048514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2049514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 2050514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2051514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 2052514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2053514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 2054514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 2055514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 2056514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 20574cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 2058514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 2059514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 2060514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 2061514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 2062514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 2063514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 2064514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 2065514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2066514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 2067514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2068514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 2069514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 2070514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2071514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 2072514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 20736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 20746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 20756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 2076514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 20776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20789c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = 0; 20796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2080514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 2081d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20824e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2083514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 2084514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 20854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 20864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 20876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20884cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 20899c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 20906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20914cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 20926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 20936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 20956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 20966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 2097892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(ExitConditionBlock, S); 20984cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 20996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21004cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 2101fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // generate new blocks as necessary. We DON'T add the statement by default to 21026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 2103012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek CFGBlock *EntryConditionBlock = Visit(S->getElement(), 2104012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek AddStmtChoice::NotAlwaysAdd); 21056d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 2106d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21074e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21084e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 21094e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 21106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 21126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 21134cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 21146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21154cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 21166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 21174cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 2118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Succ(Succ); 2119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 21216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 2123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 21246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21259c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(S->getBody()); 21266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21274cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 21284cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;" 21294e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2130d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21314e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 21324e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 21336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21344cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 21350a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, BodyBlock); 21364cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 21376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21384cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 21394cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 21400a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopSuccessor); 21414cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 2142514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 21434cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 2144514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 21456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 21466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21478e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted KremenekCFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { 21488e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // Inline the body. 21498e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return addStmt(S->getSubStmt()); 21508e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // TODO: consider adding cleanups for the end of @autoreleasepool scope. 21518e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek} 21528e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 21539c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 2154b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 21556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2156b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 21574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 21586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2159da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 2160da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 2161da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 2162d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2163da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 21646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2165da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 2166fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 2167da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 21686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21694beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 21704beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 2171247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 21724beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 2173b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 21744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 2175b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 21766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21779c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { 21784f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 217990658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 2180e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 2181514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 21824b9c2d235fb9449e249d74f48ecfec601650de93John McCallCFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { 21834b9c2d235fb9449e249d74f48ecfec601650de93John McCall autoCreateBlock(); 21844b9c2d235fb9449e249d74f48ecfec601650de93John McCall 21854b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Add the PseudoObject as the last thing. 21864b9c2d235fb9449e249d74f48ecfec601650de93John McCall appendStmt(Block, E); 21874b9c2d235fb9449e249d74f48ecfec601650de93John McCall 21884b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *lastBlock = Block; 21894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 21904b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Before that, evaluate all of the semantics in order. In 21914b9c2d235fb9449e249d74f48ecfec601650de93John McCall // CFG-land, that means appending them in reverse order. 21924b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (unsigned i = E->getNumSemanticExprs(); i != 0; ) { 21934b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *Semantic = E->getSemanticExpr(--i); 21944b9c2d235fb9449e249d74f48ecfec601650de93John McCall 21954b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If the semantic is an opaque value, we're being asked to bind 21964b9c2d235fb9449e249d74f48ecfec601650de93John McCall // it to its source expression. 21974b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) 21984b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantic = OVE->getSourceExpr(); 21994b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22004b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (CFGBlock *B = Visit(Semantic)) 22014b9c2d235fb9449e249d74f48ecfec601650de93John McCall lastBlock = B; 22024b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 22034b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22044b9c2d235fb9449e249d74f48ecfec601650de93John McCall return lastBlock; 22054b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 22064b9c2d235fb9449e249d74f48ecfec601650de93John McCall 22079c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { 22089c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 22096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 221005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 221105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 221205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 221305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 221405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 221505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 2216f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 22179c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 221805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 221905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 222005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 2221f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2222fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 2223fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 2224d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2225d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22264e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2227d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 22286b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek Block = 0; 22293f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } else { 22304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 223149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 22326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22333f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *BodyBlock = 0, *TransitionBlock = 0; 223400998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2235d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 2236d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 2237f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 2238d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 22393f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Save the current values for Block, Succ, continue and break targets. 2240f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2241f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 22423f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek save_break(BreakJumpTarget); 2243f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 22446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 22456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 22463f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Succ = TransitionBlock = createBlock(false); 22473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TransitionBlock->setLoopTarget(W); 2248f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 22496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2250d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 225105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 22526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 225305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 225405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 225505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 225605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 225705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 225805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 225905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 226005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2261d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 22623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = addStmt(W->getBody()); 22636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2264af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 22659ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;" 22663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else if (Block && badCFG) 22673f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 22683f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 22693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 22703f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because of short-circuit evaluation, the condition of the loop can span 22713f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 22723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // evaluate the condition. 22733f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0; 22743f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 22753f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 22763f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *C = W->getCond(); 22773f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 22783f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle logical operators, which have a slightly 22793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // more optimal CFG representation. 228056df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens())) 22813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) { 22823f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(EntryConditionBlock, ExitConditionBlock) = 22833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(Cond, W, BodyBlock, 22843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek LoopSuccessor); 22853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 22863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 22873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 22883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The default case when not handling logical operators. 22893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = ExitConditionBlock = createBlock(false); 22903f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitConditionBlock->setTerminator(W); 22913f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 22923f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Now add the actual condition to the condition block. 22933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because the condition itself may contain control-flow, new blocks may 22943f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // be created. Thus we update "Succ" after adding the condition. 22953f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = ExitConditionBlock; 22963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = EntryConditionBlock = addStmt(C); 22973f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 22983f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // If this block contains a condition variable, add both the condition 22993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // variable and initializer to the CFG. 23003f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 23013f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Expr *Init = VD->getInit()) { 23023f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek autoCreateBlock(); 23033f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek appendStmt(Block, W->getConditionVariableDeclStmt()); 23043f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(Init); 23053f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(Block == EntryConditionBlock); 23063f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 23074e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 23086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Block && badCFG) 23103f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 23113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // See if this is a known constant. 23133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C); 23143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 2315941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 23160a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 23173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the condition block with the code that follows the loop. (the 23183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // false branch). 23193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 23203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } while(false); 23226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23233f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the loop-back block to the entry condition block. 23243f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(TransitionBlock, EntryConditionBlock); 23256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 23276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 2328d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 23296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23304ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 23315482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 233249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 2333d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 23341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 23369c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { 23374f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 23384f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 23394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 23404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 23416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23429c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { 23432fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 23442fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 23456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23466c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2347d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 23496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23502fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 23512fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 23526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23532fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 23540a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 23556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 23576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 2358852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 23592fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 2360989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 23619c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { 23626c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2363d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23640979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 23650979d80615df97c675423de631c1b884819f4712Mike Stump 23660979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 23670979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 23680979d80615df97c675423de631c1b884819f4712Mike Stump 23695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 23705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 23710a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 2372ad5a894df1841698c824381b414630799adc26caTed Kremenek else 23735d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 23740a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 23750979d80615df97c675423de631c1b884819f4712Mike Stump 23760979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 23770979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 2378852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 23790979d80615df97c675423de631c1b884819f4712Mike Stump} 23800979d80615df97c675423de631c1b884819f4712Mike Stump 23819c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { 23829c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 23836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23848f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 23858f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 2386d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2387d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23884e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2389d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 23904f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 23914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 23926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 23946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 23956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 23969c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 23979c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 23986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 239949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 24006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 24016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 24036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 24049c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) { 240549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 240649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 24074e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2408d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24094e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 24104e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 241149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 24126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24135482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 241449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 241549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 241600998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 24170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(D->getCond()); 241800998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2419d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 24209c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = NULL; 2421d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 24226db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 24236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2424d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2425f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2426f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2427f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 24286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2429d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 2430f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 24316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2432d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 2433f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 24346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2435d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2436b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 24376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 243805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 243905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 244005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 244105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 244205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2443d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 24444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 24456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2446af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 2447a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 24484e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2449d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24504e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 24514e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 24526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2453d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 2454d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 2455d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 2456d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 2457d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 2458d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 2459d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 2460d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 2461d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 2462d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 2463d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 2464d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 24650a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopBackBlock); 2466d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 2467d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 24680a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, NULL); 2469b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 24706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2471941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 2472941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 24730a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 24746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 24766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 2477d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 24786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2479d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 24805482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 2481d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 2482d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2483d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 24849c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { 2485d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 2486d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 2487d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2488d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 24896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2490d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 2491d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 2492d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 24936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2494d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 2495235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 24969ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (ContinueJumpTarget.block) { 24979ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C); 24989ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, ContinueJumpTarget.block); 2499f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 2500235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 25016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2502d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 2503d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 25041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2505f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter CollingbourneCFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 2506f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc) { 250713fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 25083179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 250913fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2510892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, E); 251113fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 25121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 251497e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek CFGBlock *lastBlock = Block; 251597e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek 25164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 2517f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); 25184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 251997e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek lastBlock = addStmt(VA->getSizeExpr()); 2520f91a5b008d1a63630ae483247204c2651e512fa1Ted Kremenek } 252197e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek return lastBlock; 2522d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 25231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 25254f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 25269c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 25273179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, SE)) { 252813fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2529892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, SE); 253013fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 25314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 25324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2533d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 25349c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { 25356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 25366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 25379c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchSuccessor = NULL; 25386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25398ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 25408ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 25418ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 25428ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 25438ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 25448ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 25459c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 25468ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 25478ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 25488ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 25498ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 25508ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2551d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2552d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25534e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2554d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 25556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2556d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2557d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2558d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2559eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2560f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2561eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 25626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 25636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 25646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2565eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 25666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2567d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2568d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 25696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2570d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2571d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2572d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2573f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 25746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 25766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 25776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 25786db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 257949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 25808ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2581e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // For pruning unreachable case statements, save the current state 2582e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // for tracking the condition value. 2583e71f3d587844110d836c82250830b27b1651afdbTed Kremenek SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered, 2584e71f3d587844110d836c82250830b27b1651afdbTed Kremenek false); 25850498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2586e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Determine if the switch condition can be explicitly evaluated. 2587e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 25880498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult result; 2589e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek bool b = tryEvaluate(Terminator->getCond(), result); 2590e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, 2591e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek b ? &result : 0); 25920498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 25938ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 25948ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 25958ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 25968ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 25978ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2598d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 25994e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2600d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 26014e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 26024e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 260349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 26046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 2605432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // following the switch body. Moreover, take into account if all the 2606432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // cases of a switch are covered (e.g., switching on an enum value). 2607e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2608432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek switchExclusivelyCovered || Terminator->isAllEnumCasesCovered() 2609432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek ? 0 : DefaultCaseBlock); 26106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 261149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2612411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 2613d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 26146b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek Block = addStmt(Terminator->getCond()); 2615ad5a894df1841698c824381b414630799adc26caTed Kremenek 26166b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 26176b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 26186b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 26196b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 26206b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 2621d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, Terminator->getConditionVariableDeclStmt()); 26226b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek addStmt(Init); 26236b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 26246b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2625ad5a894df1841698c824381b414630799adc26caTed Kremenek 26266b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek return Block; 2627d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2628e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2629e71f3d587844110d836c82250830b27b1651afdbTed Kremenekstatic bool shouldAddCase(bool &switchExclusivelyCovered, 2630e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const Expr::EvalResult *switchCond, 2631e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const CaseStmt *CS, 2632e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ASTContext &Ctx) { 2633e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (!switchCond) 2634e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek return true; 2635e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek 2636e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool addCase = false; 26370498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2638e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!switchExclusivelyCovered) { 2639e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (switchCond->Val.isInt()) { 2640e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the LHS of the case value. 264185df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx); 2642e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const llvm::APSInt &condInt = switchCond->Val.getInt(); 2643e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2644e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (condInt == lhsInt) { 2645e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2646e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2647e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2648e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else if (condInt < lhsInt) { 2649e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (const Expr *RHS = CS->getRHS()) { 2650e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the RHS of the case value. 265185df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx); 265285df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (V2 <= condInt) { 2653e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2654e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2655e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2656e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2657e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2658e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2659e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else 2660e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2661e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2662e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return addCase; 2663e71f3d587844110d836c82250830b27b1651afdbTed Kremenek} 2664d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 26659c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) { 26666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 26676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 26680fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 26690498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 26700fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 26710fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 26720fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 26730fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 26740fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 26750a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek CFGBlock *currentBlock = createBlock(false); 26760a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek currentBlock->setLabel(CS); 26770fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 26780fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 26790a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, currentBlock); 26800fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 26810a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TopBlock = currentBlock; 26820fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2683e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2684e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2685e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2686e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? currentBlock : 0); 26870fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2688e71f3d587844110d836c82250830b27b1651afdbTed Kremenek LastBlock = currentBlock; 26890fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 26900fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 26910fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 269229ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 26930fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 26940fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 26951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26969c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CaseBlock = Block; 26974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 26984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 26996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 27016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 27024f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 27034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2704d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 27054e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 27066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 27086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 27094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2710e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2711e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2712e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2713e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? CaseBlock : 0); 27146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2715d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2716d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 27176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27180fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 27190a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, CaseBlock); 27200fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 272136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 27220fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 27230fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 27240fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 27256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27260fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2727d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 27286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27299c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) { 27304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 27314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 27321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2733eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 27344f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 27354f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 27364f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 27376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 27396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2740411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 27411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2742d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 27434e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2744eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 27456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 27466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 27476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 27486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 27496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 27506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2751eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2752eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 27536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2754eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2755eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 27566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 27576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2758295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2759d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 27605d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 27615d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 27625d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 27639c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TrySuccessor = NULL; 27645d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 27655d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2766d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 27675d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 27685d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 27695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 27705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2771a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 27725d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 27735d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2774f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 27755d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2776f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 27775d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2778a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 27795d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 27805d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 27815d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 27825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2783a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2784a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2785a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 27865d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 27875d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 27885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 27895d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 27905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 27915d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 27920a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, CatchBlock); 27935d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2794a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2795a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 27960a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2797a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 27980a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2799a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 28005d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28015d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 28025d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 28035d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2804f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2805f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock, NewTryTerminatedBlock); 2806f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek cfg->addTryDispatchBlock(TryTerminatedBlock); 2807f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 28086db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 28095d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 28103fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek Block = addStmt(Terminator->getTryBlock()); 28115d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return Block; 28125d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 28135d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28149c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { 28155d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 28165d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 28175d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28180e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 28190e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 28200e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 28210e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 28220e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 28230e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 28249c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = CS->getExceptionDecl()) { 28250e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 28260e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 28270e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 28280e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 28290e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 28305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 28315d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 28325d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28339c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CatchBlock = Block; 28345d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 28355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 2836337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2837337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // CXXCatchStmt is more than just a label. They have semantic meaning 2838337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // as well, as they implicitly "initialize" the catch variable. Add 2839337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // it to the CFG as a CFGElement so that the control-flow of these 2840337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // semantics gets captured. 2841337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek appendStmt(CatchBlock, CS); 2842337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2843337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Also add the CXXCatchStmt as a label, to mirror handling of regular 2844337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // labels. 28455d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 28465d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2847337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Bail out if the CFG is bad. 2848d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 28495d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 28505d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 28525d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 28535d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 28555d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 28565d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28579c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { 2858ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // C++0x for-range statements are specified as [stmt.ranged]: 2859ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // 2860ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // { 2861ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // auto && __range = range-init; 2862ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for ( auto __begin = begin-expr, 2863ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __end = end-expr; 2864ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __begin != __end; 2865ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // ++__begin ) { 2866ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for-range-declaration = *__begin; 2867ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // statement 2868ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2869ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2870ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2871ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save local scope position before the addition of the implicit variables. 2872ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 2873ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2874ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Create local scopes and destructors for range, begin and end variables. 2875ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *Range = S->getRangeStmt()) 2876ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(Range); 2877ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *BeginEnd = S->getBeginEndStmt()) 2878ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(BeginEnd); 2879ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S); 2880ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2881ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LocalScope::const_iterator ContinueScopePos = ScopePos; 2882ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2883ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // "for" is a control-flow statement. Thus we stop processing the current 2884ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // block. 28859c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 2886ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Block) { 2887ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2888ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2889ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Block; 2890ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } else 2891ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Succ; 2892ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2893ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current value for the break targets. 2894ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // All breaks should go to the code following the loop. 2895ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2896ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 2897ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2898ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The block for the __begin != __end expression. 28999c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConditionBlock = createBlock(false); 2900ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ConditionBlock->setTerminator(S); 2901ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2902ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now add the actual condition to the condition block. 2903ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Expr *C = S->getCond()) { 2904ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = ConditionBlock; 2905ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *BeginConditionBlock = addStmt(C); 2906ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2907ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2908ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(BeginConditionBlock == ConditionBlock && 2909ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith "condition block in for-range was unexpectedly complex"); 2910ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith (void)BeginConditionBlock; 2911ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2912ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2913ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The condition block is the implicit successor for the loop body as well as 2914ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // any code above the loop. 2915ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = ConditionBlock; 2916ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2917ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // See if this is a known constant. 2918ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith TryResult KnownVal(true); 2919ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2920ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (S->getCond()) 2921ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith KnownVal = tryEvaluateBool(S->getCond()); 2922ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2923ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now create the loop body. 2924ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith { 2925ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(S->getBody()); 2926ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2927ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current values for Block, Succ, and continue targets. 2928ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2929ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 2930ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2931ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Generate increment code in its own basic block. This is the target of 2932ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // continue statements. 2933ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2934ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = addStmt(S->getInc()); 2935ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 2936ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2937ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The starting block for the loop increment is the block that should 2938ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // represent the 'loop target' for looping back to the start of the loop. 2939ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget.block->setLoopTarget(S); 2940ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2941ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Finish up the increment block and prepare to start the loop body. 2942ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(Block); 2943ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2944ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2945ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 2946ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2947ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2948ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add implicit scope and dtors for loop variable. 2949ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeAndDtors(S->getLoopVarStmt()); 2950ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2951ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Populate a new block to contain the loop body and loop variable. 2952ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getBody()); 2953ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2954ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2955ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = addStmt(S->getLoopVarStmt()); 2956ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 2957ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 2958ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2959ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // This new body block is a successor to our condition block. 2960ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : Block); 2961ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 2962ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2963ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Link up the condition block with the code that follows the loop (the 2964ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // false branch). 2965ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor); 2966ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2967ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add the initialization statements. 2968ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = createBlock(); 2969b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith addStmt(S->getBeginEndStmt()); 2970b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith return addStmt(S->getRangeStmt()); 2971ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith} 2972ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 29734765fa05b5652fcc4356371c2f481d0ea9a1b007John McCallCFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, 29748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc) { 29755a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors) { 29768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If adding implicit destructors visit the full expression for adding 29778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // destructors of temporaries. 29788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(E->getSubExpr()); 29798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 29808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Full expression has to be added as CFGStmt so it will be sequenced 29818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before destructors of it's temporaries. 298294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(true); 29838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 29848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(E->getSubExpr(), asc); 29858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 29868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 2987a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 2988a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 29893179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 2990a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 2991247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 2992a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 2993a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 299494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 2995a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 2996a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 2997a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 2998a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 299981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, 300081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 300181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 300297a72c35a62304c3781aa280e28cb97a59afd585Zhongxing Xu appendStmt(Block, C); 300394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 300481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 300581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 300681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 3007a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 3008a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 30093179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3010a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3011247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3012a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 301394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 3014a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3015a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 3016a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3017a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 301881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 301981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 302081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 3021247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 302281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 302381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 302481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 3025a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, 3026a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 30273179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3028a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3029247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3030a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3031892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(E->getSubExpr(), AddStmtChoice()); 3032a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3033a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 30349c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) { 30356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 30369c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *IBlock = cfg->getIndirectGotoBlock(); 30376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 303819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 303919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 304019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 304119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 30426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 304319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 304419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 3045d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 30464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 30474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 304819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 304919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 30500a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, IBlock); 305119bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 305219bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 305319bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 30548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) { 30555a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors); 30565a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose 30578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskitryAgain: 30588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!E) { 30598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski badCFG = true; 30608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 30618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski switch (E->getStmtClass()) { 30638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski default: 30648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitChildrenForTemporaryDtors(E); 30658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::BinaryOperatorClass: 30678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E)); 30688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXBindTemporaryExprClass: 30708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXBindTemporaryExprForTemporaryDtors( 30718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<CXXBindTemporaryExpr>(E), BindToTemporary); 30728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 307356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 30748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ConditionalOperatorClass: 30758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitConditionalOperatorForTemporaryDtors( 307656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall cast<AbstractConditionalOperator>(E), BindToTemporary); 30778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ImplicitCastExprClass: 30798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For implicit cast we want BindToTemporary to be passed further. 30808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<CastExpr>(E)->getSubExpr(); 30818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 30828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ParenExprClass: 30848599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<ParenExpr>(E)->getSubExpr(); 30858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 308603e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor 308703e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor case Stmt::MaterializeTemporaryExprClass: 308803e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(); 308903e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor goto tryAgain; 30908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 30918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 30928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 30938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { 30948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // When visiting children for destructors we want to visit them in reverse 30958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. Because there's no reverse iterator for children must to reverse 30968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // them in helper vector. 30975f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<Stmt *, 4> ChildrenVect; 30988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ChildrenVect ChildrenRev; 30997502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range I = E->children(); I; ++I) { 31008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (*I) ChildrenRev.push_back(*I); 31018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = Block; 31048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(), 31058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski L = ChildrenRev.rend(); I != L; ++I) { 31068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (CFGBlock *R = VisitForTemporaryDtors(*I)) 31078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = R; 31088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 31108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 31118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { 31138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->isLogicalOp()) { 31148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors for temporaries in LHS expression should be called after 31158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // those for RHS expression. Even if this will unnecessarily create a block, 31168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // this block will be used at least by the full expression. 31178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 31188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); 31198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 31208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 31218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 31238599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 31248599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 31258599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (RHSBlock) { 31278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 31288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 31298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If RHS expression did produce destructors we need to connect created 31318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // blocks to CFG in same manner as for binary operator itself. 31328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = createBlock(false); 31338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock->setTerminator(CFGTerminator(E, true)); 31348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For binary operator LHS block is before RHS in list of predecessors 31368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // of ConfluenceBlock. 31378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), 31388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConfluenceBlock->pred_end()); 31398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 31410a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(E->getLHS()); 31428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) 31438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski KnownVal.negate(); 31448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Link LHSBlock with RHSBlock exactly the same way as for binary operator 31468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // itself. 31478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getOpcode() == BO_LOr) { 31480a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 31490a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 31508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 31518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert (E->getOpcode() == BO_LAnd); 31520a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 31530a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 31548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = LHSBlock; 31578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock; 31588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 31618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return ConfluenceBlock; 31628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 316436f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (E->isAssignmentOp()) { 31658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For assignment operator (=) LHS expression is visited 31668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before RHS expression. For destructors visit them in reverse order. 31678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 31688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 31698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock ? LHSBlock : RHSBlock; 31708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For any other binary operator RHS expression is visited before 31738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // LHS expression (order of children). For destructors visit them in reverse 31748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. 31758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 31768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 31778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return RHSBlock ? RHSBlock : LHSBlock; 31788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 31798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( 31818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *E, bool BindToTemporary) { 31828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for temporaries in subexpression. 31838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr()); 3184249c9458e2cc5b671634baefe8517d7598883a20Zhongxing Xu if (!BindToTemporary) { 31858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If lifetime of temporary is not prolonged (by assigning to constant 31868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // reference) add destructor for it. 3187c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 3188c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If the destructor is marked as a no-return destructor, we need to create 3189c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // a new block for the destructor which does not have as a successor 3190c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far. Control won't flow out of this block. 3191c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor(); 3192dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) 3193dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 3194dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 3195c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 3196c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 31978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendTemporaryDtor(Block, E); 31988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = Block; 31998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 32018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 32028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( 320456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AbstractConditionalOperator *E, bool BindToTemporary) { 32058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for condition expression. Even if this will 32068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // unnecessarily create a block, this block will be used at least by the full 32078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // expression. 32088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 32098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); 32108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 321256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (BinaryConditionalOperator *BCO 321356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall = dyn_cast<BinaryConditionalOperator>(E)) { 321456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); 32158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 32178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 321956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall // Try to add block with destructors for LHS expression. 322056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *LHSBlock = NULL; 322156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Succ = ConfluenceBlock; 322256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Block = NULL; 322356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); 322456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (badCFG) 322556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return NULL; 322656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 32278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for RHS expression; 32288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 32298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 323056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), 323156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall BindToTemporary); 32328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 32348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32358599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock && !LHSBlock) { 32368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If neither LHS nor RHS expression had temporaries to destroy don't create 32378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // more blocks. 32388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 32398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 32408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = createBlock(false); 32438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block->setTerminator(CFGTerminator(E, true)); 32448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 32460a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(E->getCond()); 32478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (LHSBlock) { 32490a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 32508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (KnownVal.isFalse()) { 32510a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, NULL); 32528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 32530a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, ConfluenceBlock); 32548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); 32558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock) 32588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski RHSBlock = ConfluenceBlock; 32590a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 32608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 32628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 32638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3264befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 3265026473c2175424a039f51ca8949937268721b965Ted Kremenek 32666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 32676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 32686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 32699c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFG::createBlock() { 3270026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 3271026473c2175424a039f51ca8949937268721b965Ted Kremenek 3272026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 3273ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 327402f34c5003b2c5067675f89ffce0a84c28faf722Anna Zaks new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this); 3275ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 3276026473c2175424a039f51ca8949937268721b965Ted Kremenek 3277026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 3278ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 3279ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 3280026473c2175424a039f51ca8949937268721b965Ted Kremenek 3281026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 3282ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 3283026473c2175424a039f51ca8949937268721b965Ted Kremenek} 3284026473c2175424a039f51ca8949937268721b965Ted Kremenek 3285026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 3286026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 32879c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFG::buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, 3288b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const BuildOptions &BO) { 3289b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFGBuilder Builder(C, BO); 3290b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek return Builder.buildCFG(D, Statement); 3291fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 3292fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 3293c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekconst CXXDestructorDecl * 3294c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed KremenekCFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { 3295c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek switch (getKind()) { 3296c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Invalid: 3297c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Statement: 3298c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Initializer: 3299c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek llvm_unreachable("getDestructorDecl should only be used with " 3300c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek "ImplicitDtors"); 3301c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::AutomaticObjectDtor: { 3302c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const VarDecl *var = cast<CFGAutomaticObjDtor>(this)->getVarDecl(); 3303c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = var->getType(); 3304697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek ty = ty.getNonReferenceType(); 33054cf225382a8b061dce41733c962d62b6db9721f8Ted Kremenek while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { 3306c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek ty = arrayType->getElementType(); 3307c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek } 3308c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const RecordType *recordType = ty->getAs<RecordType>(); 3309c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXRecordDecl *classDecl = 3310697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek cast<CXXRecordDecl>(recordType->getDecl()); 3311c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return classDecl->getDestructor(); 3312c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3313c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::TemporaryDtor: { 3314c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXBindTemporaryExpr *bindExpr = 3315c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek cast<CFGTemporaryDtor>(this)->getBindTemporaryExpr(); 3316c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXTemporary *temp = bindExpr->getTemporary(); 3317c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return temp->getDestructor(); 3318c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3319c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::BaseDtor: 3320c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::MemberDtor: 3321c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3322c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // Not yet supported. 3323c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return 0; 3324c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3325697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek llvm_unreachable("getKind() returned bogus value"); 3326c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek} 3327c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3328c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekbool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { 3329a08e7bc74b5635995fc50009f240dd3feb1999e2Francois Pichet if (const CXXDestructorDecl *decl = getDestructorDecl(astContext)) { 3330a08e7bc74b5635995fc50009f240dd3feb1999e2Francois Pichet QualType ty = decl->getType(); 3331c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return cast<FunctionType>(ty)->getNoReturnAttr(); 3332c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3333c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return false; 33343c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek} 33353c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 333663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 333763f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek// CFG: Queries for BlkExprs. 333863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 333963f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 334063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremeneknamespace { 334186946745225096243f6969dc745267b78fc211a6Ted Kremenek typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy; 334263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 334363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 3344f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenekstatic void FindSubExprAssignments(const Stmt *S, 3345f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek llvm::SmallPtrSet<const Expr*,50>& Set) { 33468a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!S) 334733d4aab80f31bd06257526fe2883ea920529456bTed Kremenek return; 33486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3349f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek for (Stmt::const_child_range I = S->children(); I; ++I) { 3350f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *child = *I; 33518a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek if (!child) 33528a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek continue; 3353ad5a894df1841698c824381b414630799adc26caTed Kremenek 3354f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(child)) 335533d4aab80f31bd06257526fe2883ea920529456bTed Kremenek if (B->isAssignmentOp()) Set.insert(B); 33566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33578a69366a1cd8fe1e9fd312048c0d5ce58eabeeb2Ted Kremenek FindSubExprAssignments(child, Set); 335833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 335933d4aab80f31bd06257526fe2883ea920529456bTed Kremenek} 336033d4aab80f31bd06257526fe2883ea920529456bTed Kremenek 336163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekstatic BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { 336263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = new BlkExprMapTy(); 33636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Look for assignments that are used as subexpressions. These are the only 33656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // assignments that we want to *possibly* register as a block-level 33666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression. Basically, if an assignment occurs both in a subexpression and 33676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // at the block-level, it is a block-level expression. 3368f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek llvm::SmallPtrSet<const Expr*,50> SubExprAssignments; 33696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 337063f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) 3371ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) 33723c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = BI->getAs<CFGStmt>()) 33733c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek FindSubExprAssignments(S->getStmt(), SubExprAssignments); 337486946745225096243f6969dc745267b78fc211a6Ted Kremenek 3375411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { 33766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 33776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Iterate over the statements again on identify the Expr* and Stmt* at the 33786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block-level that are block-level expressions. 3379411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 3380b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { 33813c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CFGStmt *CS = BI->getAs<CFGStmt>(); 33823c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (!CS) 3383b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu continue; 3384f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const Expr *Exp = dyn_cast<Expr>(CS->getStmt())) { 3385ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert((Exp->IgnoreParens() == Exp) && "No parens on block-level exps"); 33866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3387f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) { 338833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek // Assignment expressions that are not nested within another 33896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // expression are really "statements" whose value is never used by 33906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // another expression. 3391411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) 339233d4aab80f31bd06257526fe2883ea920529456bTed Kremenek continue; 33939c378f705405d37f49795d5e915989de774fe11fTed Kremenek } else if (const StmtExpr *SE = dyn_cast<StmtExpr>(Exp)) { 33946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Special handling for statement expressions. The last statement in 33956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the statement expression is also a block-level expr. 33969c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CompoundStmt *C = SE->getSubStmt(); 339786946745225096243f6969dc745267b78fc211a6Ted Kremenek if (!C->body_empty()) { 3398ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose const Stmt *Last = C->body_back(); 3399ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (const Expr *LastEx = dyn_cast<Expr>(Last)) 3400ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose Last = LastEx->IgnoreParens(); 340133d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3402ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[Last] = x; 340386946745225096243f6969dc745267b78fc211a6Ted Kremenek } 340486946745225096243f6969dc745267b78fc211a6Ted Kremenek } 3405e2dcd783a04f654c50bd8b13fb08a440afbd67e7Ted Kremenek 340633d4aab80f31bd06257526fe2883ea920529456bTed Kremenek unsigned x = M->size(); 3407411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek (*M)[Exp] = x; 340833d4aab80f31bd06257526fe2883ea920529456bTed Kremenek } 3409b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 34106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3411411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek // Look at terminators. The condition is a block-level expression. 34126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34139c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *S = (*I)->getTerminatorCondition(); 34146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3415390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek if (S && M->find(S) == M->end()) { 3416ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose unsigned x = M->size(); 3417ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose (*M)[S] = x; 3418411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 3419411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 34206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 342186946745225096243f6969dc745267b78fc211a6Ted Kremenek return M; 342263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 342363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 34249c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt *S) { 342586946745225096243f6969dc745267b78fc211a6Ted Kremenek assert(S != NULL); 342663f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } 34276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 342863f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap); 342986946745225096243f6969dc745267b78fc211a6Ted Kremenek BlkExprMapTy::iterator I = M->find(S); 34303fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); 343163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 34327dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 343363f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenekunsigned CFG::getNumBlkExprs() { 343463f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap)) 343563f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek return M->size(); 343636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 343736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // We assume callers interested in the number of BlkExprs will want 343836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // the map constructed if it doesn't already exist. 343936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan BlkExprMap = (void*) PopulateBlkExprMap(*this); 344036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size(); 344163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 344263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek 3443274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3444ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 3445ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3446ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3447ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 3448be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 3449ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 34506e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (To && F.IgnoreDefaultsWithCoveredEnums) { 3451ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 3452ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 3453ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 34546e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { 3455ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 34566e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek const Stmt *L = To->getLabel(); 34576e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 34586e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek return true; 3459ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3460ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3461ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3462ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3463ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 3464ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 3465ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3466ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3467274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek// Cleanup: CFG dstor. 3468274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek//===----------------------------------------------------------------------===// 3469274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek 347063f5887f316fb52d243fcbb3631c039de6c4b993Ted KremenekCFG::~CFG() { 347163f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap); 347263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek} 34736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 34747dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 34757dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 34767dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 34777dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 347842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 34792bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 3480ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 34813c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 34823c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 348342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 34841cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 34850a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek signed currentBlock; 348666c486f275531df6362b3511fc3af6563561801bTed Kremenek unsigned currStmt; 3487e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 348842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 34891c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 3490e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 349166c486f275531df6362b3511fc3af6563561801bTed Kremenek : currentBlock(0), currStmt(0), LangOpts(LO) 34923c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek { 349342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 349442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 3495ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 34961cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 34973c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *SE = BI->getAs<CFGStmt>()) { 34983c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const Stmt *stmt= SE->getStmt(); 34991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 35003c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek StmtMap[stmt] = P; 35013c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 35023c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek switch (stmt->getStmtClass()) { 35033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::DeclStmtClass: 35043c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P; 35053c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35063c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::IfStmtClass: { 35073c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable(); 35083c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35093c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35103c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35113c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35123c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::ForStmtClass: { 35133c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable(); 35143c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35153c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35163c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35173c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35183c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::WhileStmtClass: { 35193c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 35203c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<WhileStmt>(stmt)->getConditionVariable(); 35213c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35223c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35233c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35243c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35253c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::SwitchStmtClass: { 35263c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 35273c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<SwitchStmt>(stmt)->getConditionVariable(); 35283c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35293c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35303c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35313c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35323c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::CXXCatchStmtClass: { 35333c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 35343c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<CXXCatchStmt>(stmt)->getExceptionDecl(); 35353c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35363c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35373c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35383c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35393c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek default: 35403c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 35421cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 354342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 3544b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 3545fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 35463c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 35476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 354842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 35496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3550e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 35510a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setBlockID(signed i) { currentBlock = i; } 355266c486f275531df6362b3511fc3af6563561801bTed Kremenek void setStmtID(unsigned i) { currStmt = i; } 35536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35549c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual bool handledStmt(Stmt *S, raw_ostream &OS) { 35551cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 3556fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 355742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 355842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 35596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35600a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 356166c486f275531df6362b3511fc3af6563561801bTed Kremenek && I->second.second == currStmt) { 356242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 35633fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 35646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35653fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 35661c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 356742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 35681cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35699c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool handleDecl(const Decl *D, raw_ostream &OS) { 35701cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 35711cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 35731cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 35741cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35750a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 357666c486f275531df6362b3511fc3af6563561801bTed Kremenek && I->second.second == currStmt) { 35771cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 35781cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 35791cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35801cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 35811cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 35821cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 358342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 3584e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3585e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 3586e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 3587e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 3588ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 35896fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 35906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35919c378f705405d37f49795d5e915989de774fe11fTed Kremenek raw_ostream &OS; 359242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 3593d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 3594d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 35959c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper, 3596e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 3597d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 35986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35999c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIfStmt(IfStmt *I) { 3600d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 3601d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 3602d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 36036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3604d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 36059c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitStmt(Stmt *Terminator) { 36066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 36076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 36086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36099c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitForStmt(ForStmt *F) { 3610d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 36113fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 36123fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3613535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 36149c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = F->getCond()) 36153fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3616535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 36173fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 36183fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3619a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 3620d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 36216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36229c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitWhileStmt(WhileStmt *W) { 3623d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 36249c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = W->getCond()) 36253fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3626d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 36276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36289c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitDoStmt(DoStmt *D) { 3629d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 36309c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) 36313fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 36329da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 36336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36349c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitSwitchStmt(SwitchStmt *Terminator) { 36359da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 3636d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 36379da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 36386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36399c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitCXXTryStmt(CXXTryStmt *CS) { 36405d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 36415d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 36425d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 364356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { 3644d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 36456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 3646805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36489c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitChooseExpr(ChooseExpr *C) { 3649aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 3650d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 3651a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 3652aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 36536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36549c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt *I) { 36551c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 3656d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 36571c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 36586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3659805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 3660805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 3661805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 3662805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3663805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3665d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 36666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3667805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 36682de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 3669a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 3670805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 36712de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 3672a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 3673805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3674805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 3675b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid logical operator."); 36766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3677805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36799c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitExpr(Expr *E) { 3680d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 36816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3682d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3683e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3684e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 36855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper, 3686079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 36873c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *CS = E.getAs<CFGStmt>()) { 3688f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *S = CS->getStmt(); 36891cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36901cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 36911cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36921cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 3693f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) { 3694f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const CompoundStmt *Sub = SE->getSubStmt(); 36951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36967502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall if (Sub->children()) { 36971cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 36981cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 36991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 37001cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 37011cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 37021cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 37031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 3704f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 37051cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 37061cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 37071cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 37081cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 37091cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 37101cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 37111c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 37121c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 37131cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 37146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37151cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 371636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (OperatorCall)"; 3717893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 3718893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (isa<CXXBindTemporaryExpr>(S)) { 371936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (BindTemporary)"; 37206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 37213b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) { 37223b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek OS << " (CXXConstructExpr, " << CCE->getType().getAsString() << ")"; 37233b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek } 3724893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) { 3725893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek OS << " (" << CE->getStmtClassName() << ", " 3726893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << CE->getCastKindName() 3727893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ", " << CE->getType().getAsString() 3728893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ")"; 3729893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 37306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37311cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 37321cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 37331cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 37344e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 37353c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGInitializer *IE = E.getAs<CFGInitializer>()) { 37363c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXCtorInitializer *I = IE->getInitializer(); 37371cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 37381cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 373900eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet else OS << I->getAnyMember()->getName(); 37406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 37429c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *IE = I->getInit()) 37431cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 37441cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 37451cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37461cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 37471cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 37481cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 37491cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37503c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGAutomaticObjDtor *DE = E.getAs<CFGAutomaticObjDtor>()){ 37519c378f705405d37f49795d5e915989de774fe11fTed Kremenek const VarDecl *VD = DE->getVarDecl(); 37521cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 37531cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3754b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski const Type* T = VD->getType().getTypePtr(); 37551cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 37561cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 375756df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith T = T->getBaseElementTypeUnsafe(); 37581cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 37601cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 37617c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 37623c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGBaseDtor *BE = E.getAs<CFGBaseDtor>()) { 37633c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); 37647c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 37654e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 37667c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 37673c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGMemberDtor *ME = E.getAs<CFGMemberDtor>()) { 37683c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const FieldDecl *FD = ME->getFieldDecl(); 376956df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith const Type *T = FD->getType()->getBaseElementTypeUnsafe(); 37707c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 37718c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; 37724e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 37738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 37743c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } else if (const CFGTemporaryDtor *TE = E.getAs<CFGTemporaryDtor>()) { 37753c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); 37768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << "~" << BT->getType()->getAsCXXRecordDecl()->getName() << "()"; 37778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski OS << " (Temporary object destructor)\n"; 37781cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 377981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 37806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37819c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void print_block(raw_ostream &OS, const CFG* cfg, 37829c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock &B, 3783682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek StmtPrinterHelper* Helper, bool print_edges, 3784682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) { 37856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3786682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (Helper) 3787682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek Helper->setBlockID(B.getBlockID()); 37886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37897dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 3790682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3791682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::YELLOW, true); 3792682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3793682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n [B" << B.getBlockID(); 37946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 379542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 3796682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (ENTRY)]\n"; 379742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 3798682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (EXIT)]\n"; 379942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 3800682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (INDIRECT GOTO DISPATCH)]\n"; 380142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 3802682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "]\n"; 3803682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3804682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3805682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 38066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38079cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 38089c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) { 380942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 381042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3811682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 38126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38139c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (LabelStmt *L = dyn_cast<LabelStmt>(Label)) 38149cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 38159c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) { 38169cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 3817e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 3818e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 38199cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 38209cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 3821e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 3822e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 38239cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 3824079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 38259cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 3826079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 38275d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 3828a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 3829a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 3830a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 3831a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 3832a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 38335d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 38345d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 38355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 3836b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid label statement in CFGBlock."); 38376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38389cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 38399cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 38406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3841fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 3842fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 38436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 384442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 384542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 38466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38479cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 384842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3849682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 38506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3851a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 38526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 385342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 385442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 38556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3856682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_elem(OS, Helper, *I); 3857fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 38586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38599cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 386042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 3861682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3862682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::GREEN); 38636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3864682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " T: "; 38656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 386642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 38676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3868e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, Helper, 3869e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 38704ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt())); 3871a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 3872682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3873682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3874682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3875fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 38766d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38779cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 38789cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 3879682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.pred_empty()) { 3880682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::BLUE; 3881682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3882682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3883682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Preds " ; 3884682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3885682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3886682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.pred_size() << "):"; 3887682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3888682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3889682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3890682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3891682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3892682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 3893682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 389442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3895682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (i == 8 || (i-8) == 0) 3896682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 38976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3898682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3899682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3900682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3901682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3902682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 39036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3904682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 39059cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 39066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 39079cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 3908682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.succ_empty()) { 3909682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::MAGENTA; 3910682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3911682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3912682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Succs "; 3913682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3914682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3915682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.succ_size() << "):"; 3916682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3917682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3918682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3919682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3920682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3921682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 3922682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 3923682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3924682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (i == 8 || (i-8) % 10 == 0) 3925682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 3926682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3927682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (*I) 3928682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3929682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek else 3930682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " NULL"; 3931682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3932682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3933682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3934682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3935682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3936fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 3937fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 39386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 393942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 394042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 394142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 3942682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::dump(const LangOptions &LO, bool ShowColors) const { 3943682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), LO, ShowColors); 3944682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek} 394542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 394642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 3947682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const { 3948e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 39496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 395042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 3951682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getEntry(), &Helper, true, ShowColors); 39526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 395342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 395442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 395542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 3956ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 395742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 39586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3959682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, **I, &Helper, true, ShowColors); 396042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 39616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 396242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 3963682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getExit(), &Helper, true, ShowColors); 3964682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3965d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 39666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 396742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 396842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 3969682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO, 3970682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) const { 3971682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), cfg, LO, ShowColors); 3972e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 397342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 397442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 397542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 39769c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBlock::print(raw_ostream &OS, const CFG* cfg, 3977682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const LangOptions &LO, bool ShowColors) const { 3978e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 3979682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, cfg, *this, &Helper, true, ShowColors); 3980682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3981026473c2175424a039f51ca8949937268721b965Ted Kremenek} 39827dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 3983a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 39845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid CFGBlock::printTerminator(raw_ostream &OS, 39856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 3986e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 39874ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt())); 3988a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 3989a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 39909c378f705405d37f49795d5e915989de774fe11fTed KremenekStmt *CFGBlock::getTerminatorCondition() { 39914ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski Stmt *Terminator = this->Terminator; 3992411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 3993411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 39946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 39959c378f705405d37f49795d5e915989de774fe11fTed Kremenek Expr *E = NULL; 39966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3997411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 3998411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 3999411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4001411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 4002411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 4003411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4005411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 4006411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 4007411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4009411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 4010411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 4011411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4013411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 4014411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 4015411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4017411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 4018411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 4019411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4021411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 4022411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 4023411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4025411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 4026411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 4027411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 402956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 403056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall E = cast<BinaryConditionalOperator>(Terminator)->getCond(); 403156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall break; 403256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 4033411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 4034411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 4035411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4037411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 4038411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 4039390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 40406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4041390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 40426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 4043411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 40446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4045411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 4046411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 4047411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 40487dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 40497dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 40507dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 40517dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 405242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 405342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 40546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 405542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 405642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 4057e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 405842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 4059e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 406042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 406142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 406242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 406342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 406442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 406542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 40667dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 40677dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 40687dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 4069006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 4070006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 4071006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 40729c378f705405d37f49795d5e915989de774fe11fTed Kremenek static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) { 40737dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 4074bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 4075a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 4076a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 4077682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(Out,Graph, *Node, GraphHelper, false, false); 4078a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 40797dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 40807dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 40817dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 40827dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 40837dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 40847dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 40857dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 40867dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 40877dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 40886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 40897dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 4090bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 4091bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 4092bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 40937dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 40947dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 40957dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 4096