CFG.cpp revision 1ae74842cd1be37a8d99d0865623ef16432d3b67
16960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek //===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===// 2fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 3fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// The LLVM Compiler Infrastructure 4fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 7fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 8fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 9fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 10fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// This file defines the CFG and CFGBuilder classes for representing and 11fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// building Control-Flow Graphs (CFGs) from ASTs. 12fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek// 13fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek//===----------------------------------------------------------------------===// 14fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 15e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h" 16478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer#include "clang/AST/ASTContext.h" 172fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h" 182fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/CharUnits.h" 19b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump#include "clang/AST/DeclCXX.h" 2042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#include "clang/AST/PrettyPrinter.h" 212fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/StmtVisitor.h" 227d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose#include "clang/Basic/Builtins.h" 236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/DenseMap.h" 240ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek#include "llvm/ADT/OwningPtr.h" 252fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/ADT/SmallPtrSet.h" 262fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/Allocator.h" 272fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/Format.h" 282fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/GraphWriter.h" 292fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "llvm/Support/SaveAndRestore.h" 3083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 31fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenekusing namespace clang; 32fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 33fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremeneknamespace { 34fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 359c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic SourceLocation GetEndLoc(Decl *D) { 369c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(D)) 379c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *Ex = VD->getInit()) 38c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek return Ex->getSourceRange().getEnd(); 396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return D->getLocation(); 40c7eb9031159f30a63db960fad4640d779f1617c8Ted Kremenek} 41ad5a894df1841698c824381b414630799adc26caTed Kremenek 423179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenekclass CFGBuilder; 433179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 4494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// The CFG builder uses a recursive algorithm to build the CFG. When 4594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// we process an expression, sometimes we know that we must add the 4694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// subexpressions as block-level expressions. For example: 4794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 4894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// exp1 || exp2 4994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 5094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// When processing the '||' expression, we know that exp1 and exp2 5194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// need to be added as block-level expressions, even though they 5294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// might not normally need to be. AddStmtChoice records this 5394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// contextual information. If AddStmtChoice is 'NotAlwaysAdd', then 5494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// the builder has an option not to add a subexpression as a 5594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// block-level expression. 5694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan/// 57852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekclass AddStmtChoice { 58852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekpublic: 59892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 }; 605ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 6194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {} 625ba290a12fb9390a77ea4dca3d98deb53022d182Ted Kremenek 633179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek bool alwaysAdd(CFGBuilder &builder, 643179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek const Stmt *stmt) const; 6594a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 6694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// Return a copy of this object, except with the 'always-add' bit 6794a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan /// set as specified. 6894a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice withAlwaysAdd(bool alwaysAdd) const { 693179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek return AddStmtChoice(alwaysAdd ? AlwaysAdd : NotAlwaysAdd); 7094a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan } 7194a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 72852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenekprivate: 7394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan Kind kind; 74852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek}; 756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 76f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope - Node in tree of local scopes created for C++ implicit 77f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// destructor calls generation. It contains list of automatic variables 78f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// declared in the scope and link to position in previous scope this scope 79f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// began in. 80f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 81f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// The process of creating local scopes is as follows: 82f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null), 83f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - Before processing statements in scope (e.g. CompoundStmt) create 84f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope object using CFGBuilder::ScopePos as link to previous scope 85f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// and set CFGBuilder::ScopePos to the end of new scope, 8635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// - On every occurrence of VarDecl increase CFGBuilder::ScopePos if it points 87f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// at this VarDecl, 88f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every normal (without jump) end of scope add to CFGBlock destructors 89f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// for objects in the current scope, 90f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// - For every jump add to CFGBlock destructors for objects 91f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// between CFGBuilder::ScopePos and local scope position saved for jump 92f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// target. Thanks to C++ restrictions on goto jumps we can be sure that 93f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// jump target position will be on the path to root from CFGBuilder::ScopePos 94f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// (adding any variable that doesn't need constructor to be called to 95f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// LocalScope can break this assumption), 96f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski/// 97f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiclass LocalScope { 98f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 99fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek typedef BumpVector<VarDecl*> AutomaticVarsTy; 100f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 101f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// const_iterator - Iterates local scope backwards and jumps to previous 10235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski /// scope on reaching the beginning of currently iterated scope. 103f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski class const_iterator { 104f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const LocalScope* Scope; 105f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 106f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// VarIter is guaranteed to be greater then 0 for every valid iterator. 107f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Invalid iterator (with null Scope) has VarIter equal to 0. 108f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski unsigned VarIter; 109f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 110f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski public: 111f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create invalid iterator. Dereferencing invalid iterator is not allowed. 112f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Incrementing invalid iterator is allowed and will result in invalid 113f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// iterator. 114f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator() 115f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(NULL), VarIter(0) {} 116f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 117f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Create valid iterator. In case when S.Prev is an invalid iterator and 118f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// I is equal to 0, this will create invalid iterator. 119f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator(const LocalScope& S, unsigned I) 120f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski : Scope(&S), VarIter(I) { 121f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Iterator to "end" of scope is not allowed. Handle it by going up 122f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // in scopes tree possibly up to invalid iterator in the root. 123f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0 && Scope) 124f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 125f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 126f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1279c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *const* operator->() const { 128f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (Scope && "Dereferencing invalid iterator is not allowed"); 129f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 130f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return &Scope->Vars[VarIter - 1]; 131f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1329c378f705405d37f49795d5e915989de774fe11fTed Kremenek VarDecl *operator*() const { 133f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this->operator->(); 134f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 135f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1369c378f705405d37f49795d5e915989de774fe11fTed Kremenek const_iterator &operator++() { 137f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (!Scope) 138f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 139f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 140f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski assert (VarIter != 0 && "Iterator has invalid value of VarIter member"); 141f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski --VarIter; 142f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski if (VarIter == 0) 143f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski *this = Scope->Prev; 144f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return *this; 145f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 14635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator operator++(int) { 14735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator P = *this; 14835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski ++*this; 14935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return P; 15035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 151f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 1529c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator==(const const_iterator &rhs) const { 153f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return Scope == rhs.Scope && VarIter == rhs.VarIter; 154f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1559c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool operator!=(const const_iterator &rhs) const { 156f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski return !(*this == rhs); 157f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 15835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 1597247c88d1e41514a41085f83ebf03dd5220e054aDavid Blaikie LLVM_EXPLICIT operator bool() const { 16035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return *this != const_iterator(); 16135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 16235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 16335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int distance(const_iterator L); 164f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski }; 165f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 166f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski friend class const_iterator; 167f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 168f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskiprivate: 169fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx; 170fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek 171f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Automatic variables in order of declaration. 172f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski AutomaticVarsTy Vars; 173f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Iterator to variable in previous scope that was declared just before 174f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// begin of this scope. 175f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator Prev; 176f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 177f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskipublic: 178f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Constructs empty scope linked to previous scope in specified place. 179fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek LocalScope(BumpVectorContext &ctx, const_iterator P) 180fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek : ctx(ctx), Vars(ctx, 4), Prev(P) {} 181f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 182f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski /// Begin of scope in direction of CFG building (backwards). 183f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski const_iterator begin() const { return const_iterator(*this, Vars.size()); } 18435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 1859c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addVar(VarDecl *VD) { 186fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Vars.push_back(VD, ctx); 18735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 188f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 189f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 19035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// distance - Calculates distance from this to L. L must be reachable from this 19135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// (with use of ++ operator). Cost of calculating the distance is linear w.r.t. 19235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// number of scopes between this and L. 19335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderskiint LocalScope::const_iterator::distance(LocalScope::const_iterator L) { 19435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski int D = 0; 19535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski const_iterator F = *this; 19635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski while (F.Scope != L.Scope) { 1975290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek assert (F != const_iterator() 1985290c80eba2c96aee32912adf77bea6eddb92026Ted Kremenek && "L iterator is not reachable from F iterator."); 19935387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter; 20035387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski F = F.Scope->Prev; 20135387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski } 20235387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski D += F.VarIter - L.VarIter; 20335387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski return D; 20435387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski} 20535387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski 20635387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// BlockScopePosPair - Structure for specifying position in CFG during its 20735387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// build process. It consists of CFGBlock that specifies position in CFG graph 20835387a0daf3a6a7f5fcfc232eb4c28f62a4a1957Marcin Swiderski/// and LocalScope::const_iterator that specifies position in LocalScope graph. 209f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderskistruct BlockScopePosPair { 2109ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BlockScopePosPair() : block(0) {} 2119c378f705405d37f49795d5e915989de774fe11fTed Kremenek BlockScopePosPair(CFGBlock *b, LocalScope::const_iterator scopePos) 2129ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek : block(b), scopePosition(scopePos) {} 213f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2149ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek CFGBlock *block; 2159ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek LocalScope::const_iterator scopePosition; 216f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski}; 217f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 218e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// TryResult - a class representing a variant over the values 219e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// 'true', 'false', or 'unknown'. This is returned by tryEvaluateBool, 220e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// and is used by the CFGBuilder to decide if a branch condition 221e71f3d587844110d836c82250830b27b1651afdbTed Kremenek/// can be decided up front during CFG construction. 222e71f3d587844110d836c82250830b27b1651afdbTed Kremenekclass TryResult { 223e71f3d587844110d836c82250830b27b1651afdbTed Kremenek int X; 224e71f3d587844110d836c82250830b27b1651afdbTed Kremenekpublic: 225e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult(bool b) : X(b ? 1 : 0) {} 226e71f3d587844110d836c82250830b27b1651afdbTed Kremenek TryResult() : X(-1) {} 227e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 228e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isTrue() const { return X == 1; } 229e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isFalse() const { return X == 0; } 230e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool isKnown() const { return X >= 0; } 231e71f3d587844110d836c82250830b27b1651afdbTed Kremenek void negate() { 232e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(isKnown()); 233e71f3d587844110d836c82250830b27b1651afdbTed Kremenek X ^= 0x1; 234e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 235e71f3d587844110d836c82250830b27b1651afdbTed Kremenek}; 236e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2375846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenekclass reverse_children { 2385846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek llvm::SmallVector<Stmt *, 12> childrenBuf; 2395846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek ArrayRef<Stmt*> children; 2405846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenekpublic: 2415846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek reverse_children(Stmt *S); 2425846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2435846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek typedef ArrayRef<Stmt*>::reverse_iterator iterator; 2445846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek iterator begin() const { return children.rbegin(); } 2455846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek iterator end() const { return children.rend(); } 2465846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek}; 2475846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2485846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2495846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenekreverse_children::reverse_children(Stmt *S) { 2505846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 2515846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek children = CE->getRawSubExprs(); 2525846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek return; 2535846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2545846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek switch (S->getStmtClass()) { 255b1855de3d61eab7d2f2e616ed59195f83e2a6dc0Ted Kremenek // Note: Fill in this switch with more cases we want to optimize. 2565846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek case Stmt::InitListExprClass: { 2575846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek InitListExpr *IE = cast<InitListExpr>(S); 2585846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()), 2595846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek IE->getNumInits()); 2605846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek return; 2615846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2625846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek default: 2635846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek break; 2645846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2655846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2665846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // Default case for all other statements. 2675846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek for (Stmt::child_range I = S->children(); I; ++I) { 2685846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek childrenBuf.push_back(*I); 2695846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 2705846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 2715846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // This needs to be done *after* childrenBuf has been populated. 2725846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek children = childrenBuf; 2735846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek} 2745846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek 275a34ea072371154c9042ce86321d17fbb4df1f84dTed Kremenek/// CFGBuilder - This class implements CFG construction from an AST. 276fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// The builder is stateful: an instance of the builder should be used to only 277fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// construct a single CFG. 278fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 279fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// Example usage: 280fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 281fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFGBuilder builder; 282fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// CFG* cfg = builder.BuildAST(stmt1); 283fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek/// 2846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG construction is done via a recursive walk of an AST. We actually parse 2856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// the AST in reverse order so that the successor of a basic block is 2866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// constructed prior to its predecessor. This allows us to nicely capture 2876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// implicit fall-throughs without extra basic blocks. 288c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek/// 289ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBuilder { 290f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpTarget; 291f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef BlockScopePosPair JumpSource; 292f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 293e5af3ce53ec58995b09381ba645ab2117a46647bMike Stump ASTContext *Context; 2946f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CFG> cfg; 295ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek 2969c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Block; 2979c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *Succ; 298f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget ContinueJumpTarget; 299f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget BreakJumpTarget; 3009c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchTerminatedBlock; 3019c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *DefaultCaseBlock; 3029c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TryTerminatedBlock; 303e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 304f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // Current position in local scope. 305f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator ScopePos; 306f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 307f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski // LabelMap records the mapping from Label expressions to their jump targets. 308ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy; 3090cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek LabelMapTy LabelMap; 3106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // A list of blocks that end with a "goto" that must be backpatched to their 3126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // resolved targets upon completion of CFG construction. 313f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski typedef std::vector<JumpSource> BackpatchBlocksTy; 3140cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek BackpatchBlocksTy BackpatchBlocks; 3156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 31619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // A list of labels whose address has been taken (for indirect gotos). 317ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy; 31819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek LabelSetTy AddressTakenLabels; 3196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 32049b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu bool badCFG; 321b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &BuildOpts; 322e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 323e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // State to track for building switch statements. 324e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool switchExclusivelyCovered; 3250498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult *switchCond; 3260d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3270d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; 328a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek const Stmt *lastLookup; 32949b4ef364ba042f7db2ba567310fb49917ad0086Zhongxing Xu 3308c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Caches boolean evaluations of expressions to avoid multiple re-evaluations 3318c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // during construction of branches for chained logical operators. 3326955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi typedef llvm::DenseMap<Expr *, TryResult> CachedBoolEvalsTy; 3336955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy CachedBoolEvals; 3348c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 3356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumppublic: 336b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek explicit CFGBuilder(ASTContext *astContext, 337b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const CFG::BuildOptions &buildOpts) 338b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek : Context(astContext), cfg(new CFG()), // crew a new CFG 339b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek Block(NULL), Succ(NULL), 340b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), 341b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), 3420d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek switchExclusivelyCovered(false), switchCond(0), 343a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry(0), lastLookup(0) {} 3446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 345d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // buildCFG - Used by external clients to construct the CFG. 346b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFG* buildCFG(const Decl *D, Stmt *Statement); 3476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3480d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool alwaysAdd(const Stmt *stmt); 3490d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 3504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenekprivate: 3514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Visitors to walk an AST and construct the CFG. 352852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); 353852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc); 3544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitBreakStmt(BreakStmt *B); 355852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc); 3564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitCaseStmt(CaseStmt *C); 357852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc); 3583fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitCompoundStmt(CompoundStmt *C); 35956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *VisitConditionalOperator(AbstractConditionalOperator *C, 36056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AddStmtChoice asc); 3613fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitContinueStmt(ContinueStmt *C); 3626960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 3636960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3646960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S); 3656960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXConstructExpr(CXXConstructExpr *C, AddStmtChoice asc); 36636d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose CFGBlock *VisitCXXDeleteExpr(CXXDeleteExpr *DE, AddStmtChoice asc); 3676960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXForRangeStmt(CXXForRangeStmt *S); 3686960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 3696960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3706960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 3716960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 3726960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T); 3736960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitCXXTryStmt(CXXTryStmt *S); 3744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitDeclStmt(DeclStmt *DS); 3759c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitDeclSubExpr(DeclStmt *DS); 3763fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDefaultStmt(DefaultStmt *D); 3773fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitDoStmt(DoStmt *D); 3786960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitExprWithCleanups(ExprWithCleanups *E, AddStmtChoice asc); 3793fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek CFGBlock *VisitForStmt(ForStmt *F); 3809c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitGotoStmt(GotoStmt *G); 3814f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIfStmt(IfStmt *I); 382a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu CFGBlock *VisitImplicitCastExpr(ImplicitCastExpr *E, AddStmtChoice asc); 3834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I); 3844f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitLabelStmt(LabelStmt *L); 3856960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc); 3865c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek CFGBlock *VisitLogicalOperator(BinaryOperator *B); 3873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek std::pair<CFGBlock *, CFGBlock *> VisitLogicalOperator(BinaryOperator *B, 3883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Stmt *Term, 3893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *TrueBlock, 3903f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *FalseBlock); 391115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc); 3924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); 3934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); 3954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); 3966960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); 3974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); 3984b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); 3996960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitReturnStmt(ReturnStmt *R); 400852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); 4014f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitSwitchStmt(SwitchStmt *S); 4026960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 4036960ee6c7cc8a8883126d9861beecb51a4e4a475Ted Kremenek AddStmtChoice asc); 40499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan CFGBlock *VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc); 4054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *VisitWhileStmt(WhileStmt *W); 4064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 407852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd); 408852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); 4099c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *VisitChildren(Stmt *S); 41055331da3211151aa67277aa095b7d301342200d4Ted Kremenek CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); 411cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 4128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Visitors to walk an AST and generate destructors of temporaries in 4138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // full expression. 4148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitForTemporaryDtors(Stmt *E, bool BindToTemporary = false); 4158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitChildrenForTemporaryDtors(Stmt *E); 4168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E); 4178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *VisitCXXBindTemporaryExprForTemporaryDtors(CXXBindTemporaryExpr *E, 4188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool BindToTemporary); 41956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock * 42056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall VisitConditionalOperatorForTemporaryDtors(AbstractConditionalOperator *E, 42156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall bool BindToTemporary); 4228599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 423274f4334f6dd35239e5c3d4b86198f7f5804b059Ted Kremenek // NYS == Not Yet Supported 4249c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *NYS() { 4254102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek badCFG = true; 4264102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek return Block; 4274102af916d52310c3deedd84d6fd5e2fd3c09bfeTed Kremenek } 4286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek void autoCreateBlock() { if (!Block) Block = createBlock(); } 4304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *createBlock(bool add_successor = true); 431dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *createNoReturnBlock(); 432d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu 433df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu CFGBlock *addStmt(Stmt *S) { 434df119892cf291847d6aebb117512225a8e67c0d5Zhongxing Xu return Visit(S, AddStmtChoice::AlwaysAdd); 435852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 436cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt CFGBlock *addInitializer(CXXCtorInitializer *I); 4376a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu void addAutomaticObjDtors(LocalScope::const_iterator B, 4389c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S); 4397c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD); 440239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 441239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Local scopes creation. 442239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope* createOrReuseLocalScope(LocalScope* Scope); 443239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4449c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeForStmt(Stmt *S); 4459c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, LocalScope* Scope = NULL); 4469c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = NULL); 447239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 4489c378f705405d37f49795d5e915989de774fe11fTed Kremenek void addLocalScopeAndDtors(Stmt *S); 449ad5a894df1841698c824381b414630799adc26caTed Kremenek 450239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Interface to CFGBlock - adding CFGElements. 451d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek void appendStmt(CFGBlock *B, const Stmt *S) { 45274fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek if (alwaysAdd(S) && cachedEntry) 4530d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry->second = B; 4540d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 455ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose // All block-level expressions should have already been IgnoreParens()ed. 456ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose assert(!isa<Expr>(S) || cast<Expr>(S)->IgnoreParens() == S); 457d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext()); 458ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 459cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { 46082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B->appendInitializer(I, cfg->getBumpVectorContext()); 46182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 4627c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) { 4637c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendBaseDtor(BS, cfg->getBumpVectorContext()); 4647c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4657c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski void appendMemberDtor(CFGBlock *B, FieldDecl *FD) { 4667c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski B->appendMemberDtor(FD, cfg->getBumpVectorContext()); 4677c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 4688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) { 4698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B->appendTemporaryDtor(E, cfg->getBumpVectorContext()); 4708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 471c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) { 472c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext()); 473c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 474ad5a894df1841698c824381b414630799adc26caTed Kremenek 47536d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose void appendDeleteDtor(CFGBlock *B, CXXRecordDecl *RD, CXXDeleteExpr *DE) { 47636d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose B->appendDeleteDtor(RD, DE, cfg->getBumpVectorContext()); 47736d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose } 47836d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose 4799c378f705405d37f49795d5e915989de774fe11fTed Kremenek void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 48053de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E); 48153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 4820a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void addSuccessor(CFGBlock *B, CFGBlock *S) { 483ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek B->addSuccessor(S, cfg->getBumpVectorContext()); 484ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek } 4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 486e71f3d587844110d836c82250830b27b1651afdbTed Kremenek /// Try and evaluate an expression to an integer constant. 487e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool tryEvaluate(Expr *S, Expr::EvalResult &outResult) { 488e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!BuildOpts.PruneTriviallyFalseEdges) 489e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return false; 490e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return !S->isTypeDependent() && 491f8adeefa9e9882bff402e092024dd457f8574673Ted Kremenek !S->isValueDependent() && 49251f4708c00110940ca3f337961915f2ca1668375Richard Smith S->EvaluateAsRValue(outResult, *Context); 493e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4950a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek /// tryEvaluateBool - Try and evaluate the Stmt and return 0 or 1 49600998a068e50945118f334c98af05ed44d7c22a6Mike Stump /// if we can evaluate to a known value, otherwise return -1. 4970a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult tryEvaluateBool(Expr *S) { 49885df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (!BuildOpts.PruneTriviallyFalseEdges || 4998c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis S->isTypeDependent() || S->isValueDependent()) 500e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return TryResult(); 5018c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5028c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) { 5038c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 5048c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // Check the cache first. 5056955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi CachedBoolEvalsTy::iterator I = CachedBoolEvals.find(S); 5066955da2cad4bce19c541ddb85a6d965d77a1a4abNAKAMURA Takumi if (I != CachedBoolEvals.end()) 5078c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return I->second; // already in map; 5089260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi 5099260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi // Retrieve result at first, or the map might be updated. 5109260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi TryResult Result = evaluateAsBooleanConditionNoCache(S); 5119260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi CachedBoolEvals[S] = Result; // update or insert 5129260f618e72f7c70dc76312f95d679f0ed03858cNAKAMURA Takumi return Result; 5138c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5143d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek else { 5153d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek switch (Bop->getOpcode()) { 5163d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek default: break; 5173d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // For 'x & 0' and 'x * 0', we can determine that 5183d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // the value is always false. 5193d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek case BO_Mul: 5203d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek case BO_And: { 5213d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // If either operand is zero, we know the value 5223d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek // must be false. 5233d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek llvm::APSInt IntVal; 5243d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) { 5253d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (IntVal.getBoolValue() == false) { 5263d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek return TryResult(false); 5273d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5283d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5293d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) { 5303d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek if (IntVal.getBoolValue() == false) { 5313d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek return TryResult(false); 5323d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5333d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5343d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5353d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek break; 5363d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5373d1125b27e8006385a830f5b3748b7b44d227b4cTed Kremenek } 5388c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5398c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5408c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return evaluateAsBooleanConditionNoCache(S); 5418c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5428c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5438c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis /// \brief Evaluate as boolean \param E without using the cache. 5448c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult evaluateAsBooleanConditionNoCache(Expr *E) { 5458c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) { 5468c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->isLogicalOp()) { 5478c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult LHS = tryEvaluateBool(Bop->getLHS()); 5488c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isKnown()) { 5498c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We were able to evaluate the LHS, see if we can get away with not 5508c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 5518c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (LHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 5528c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue(); 5538c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5548c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 5558c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 5568c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (Bop->getOpcode() == BO_LOr) 5578c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() || RHS.isTrue(); 5588c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis else 5598c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return LHS.isTrue() && RHS.isTrue(); 5608c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5618c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } else { 5628c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis TryResult RHS = tryEvaluateBool(Bop->getRHS()); 5638c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isKnown()) { 5648c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // We can't evaluate the LHS; however, sometimes the result 5658c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. 5668c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (RHS.isTrue() == (Bop->getOpcode() == BO_LOr)) 5678c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return RHS.isTrue(); 5688c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5698c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5708c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5718c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 5728c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5738c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis } 5748c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5758c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis bool Result; 5768c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis if (E->EvaluateAsBooleanCondition(Result, *Context)) 5778c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return Result; 5788c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 5798c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis return TryResult(); 58000998a068e50945118f334c98af05ed44d7c22a6Mike Stump } 581e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 582d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 5836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 5840d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekinline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, 5850d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const Stmt *stmt) const { 5860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return builder.alwaysAdd(stmt) || kind == AlwaysAdd; 5870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek} 588a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 5890d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenekbool CFGBuilder::alwaysAdd(const Stmt *stmt) { 59074fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek bool shouldAdd = BuildOpts.alwaysAdd(stmt); 59174fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek 5920d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!BuildOpts.forcedBlkExprs) 59374fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 594a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 595a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (lastLookup == stmt) { 596a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (cachedEntry) { 597a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry->first == stmt); 598a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek return true; 599a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 60074fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 601a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 6020d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 603a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek lastLookup = stmt; 604a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 605a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // Perform the lookup! 6060d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; 6070d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 608a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (!fb) { 609a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek // No need to update 'cachedEntry', since it will always be null. 610a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek assert(cachedEntry == 0); 61174fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 612a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 6130d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 6140d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); 615a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek if (itr == fb->end()) { 616a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek cachedEntry = 0; 61774fb1a493cf5d2dd0fb51a4eadf74e85e10a3457Ted Kremenek return shouldAdd; 618a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek } 619a8d459e8a68b1270b0c35fb73e8cc090b2b69e36Ted Kremenek 6200d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek cachedEntry = &*itr; 6210d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek return true; 6223179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek} 6233179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek 624898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// FIXME: Add support for dependent-sized array types in C++? 625898574e7496ba8fd76290079d3a9d06954992734Douglas Gregor// Does it even make sense to build a CFG for an uninstantiated template? 626f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCallstatic const VariableArrayType *FindVA(const Type *t) { 627f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall while (const ArrayType *vt = dyn_cast<ArrayType>(t)) { 628f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const VariableArrayType *vat = dyn_cast<VariableArrayType>(vt)) 629610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek if (vat->getSizeExpr()) 630610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return vat; 6316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 632610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek t = vt->getElementType().getTypePtr(); 633610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek } 6346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 635610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek return 0; 636610a09e409bea151a42dd907768f1e0c4b103f1fTed Kremenek} 6376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an 6396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// arbitrary statement. Examples include a single expression or a function 6406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// body (compound statement). The ownership of the returned CFG is 6416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// transferred to the caller. If CFG construction fails, this method returns 6426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// NULL. 6439c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { 6440ba497be27170c2a23c0217366f97eeecefa1ed8Ted Kremenek assert(cfg.get()); 6454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!Statement) 6464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return NULL; 647d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 6486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block that will serve as the exit block for the CFG. Since 6496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // this is the first block added to the CFG, it will be implicitly registered 6506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // as the exit block. 65149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = createBlock(); 652ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek assert(Succ == &cfg->getExit()); 65349af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; // the EXIT block is empty. Create all other blocks lazily. 6546d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6557c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (BuildOpts.AddImplicitDtors) 6567c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (const CXXDestructorDecl *DD = dyn_cast_or_null<CXXDestructorDecl>(D)) 6577c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski addImplicitDtorsForDestructor(DD); 6587c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 659d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Visit the statements and create the CFG. 6601b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu CFGBlock *B = addStmt(Statement); 6611b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 6621b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (badCFG) 6631b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return NULL; 6641b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 66582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski // For C++ constructor add initializers to CFG. 666b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) { 66782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski for (CXXConstructorDecl::init_const_reverse_iterator I = CD->init_rbegin(), 66882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski E = CD->init_rend(); I != E; ++I) { 66982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski B = addInitializer(*I); 67082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (badCFG) 67182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return NULL; 67282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 673b978a441c7d8bf59e7fede938e1f3b672573b443Mike Stump } 6746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 67582bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (B) 67682bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski Succ = B; 67782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 6781b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Backpatch the gotos whose label -> block mappings we didn't know when we 6791b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // encountered them. 6801b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 6811b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = BackpatchBlocks.end(); I != E; ++I ) { 682c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar 6839c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = I->block; 6848343f8e00a222ca09dde536c77313e3e6e03ad59Rafael Espindola const GotoStmt *G = cast<GotoStmt>(B->getTerminator()); 6851b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(G->getLabel()); 6866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6871b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target for the goto, then we are looking at an 6881b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // incomplete AST. Handle this by not registering a successor. 6891b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 690d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 691f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = LI->second; 6929ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek prependAutomaticObjDtorsWithTerminator(B, I->scopePosition, 6939ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek JT.scopePosition); 6949ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, JT.block); 6951b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu } 6966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 6971b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Add successors to the Indirect Goto Dispatch block (if we have one). 6989c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (CFGBlock *B = cfg->getIndirectGotoBlock()) 6991b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu for (LabelSetTy::iterator I = AddressTakenLabels.begin(), 7001b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu E = AddressTakenLabels.end(); I != E; ++I ) { 7011b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 7021b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // Lookup the target block. 7031b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu LabelMapTy::iterator LI = LabelMap.find(*I); 7041b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 7051b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // If there is no target block that contains label, then we are looking 7061b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu // at an incomplete AST. Handle this by not registering a successor. 7071b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu if (LI == LabelMap.end()) continue; 7081b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu 7099ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(B, LI->second.block); 710c3daac59e26b63c08208de2fbaceb1ff01be3492Daniel Dunbar } 7116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 7126d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty entry block that has no predecessors. 713322f58d3830da13b419646c071e3ab801518a09cTed Kremenek cfg->setEntry(createBlock()); 7146d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 7151b3b7cb15cbd02b7283bbf3ce7c0e9b0da30ef9dZhongxing Xu return cfg.take(); 716d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 7176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 718d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// createBlock - Used to lazily create blocks that are connected 719d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek/// to the current (global) succcessor. 7209c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::createBlock(bool add_successor) { 7219c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *B = cfg->createBlock(); 7224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (add_successor && Succ) 7230a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(B, Succ); 724d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return B; 725d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 7266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 727dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// createNoReturnBlock - Used to create a block is a 'noreturn' point in the 728dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// CFG. It is *not* connected to the current (global) successor, and instead 729dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth/// directly tied to the exit block in order to be reachable. 730dba3fb5413437dc613734fa4ffac892b11a37d25Chandler CarruthCFGBlock *CFGBuilder::createNoReturnBlock() { 731dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth CFGBlock *B = createBlock(false); 73283754162f698a5dafad93fb89be0953651a604d0Chandler Carruth B->setHasNoReturnElement(); 733dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth addSuccessor(B, &cfg->getExit()); 734dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth return B; 735dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth} 736dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 73782bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski/// addInitializer - Add C++ base or member initializer element to CFG. 738cbb67480094b3bcb5b715acd827cbad55e2a204cSean HuntCFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { 73982bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski if (!BuildOpts.AddInitializers) 74082bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 74182bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 7438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 74482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 7468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 7478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Expr *Init = I->getInit(); 7488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 74900eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet if (FieldDecl *FD = I->getAnyMember()) 7508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = FD->getType()->isReferenceType(); 7514765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 75282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7535a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors && HasTemporaries) { 7548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 7554765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 7568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 7578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 75882bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski } 7598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 7608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 7618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendInitializer(Block, I); 7628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 7638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 764892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek if (HasTemporaries) { 7658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 7668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 767892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(cast<ExprWithCleanups>(Init)->getSubExpr()); 768892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek } 769892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(Init); 7708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 7718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 77282bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski return Block; 77382bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski} 77482bc3fd823d85ee3ef9a641c0975b6ad25f55047Marcin Swiderski 7752d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// \brief Retrieve the type of the temporary object whose lifetime was 7762d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor/// extended by a local reference with the given initializer. 7772d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregorstatic QualType getReferenceInitTemporaryType(ASTContext &Context, 7782d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor const Expr *Init) { 7792d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (true) { 7802d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip parentheses. 7812d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = Init->IgnoreParens(); 7822d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7832d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through cleanups. 7842d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) { 7852d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = EWC->getSubExpr(); 7862d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7872d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7882d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7892d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip through the temporary-materialization expression. 7902d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MaterializeTemporaryExpr *MTE 7912d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor = dyn_cast<MaterializeTemporaryExpr>(Init)) { 7922d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = MTE->GetTemporaryExpr(); 7932d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 7942d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 7952d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 7962d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip derived-to-base and no-op casts. 7972d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const CastExpr *CE = dyn_cast<CastExpr>(Init)) { 7982d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if ((CE->getCastKind() == CK_DerivedToBase || 7992d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_UncheckedDerivedToBase || 8002d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor CE->getCastKind() == CK_NoOp) && 8012d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init->getType()->isRecordType()) { 8022d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = CE->getSubExpr(); 8032d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 8042d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8052d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8062d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 8072d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor // Skip member accesses into rvalues. 8082d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (const MemberExpr *ME = dyn_cast<MemberExpr>(Init)) { 8092d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (!ME->isArrow() && ME->getBase()->isRValue()) { 8102d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Init = ME->getBase(); 8112d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor continue; 8122d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8132d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8142d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 8152d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor break; 8162d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 8172d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 8182d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor return Init->getType(); 8192d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor} 8202d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 821239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addAutomaticObjDtors - Add to current block automatic objects destructors 822239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for objects in range of local scope positions. Use S as trigger statement 823239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// for destructors. 8246a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xuvoid CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B, 8259c378f705405d37f49795d5e915989de774fe11fTed Kremenek LocalScope::const_iterator E, Stmt *S) { 826239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 8276a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 8286a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu 829239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (B == E) 8306a16a306f6226030f8d38ae7e32082888fa937a1Zhongxing Xu return; 831239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 832c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // We need to append the destructors in reverse order, but any one of them 833c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // may be a no-return destructor which changes the CFG. As a result, buffer 834c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // this sequence up and replay them in reverse order when appending onto the 835c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // CFGBlock(s). 836c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth SmallVector<VarDecl*, 10> Decls; 837c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.reserve(B.distance(E)); 838c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 839c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Decls.push_back(*I); 840c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 841c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(), 842c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth E = Decls.rend(); 843c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth I != E; ++I) { 844c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If this destructor is marked as a no-return destructor, we need to 845c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // create a new block for the destructor which does not have as a successor 846c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far: control won't flow out of this block. 84788237bf587581026dcfc8386abf055cb201aa487Ted Kremenek QualType Ty = (*I)->getType(); 84888237bf587581026dcfc8386abf055cb201aa487Ted Kremenek if (Ty->isReferenceType()) { 8492d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor Ty = getReferenceInitTemporaryType(*Context, (*I)->getInit()); 8502d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor } 85188237bf587581026dcfc8386abf055cb201aa487Ted Kremenek Ty = Context->getBaseElementType(Ty); 85288237bf587581026dcfc8386abf055cb201aa487Ted Kremenek 853c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); 854cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (Dtor->isNoReturn()) 855dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 856dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 857c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 858c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 859c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth appendAutomaticObjDtor(Block, *I, S); 860c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth } 861239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 862239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 8637c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// addImplicitDtorsForDestructor - Add implicit destructors generated for 8647c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski/// base and member objects in destructor. 8657c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderskivoid CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { 8667c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski assert (BuildOpts.AddImplicitDtors 8677c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski && "Can be called only when dtors should be added"); 8687c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *RD = DD->getParent(); 8697c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8707c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // At the end destroy virtual base objects. 8717c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator VI = RD->vbases_begin(), 8727c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski VE = RD->vbases_end(); VI != VE; ++VI) { 8737c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski const CXXRecordDecl *CD = VI->getType()->getAsCXXRecordDecl(); 8747c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 8757c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 8767c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski appendBaseDtor(Block, VI); 8777c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8787c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8797c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8807c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // Before virtual bases destroy direct base objects. 8817c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(), 8827c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski BE = RD->bases_end(); BI != BE; ++BI) { 88323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!BI->isVirtual()) { 88423661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie const CXXRecordDecl *CD = BI->getType()->getAsCXXRecordDecl(); 88523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 88623661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie autoCreateBlock(); 88723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie appendBaseDtor(Block, BI); 88823661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 88923661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie } 8907c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 8917c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 8927c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski // First destroy member objects. 8937c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski for (CXXRecordDecl::field_iterator FI = RD->field_begin(), 8947c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski FE = RD->field_end(); FI != FE; ++FI) { 8958c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski // Check for constant size array. Set type to array element type. 8968c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QualType QT = FI->getType(); 8978c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 8988c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (AT->getSize() == 0) 8998c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski continue; 9008c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski QT = AT->getElementType(); 9018c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski } 9028c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski 9038c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 9047c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski if (!CD->hasTrivialDestructor()) { 9057c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski autoCreateBlock(); 906581deb3da481053c4993c7600f97acf7768caac5David Blaikie appendMemberDtor(Block, *FI); 9077c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 9087c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski } 9097c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski} 9107c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 911239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either 912239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// way return valid LocalScope object. 913239a7c42df78abc7fd5611d806d5e199fec994d1Marcin SwiderskiLocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { 914239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!Scope) { 915fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek llvm::BumpPtrAllocator &alloc = cfg->getAllocator(); 916fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek Scope = alloc.Allocate<LocalScope>(); 917fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek BumpVectorContext ctx(alloc); 918fe59b7472c06b36efb74fbb50bbdf464fa30c0d8Ted Kremenek new (Scope) LocalScope(ctx, ScopePos); 919239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 920239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 921239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 922239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 923239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement 92402acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu/// that should create implicit scope (e.g. if/else substatements). 9259c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeForStmt(Stmt *S) { 926239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 92702acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 92802acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu 92902acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu LocalScope *Scope = 0; 930239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 931239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For compound statement we will be creating explicit scope. 932ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) { 933239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end() 934239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; BI != BE; ++BI) { 935a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth Stmt *SI = (*BI)->stripLabelLikeStatements(); 936ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner if (DeclStmt *DS = dyn_cast<DeclStmt>(SI)) 937239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForDeclStmt(DS, Scope); 938239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 93902acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu return; 940239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 941239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 942239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // For any other statement scope will be implicit and as such will be 943239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // interesting only for DeclStmt. 944a1364be341550d71dff27dd8de0c6872ba6c707eChandler Carruth if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements())) 945b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu addLocalScopeForDeclStmt(DS); 946239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 947239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 948239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will 949239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// reuse Scope if not NULL. 9509c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS, 951b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 952239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 953239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 954239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 955239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end() 956239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski ; DI != DE; ++DI) { 9579c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = dyn_cast<VarDecl>(*DI)) 958239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski Scope = addLocalScopeForVarDecl(VD, Scope); 959239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 960239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 961239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 962239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 963239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeForVarDecl - Add LocalScope for variable declaration. It will 964239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// create add scope for automatic objects and temporary objects bound to 965239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// const reference. Will reuse Scope if not NULL. 9669c378f705405d37f49795d5e915989de774fe11fTed KremenekLocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD, 967b6edff55db4ff240d56d33594d68a711e4b1e24aZhongxing Xu LocalScope* Scope) { 968239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 969239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 970239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 971239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check if variable is local. 972239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski switch (VD->getStorageClass()) { 973239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_None: 974239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Auto: 975239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski case SC_Register: 976239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski break; 977239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski default: return Scope; 978239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 979239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 980239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski // Check for const references bound to temporary. Set type to pointee. 981239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski QualType QT = VD->getType(); 9822d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor if (QT.getTypePtr()->isReferenceType()) { 98349bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // Attempt to determine whether this declaration lifetime-extends a 98449bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // temporary. 98549bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // 98649bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // FIXME: This is incorrect. Non-reference declarations can lifetime-extend 98749bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // temporaries, and a single declaration can extend multiple temporaries. 98849bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // We should look at the storage duration on each nested 98949bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // MaterializeTemporaryExpr instead. 99049bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith const Expr *Init = VD->getInit(); 99149bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith if (!Init) 99249bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith return Scope; 99349bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init)) 99449bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith Init = EWC->getSubExpr(); 99549bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith if (!isa<MaterializeTemporaryExpr>(Init)) 996239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 9972d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor 99849bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith // Lifetime-extending a temporary. 99949bab4c0046e8300c79e79b7ca9a479696c7e87aRichard Smith QT = getReferenceInitTemporaryType(*Context, Init); 1000239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski } 1001239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 1002b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check for constant size array. Set type to array element type. 10032d9eb21325a0854e86de7344f54a8e6cef2a97adDouglas Gregor while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { 1004b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski if (AT->getSize() == 0) 1005b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski return Scope; 1006b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski QT = AT->getElementType(); 1007b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski } 10084e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu 1009b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski // Check if type is a C++ class with non-trivial destructor. 10109c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl()) 101123661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!CD->hasTrivialDestructor()) { 10124e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu // Add the variable to scope 10134e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope = createOrReuseLocalScope(Scope); 10144e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu Scope->addVar(VD); 10154e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu ScopePos = Scope->begin(); 10164e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu } 1017239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return Scope; 1018239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 1019239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 1020239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// addLocalScopeAndDtors - For given statement add local scope for it and 1021239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski/// add destructors that will cleanup the scope. Will reuse Scope if not NULL. 10229c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::addLocalScopeAndDtors(Stmt *S) { 1023239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski if (!BuildOpts.AddImplicitDtors) 1024239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski return; 1025239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 1026239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski LocalScope::const_iterator scopeBeginPos = ScopePos; 102702acdfaeb3f3805b65e4707e5dff096209adb367Zhongxing Xu addLocalScopeForStmt(S); 1028239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski addAutomaticObjDtors(ScopePos, scopeBeginPos, S); 1029239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski} 1030239a7c42df78abc7fd5611d806d5e199fec994d1Marcin Swiderski 103153de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for 103253de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// variables with automatic storage duration to CFGBlock's elements vector. 103353de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// Elements will be prepended to physical beginning of the vector which 103453de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// happens to be logical end. Use blocks terminator as statement that specifies 103553de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski/// destructors call site. 1036c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// FIXME: This mechanism for adding automatic destructors doesn't handle 1037c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth/// no-return destructors properly. 10389c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, 103953de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski LocalScope::const_iterator B, LocalScope::const_iterator E) { 1040c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth BumpVectorContext &C = cfg->getBumpVectorContext(); 1041c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth CFGBlock::iterator InsertPos 1042c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); 1043c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth for (LocalScope::const_iterator I = B; I != E; ++I) 1044c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, 1045c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth Blk->getTerminator()); 104653de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski} 104753de134e7b4686eed40bc031438d8a4560a2cda4Marcin Swiderski 10484f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// Visit - Walk the subtree of a statement and add extra 10496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// blocks for ternary operators, &&, and ||. We also process "," and 10506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// DeclStmts (which may contain nested control-flow). 10519c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { 1052f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek if (!S) { 1053f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek badCFG = true; 1054f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek return 0; 1055f42e3371079de333c3822a060c008bf6680677c8Ted Kremenek } 1056ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 1057ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose if (Expr *E = dyn_cast<Expr>(S)) 1058ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose S = E->IgnoreParens(); 1059ac73ea8c12772fd0dcec71b83c193a2837de7f8bJordy Rose 10604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek switch (S->getStmtClass()) { 10614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek default: 1062852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, asc); 10634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::AddrLabelExprClass: 1065852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc); 10661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 106756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 106856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return VisitConditionalOperator(cast<BinaryConditionalOperator>(S), asc); 106956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 10704f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BinaryOperatorClass: 1071852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitBinaryOperator(cast<BinaryOperator>(S), asc); 10721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10734f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BlockExprClass: 107455331da3211151aa67277aa095b7d301342200d4Ted Kremenek return VisitNoRecurse(cast<Expr>(S), asc); 10754f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::BreakStmtClass: 10774f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitBreakStmt(cast<BreakStmt>(S)); 10781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CallExprClass: 1080a427f1d8f0848997029d1bdc0c5c137f982f775dTed Kremenek case Stmt::CXXOperatorCallExprClass: 10811de85338543dd6228eb518185e385d94d377f4cbJohn McCall case Stmt::CXXMemberCallExprClass: 10829fcce65e7e1307b5b8da9be13e4092d6bb94dc1dRichard Smith case Stmt::UserDefinedLiteralClass: 1083852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitCallExpr(cast<CallExpr>(S), asc); 10841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CaseStmtClass: 10864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCaseStmt(cast<CaseStmt>(S)); 10874f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 10884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ChooseExprClass: 1089852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitChooseExpr(cast<ChooseExpr>(S), asc); 10901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::CompoundStmtClass: 10924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(cast<CompoundStmt>(S)); 10931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ConditionalOperatorClass: 1095852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitConditionalOperator(cast<ConditionalOperator>(S), asc); 10961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10974f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ContinueStmtClass: 10984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitContinueStmt(cast<ContinueStmt>(S)); 10991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1100021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXCatchStmtClass: 1101021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXCatchStmt(cast<CXXCatchStmt>(S)); 1102021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek 11034765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall case Stmt::ExprWithCleanupsClass: 11044765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc); 110547e331ed28c2536bec227c5e2fa094ab3d46eed1Ted Kremenek 1106b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose case Stmt::CXXDefaultArgExprClass: 1107c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith case Stmt::CXXDefaultInitExprClass: 1108b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // FIXME: The expression inside a CXXDefaultArgExpr is owned by the 1109b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // called function's declaration, not by the caller. If we simply add 1110b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // this expression to the CFG, we could end up with the same Expr 1111b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // appearing multiple times. 1112b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose // PR13385 / <rdar://problem/12156507> 1113c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // 1114c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // It's likewise possible for multiple CXXDefaultInitExprs for the same 1115c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // expression to be used in the same function (through aggregate 1116c3bf52ced9652f555aa0767bb822ec4c64546212Richard Smith // initialization). 1117b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose return VisitStmt(S, asc); 1118b66529d04727dc686b97ea3d937fc9785792f505Jordan Rose 1119a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXBindTemporaryExprClass: 1120a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), asc); 1121a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 112281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXConstructExprClass: 112381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXConstructExpr(cast<CXXConstructExpr>(S), asc); 112481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 112536d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose case Stmt::CXXDeleteExprClass: 112636d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose return VisitCXXDeleteExpr(cast<CXXDeleteExpr>(S), asc); 112736d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose 1128a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu case Stmt::CXXFunctionalCastExprClass: 1129a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return VisitCXXFunctionalCastExpr(cast<CXXFunctionalCastExpr>(S), asc); 1130a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 113181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu case Stmt::CXXTemporaryObjectExprClass: 113281bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitCXXTemporaryObjectExpr(cast<CXXTemporaryObjectExpr>(S), asc); 113381bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 1134021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXThrowExprClass: 1135021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXThrowExpr(cast<CXXThrowExpr>(S)); 1136ad5a894df1841698c824381b414630799adc26caTed Kremenek 1137021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek case Stmt::CXXTryStmtClass: 1138021c8afbab95c71fbdd95c0b5cea36fd316281f9Ted Kremenek return VisitCXXTryStmt(cast<CXXTryStmt>(S)); 1139ad5a894df1841698c824381b414630799adc26caTed Kremenek 1140ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith case Stmt::CXXForRangeStmtClass: 1141ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return VisitCXXForRangeStmt(cast<CXXForRangeStmt>(S)); 1142ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 11434f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DeclStmtClass: 11444f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDeclStmt(cast<DeclStmt>(S)); 11451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DefaultStmtClass: 11474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDefaultStmt(cast<DefaultStmt>(S)); 11481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11494f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::DoStmtClass: 11504f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitDoStmt(cast<DoStmt>(S)); 11511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ForStmtClass: 11534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitForStmt(cast<ForStmt>(S)); 11541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::GotoStmtClass: 11564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitGotoStmt(cast<GotoStmt>(S)); 11571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IfStmtClass: 11594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIfStmt(cast<IfStmt>(S)); 11601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1161892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek case Stmt::ImplicitCastExprClass: 1162892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc); 1163a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 11644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::IndirectGotoStmtClass: 11654f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S)); 11661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11674f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::LabelStmtClass: 11684f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitLabelStmt(cast<LabelStmt>(S)); 11691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 117083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek case Stmt::LambdaExprClass: 117183748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return VisitLambdaExpr(cast<LambdaExpr>(S), asc); 117283748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 1173115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek case Stmt::MemberExprClass: 1174115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek return VisitMemberExpr(cast<MemberExpr>(S), asc); 1175115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 11766a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::NullStmtClass: 11776a9065a39ab15383082b914af28759da1652db18Ted Kremenek return Block; 11786a9065a39ab15383082b914af28759da1652db18Ted Kremenek 11794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtCatchStmtClass: 11801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S)); 11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11828e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek case Stmt::ObjCAutoreleasePoolStmtClass: 11838e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return VisitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(S)); 11848e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 11854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtSynchronizedStmtClass: 11864f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S)); 11871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11884f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtThrowStmtClass: 11894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S)); 11901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11914f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCAtTryStmtClass: 11924f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S)); 11931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ObjCForCollectionStmtClass: 11954f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S)); 11961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11976a9065a39ab15383082b914af28759da1652db18Ted Kremenek case Stmt::OpaqueValueExprClass: 11984f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 11991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12004b9c2d235fb9449e249d74f48ecfec601650de93John McCall case Stmt::PseudoObjectExprClass: 12014b9c2d235fb9449e249d74f48ecfec601650de93John McCall return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S)); 12024b9c2d235fb9449e249d74f48ecfec601650de93John McCall 12034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::ReturnStmtClass: 12044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitReturnStmt(cast<ReturnStmt>(S)); 12051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1206f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne case Stmt::UnaryExprOrTypeTraitExprClass: 1207f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne return VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S), 1208f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne asc); 12091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12104f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::StmtExprClass: 1211852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmtExpr(cast<StmtExpr>(S), asc); 12121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12134f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::SwitchStmtClass: 12144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitSwitchStmt(cast<SwitchStmt>(S)); 12151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 121699cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan case Stmt::UnaryOperatorClass: 121799cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan return VisitUnaryOperator(cast<UnaryOperator>(S), asc); 121899cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 12194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek case Stmt::WhileStmtClass: 12204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitWhileStmt(cast<WhileStmt>(S)); 12214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 12224f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1224852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { 12253179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, S)) { 12264f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1227247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 12286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 12291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitChildren(S); 12314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitChildren - Visit the children of a Stmt. 12345846720f08a6b225484bfe663599c2b057a99bc8Ted KremenekCFGBlock *CFGBuilder::VisitChildren(Stmt *S) { 12355846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek CFGBlock *B = Block; 12366b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek 12375846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // Visit the children in their reverse order so that they appear in 12385846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // left-to-right (natural) order in the CFG. 12395846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek reverse_children RChildren(S); 12405846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end(); 12415846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek I != E; ++I) { 12425846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (Stmt *Child = *I) 12435846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (CFGBlock *R = Visit(Child)) 12445846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek B = R; 12455846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek } 12465846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek return B; 12474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1249852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, 1250852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 12514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek AddressTakenLabels.insert(A->getLabel()); 12526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12533179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, A)) { 12544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek autoCreateBlock(); 1255247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, A); 12566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 12576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 12584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 12594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 126199cae5b67b9711ca260e5b364a878a1a91183632Zhanyong WanCFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, 1262892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek AddStmtChoice asc) { 12633179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, U)) { 126499cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan autoCreateBlock(); 1265247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, U); 126699cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan } 126799cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 1268892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(U->getSubExpr(), AddStmtChoice()); 126999cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan} 127099cae5b67b9711ca260e5b364a878a1a91183632Zhanyong Wan 12715c3ea5c57971317c35b120ef0a2a2c79bd171008Ted KremenekCFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) { 12725c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 12735c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek appendStmt(ConfluenceBlock, B); 12741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12755c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (badCFG) 12765c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek return 0; 12771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12783f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(B, 0, ConfluenceBlock, ConfluenceBlock).first; 12793f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek} 1280862b24f8e9b1a3b332399591e48b303f57f01d0aTed Kremenek 12813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenekstd::pair<CFGBlock*, CFGBlock*> 12823f635c08b2d0b2d5bafb38da09589cb238407faaTed KremenekCFGBuilder::VisitLogicalOperator(BinaryOperator *B, 12833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Stmt *Term, 12843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *TrueBlock, 12853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *FalseBlock) { 12863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Introspect the RHS. If it is a nested logical operation, we recursively 12883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // build the CFG using this function. Otherwise, resort to default 12893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // CFG construction behavior. 12903f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *RHS = B->getRHS()->IgnoreParens(); 12913f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *RHSBlock, *ExitBlock; 12923f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 12933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 12943f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (BinaryOperator *B_RHS = dyn_cast<BinaryOperator>(RHS)) 12953f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B_RHS->isLogicalOp()) { 12963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(RHSBlock, ExitBlock) = 12973f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(B_RHS, Term, TrueBlock, FalseBlock); 12983f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 12993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 13001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13013f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The RHS is not a nested logical operation. Don't push the terminator 13023f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // down further, but instead visit RHS and construct the respective 13033f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // pieces of the CFG, and link up the RHSBlock with the terminator 13043f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // we have been provided. 13053f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitBlock = RHSBlock = createBlock(false); 13063f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13073f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!Term) { 13083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(TrueBlock == FalseBlock); 13093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, TrueBlock); 13103f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 13113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else { 13123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek RHSBlock->setTerminator(Term); 13133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal = tryEvaluateBool(RHS); 13143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, KnownVal.isFalse() ? NULL : TrueBlock); 13153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(RHSBlock, KnownVal.isTrue() ? NULL : FalseBlock); 13163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 13173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = RHSBlock; 13193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek RHSBlock = addStmt(RHS); 13205c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } 13213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek while (false); 13223f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13233f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (badCFG) 13243f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair((CFGBlock*)0, (CFGBlock*)0); 13258c6d360636dee25f1ce071c3656810c6632cb89dArgyrios Kyrtzidis 13265c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // Generate the blocks for evaluating the LHS. 13273f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *LHS = B->getLHS()->IgnoreParens(); 13283f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13293f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (BinaryOperator *B_LHS = dyn_cast<BinaryOperator>(LHS)) 13303f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B_LHS->isLogicalOp()) { 13313f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (B->getOpcode() == BO_LOr) 13323f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek FalseBlock = RHSBlock; 13333f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else 13343f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TrueBlock = RHSBlock; 13353f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13363f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // For the LHS, treat 'B' as the terminator that we want to sink 13373f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // into the nested branch. The RHS always gets the top-most 13383f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // terminator. 13393f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(B_LHS, B, TrueBlock, FalseBlock); 13403f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 13413f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13423f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Create the block evaluating the LHS. 13433f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // This contains the '&&' or '||' as the terminator. 13443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *LHSBlock = createBlock(false); 13453f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek LHSBlock->setTerminator(B); 13463f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13475c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek Block = LHSBlock; 13483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryLHSBlock = addStmt(LHS); 13493f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13503f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (badCFG) 13513f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair((CFGBlock*)0, (CFGBlock*)0); 13525c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek 13535c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // See if this is a known constant. 13543f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal = tryEvaluateBool(LHS); 13555c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek 13565c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // Now link the LHSBlock with RHSBlock. 13575c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (B->getOpcode() == BO_LOr) { 13583f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : TrueBlock); 13593f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : RHSBlock); 13605c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } else { 13615c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek assert(B->getOpcode() == BO_LAnd); 13625c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 13633f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : FalseBlock); 13645c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek } 136500998a068e50945118f334c98af05ed44d7c22a6Mike Stump 13663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return std::make_pair(EntryLHSBlock, ExitBlock); 13675c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek} 13681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 13705c3ea5c57971317c35b120ef0a2a2c79bd171008Ted KremenekCFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, 13715c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek AddStmtChoice asc) { 13725c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek // && or || 13735c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek if (B->isLogicalOp()) 13745c3ea5c57971317c35b120ef0a2a2c79bd171008Ted Kremenek return VisitLogicalOperator(B); 137536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 137636f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->getOpcode() == BO_Comma) { // , 13776dc534ecc19a045ebcfe93eefa45da509968e888Ted Kremenek autoCreateBlock(); 1378247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 13794f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(B->getRHS()); 13804f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(B->getLHS()); 13816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 138236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 138336f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (B->isAssignmentOp()) { 13843179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1385fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu autoCreateBlock(); 1386247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1387fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 1388892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek Visit(B->getLHS()); 1389e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski return Visit(B->getRHS()); 1390fc61d94fbdbcd2b423976e21f24d423fcd442486Zhongxing Xu } 13911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13923179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, B)) { 1393e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski autoCreateBlock(); 1394247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, B); 1395e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski } 1396e1667190dff025936a21e5eb43889ac93b570468Marcin Swiderski 1397a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *RBlock = Visit(B->getRHS()); 1398a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu CFGBlock *LBlock = Visit(B->getLHS()); 1399a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // If visiting RHS causes us to finish 'Block', e.g. the RHS is a StmtExpr 1400a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // containing a DoStmt, and the LHS doesn't create a new block, then we should 1401a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu // return RBlock. Otherwise we'll incorrectly return NULL. 1402a1898ddd5d0e46330898930b9185b628b5cede63Zhongxing Xu return (LBlock ? LBlock : RBlock); 14034f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 14046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 140555331da3211151aa67277aa095b7d301342200d4Ted KremenekCFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) { 14063179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 1407721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek autoCreateBlock(); 1408247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 1409721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek } 1410721903eca33f6115296083aed17685eaa73d3e8cTed Kremenek return Block; 14114f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 1412cd7bf230a77c550115e4a78ee371fc49a7563692Mike Stump 14134f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { 14144f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // "break" is a control-flow statement. Thus we stop processing the current 14154f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // block. 1416d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1417d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 14181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Now create a new block that ends with the break statement. 14204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block = createBlock(false); 14214f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Block->setTerminator(B); 14221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If there is no target for the break, then we are looking at an incomplete 14244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // AST. This means that the CFG cannot be constructed. 14259ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (BreakJumpTarget.block) { 14269ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B); 14279ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, BreakJumpTarget.block); 1428f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 14294f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek badCFG = true; 14301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 14334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 14341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14358026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redlstatic bool CanThrow(Expr *E, ASTContext &Ctx) { 14364c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump QualType Ty = E->getType(); 14374c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (Ty->isFunctionPointerType()) 14384c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<PointerType>()->getPointeeType(); 14394c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump else if (Ty->isBlockPointerType()) 14404c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 1441ad5a894df1841698c824381b414630799adc26caTed Kremenek 14424c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump const FunctionType *FT = Ty->getAs<FunctionType>(); 14434c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (FT) { 14444c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) 1445b9d0b76e42fd2d4cdfd135220302458d03ad09feRichard Smith if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) && 1446e6975e9b0985ad7f7ff9187e38d95bfe9ac4181bRichard Smith Proto->isNothrow(Ctx)) 14474c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return false; 14484c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump } 14494c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump return true; 14504c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump} 14514c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 1452852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { 14531de85338543dd6228eb518185e385d94d377f4cbJohn McCall // Compute the callee type. 14541de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType calleeType = C->getCallee()->getType(); 14551de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (calleeType == Context->BoundMemberTy) { 14561de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType boundType = Expr::findBoundMemberType(C->getCallee()); 14571de85338543dd6228eb518185e385d94d377f4cbJohn McCall 14581de85338543dd6228eb518185e385d94d377f4cbJohn McCall // We should only get a null bound type if processing a dependent 14591de85338543dd6228eb518185e385d94d377f4cbJohn McCall // CFG. Recover by assuming nothing. 14601de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (!boundType.isNull()) calleeType = boundType; 14612455636163fdd18581d7fdae816433f886d88213Mike Stump } 14622455636163fdd18581d7fdae816433f886d88213Mike Stump 14631de85338543dd6228eb518185e385d94d377f4cbJohn McCall // If this is a call to a no-return function, this stops the block here. 14641de85338543dd6228eb518185e385d94d377f4cbJohn McCall bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn(); 14651de85338543dd6228eb518185e385d94d377f4cbJohn McCall 14664c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump bool AddEHEdge = false; 1467079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 1468079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Languages without exceptions are assumed to not throw. 14694e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (Context->getLangOpts().Exceptions) { 14706c52c7850bccb6991470668429a1e1edf01b0873Ted Kremenek if (BuildOpts.AddEHEdges) 14714c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = true; 1472079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 1473079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 14747d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose // If this is a call to a builtin function, it might not actually evaluate 14757d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose // its arguments. Don't add them to the CFG if this is the case. 14767d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose bool OmitArguments = false; 14777d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose 1478079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FunctionDecl *FD = C->getDirectCallee()) { 1479cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (FD->isNoReturn()) 14802455636163fdd18581d7fdae816433f886d88213Mike Stump NoReturn = true; 1481079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (FD->hasAttr<NoThrowAttr>()) 14824c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 14837d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose if (FD->getBuiltinID() == Builtin::BI__builtin_object_size) 14847d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose OmitArguments = true; 1485079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 14862455636163fdd18581d7fdae816433f886d88213Mike Stump 14878026f6d82f7fa544bc0453714fe94bca62a1196eSebastian Redl if (!CanThrow(C->getCallee(), *Context)) 14884c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump AddEHEdge = false; 14894c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump 14907d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose if (OmitArguments) { 14917d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose assert(!NoReturn && "noreturn calls with unevaluated args not implemented"); 14927d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose assert(!AddEHEdge && "EH calls with unevaluated args not implemented"); 14937d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose autoCreateBlock(); 14947d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose appendStmt(Block, C); 14957d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose return Visit(C->getCallee()); 14967d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose } 14977d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose 14987d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose if (!NoReturn && !AddEHEdge) { 149994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan return VisitStmt(C, asc.withAlwaysAdd(true)); 15007d0dcd2de023e2667a3f1f14daff9d087fab9bf7Jordan Rose } 15011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1502079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (Block) { 1503079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump Succ = Block; 1504d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1505079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump return 0; 1506079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 15071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1508dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth if (NoReturn) 1509dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 1510dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 1511dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createBlock(); 1512dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth 1513247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 15142455636163fdd18581d7fdae816433f886d88213Mike Stump 15154c45aa1b00b91847acfb082acfaced3ffa294d1dMike Stump if (AddEHEdge) { 1516079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump // Add exceptional edges. 1517079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump if (TryTerminatedBlock) 15180a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 1519079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else 15200a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 1521079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } 15221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15232455636163fdd18581d7fdae816433f886d88213Mike Stump return VisitChildren(C); 1524d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1525d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1526852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekCFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C, 1527852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 15289c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1529247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1530d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15313fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 15321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 153394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 15343fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 15353fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 15369c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = Visit(C->getLHS(), alwaysAdd); 1537d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15383fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 15391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15403fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Succ = ConfluenceBlock; 15413fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = NULL; 15429c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getRHS(), alwaysAdd); 1543d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 15443fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek return 0; 15451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15463fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block = createBlock(false); 154700998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 15480a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 15490a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 15500a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 15513fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek Block->setTerminator(C); 15521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return addStmt(C->getCond()); 15533fc8ef574cdc09c613c329ee511852d219263c15Ted Kremenek} 15541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15569c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) { 1557fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addLocalScopeAndDtors(C); 15589c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LastBlock = Block; 15594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 15604f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); 15614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek I != E; ++I ) { 1562334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // If we hit a segment of code just containing ';' (NullStmts), we can 1563334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek // get a null block back. In such cases, just use the LastBlock 1564334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek if (CFGBlock *newBlock = addStmt(*I)) 1565334c19566104d3333cf662f0017088a18eddfa81Ted Kremenek LastBlock = newBlock; 15661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1567e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek if (badCFG) 1568e8d6d2b9a2c5d3f0e7e0f88f54f1711bbc6c6f78Ted Kremenek return NULL; 15691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1570079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump 15714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return LastBlock; 15724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 15731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 157456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCallCFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, 1575852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek AddStmtChoice asc) { 157656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const BinaryConditionalOperator *BCO = dyn_cast<BinaryConditionalOperator>(C); 157756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const OpaqueValueExpr *opaqueValue = (BCO ? BCO->getOpaqueValue() : NULL); 157856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 1579f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the confluence block that will "merge" the results of the ternary 1580f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // expression. 15819c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConfluenceBlock = Block ? Block : createBlock(); 1582247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(ConfluenceBlock, C); 1583d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1584f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 15851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 158694a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan AddStmtChoice alwaysAdd = asc.withAlwaysAdd(true); 1587115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 1588f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create a block for the LHS expression if there is an LHS expression. A 1589f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // GCC extension allows LHS to be NULL, causing the condition to be the 1590f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // value that is returned instead. 1591f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // e.g: x ?: y is shorthand for: x ? x : y; 1592f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 1593f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 15949c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LHSBlock = 0; 159556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall const Expr *trueExpr = C->getTrueExpr(); 159656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (trueExpr != opaqueValue) { 159756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = Visit(C->getTrueExpr(), alwaysAdd); 1598d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1599f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 1600f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = NULL; 1601f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek } 1602f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek else 1603f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek LHSBlock = ConfluenceBlock; 16041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1605f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block for the RHS expression. 1606f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Succ = ConfluenceBlock; 16079c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *RHSBlock = Visit(C->getFalseExpr(), alwaysAdd); 1608d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 1609f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek return 0; 16101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 161156df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith // If the condition is a logical '&&' or '||', build a more accurate CFG. 161256df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 161356df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast<BinaryOperator>(C->getCond()->IgnoreParens())) 161456df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (Cond->isLogicalOp()) 161556df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith return VisitLogicalOperator(Cond, C, LHSBlock, RHSBlock).first; 161656df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith 1617f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek // Create the block that will contain the condition. 1618f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block = createBlock(false); 16191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 162000998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 16210a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C->getCond()); 1622f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 16230a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 1624f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek Block->setTerminator(C); 162556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Expr *condExpr = C->getCond(); 1626d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1627f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (opaqueValue) { 1628f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Run the condition expression if it's not trivially expressed in 1629f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // terms of the opaque value (or if there is no opaque value). 1630f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek if (condExpr != opaqueValue) 1631f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek addStmt(condExpr); 1632d40baf6a77f6353a93f181da5d1347d3730aad37John McCall 1633f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // Before that, run the common subexpression if there was one. 1634f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek // At least one of this or the above will be run. 1635f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(BCO->getCommon()); 1636f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek } 1637f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek 1638f226d18f0f49394cec460699f4268e32bd0ce833Ted Kremenek return addStmt(condExpr); 1639f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek} 1640f34bb2eaa87aa28bcc8b6ff0dfc696cd75605b11Ted Kremenek 16414f88063677a2d990a44bb0d5f8437d2498b91d7fTed KremenekCFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { 1642bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // Check if the Decl is for an __label__. If so, elide it from the 1643bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek // CFG entirely. 1644bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek if (isa<LabelDecl>(*DS->decl_begin())) 1645bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek return Block; 1646bc869de349227707a07ccc783344d255cf37ec16Ted Kremenek 164729c9e62f412c9db3ee238db2472390685a6303f3Ted Kremenek // This case also handles static_asserts. 16488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (DS->isSingleDecl()) 16498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitDeclSubExpr(DS); 16501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *B = 0; 16521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1653fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose // Build an individual DeclStmt for each decl. 1654fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose for (DeclStmt::reverse_decl_iterator I = DS->decl_rbegin(), 1655fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose E = DS->decl_rend(); 1656fd8b43596478b779b6777cb3a595e69d7856c378Jordan Rose I != E; ++I) { 16574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Get the alignment of the new DeclStmt, padding out to >=8 bytes. 16584f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8 16594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ? 8 : llvm::AlignOf<DeclStmt>::Alignment; 16601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16614f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Allocate the DeclStmt using the BumpPtrAllocator. It will get 16624f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // automatically freed with the CFG. 16634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclGroupRef DG(*I); 16644f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Decl *D = *I; 16651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A); 16664f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D)); 166749a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose cfg->addSyntheticDeclStmt(DSNew, DS); 16681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16694f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // Append the fake DeclStmt to block. 16708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = VisitDeclSubExpr(DSNew); 16714f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 16721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return B; 16744f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 16751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16764f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitDeclSubExpr - Utility method to add block-level expressions for 16778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski/// DeclStmts and initializers in them. 16789c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { 16798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert(DS->isSingleDecl() && "Can handle single declarations only."); 16808599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl()); 16811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!VD) { 16832794bc0e3757992194dd587d0f6a253ec72afc9aJordan Rose // Of everything that can be declared in a DeclStmt, only VarDecls impact 16842794bc0e3757992194dd587d0f6a253ec72afc9aJordan Rose // runtime semantics. 16854f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 16868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 16871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool IsReference = false; 16898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski bool HasTemporaries = false; 16908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 1691fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek // Guard static initializers under a branch. 16925062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek CFGBlock *blockAfterStaticInit = 0; 16935062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek 16945062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (BuildOpts.AddStaticInitBranches && VD->isStaticLocal()) { 16955062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek // For static variables, we need to create a branch to track 16965062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek // whether or not they are initialized. 16975062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (Block) { 16985062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek Succ = Block; 16995062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek Block = 0; 17005062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (badCFG) 17015062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek return 0; 17025062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek } 17035062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek blockAfterStaticInit = Succ; 17045062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek } 1705fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek 17068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors of temporaries in initialization expression should be called 17078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // after initialization finishes. 17084f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Expr *Init = VD->getInit(); 17098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (Init) { 17108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference = VD->getType()->isReferenceType(); 17114765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall HasTemporaries = isa<ExprWithCleanups>(Init); 17128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 17135a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors && HasTemporaries) { 17148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Generate destructors for temporaries in initialization expression. 17154765fa05b5652fcc4356371c2f481d0ea9a1b007John McCall VisitForTemporaryDtors(cast<ExprWithCleanups>(Init)->getSubExpr(), 17168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski IsReference); 17178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 17188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 17198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 17208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 1721892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, DS); 1722550f2234fc9218914c325041067052342dfce553Ted Kremenek 1723550f2234fc9218914c325041067052342dfce553Ted Kremenek // Keep track of the last non-null block, as 'Block' can be nulled out 1724550f2234fc9218914c325041067052342dfce553Ted Kremenek // if the initializer expression is something like a 'while' in a 1725550f2234fc9218914c325041067052342dfce553Ted Kremenek // statement-expression. 1726550f2234fc9218914c325041067052342dfce553Ted Kremenek CFGBlock *LastBlock = Block; 17271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Init) { 1729550f2234fc9218914c325041067052342dfce553Ted Kremenek if (HasTemporaries) { 17308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For expression with temporaries go directly to subexpression to omit 17318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // generating destructors for the second time. 1732550f2234fc9218914c325041067052342dfce553Ted Kremenek ExprWithCleanups *EC = cast<ExprWithCleanups>(Init); 1733550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(EC->getSubExpr())) 1734550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1735550f2234fc9218914c325041067052342dfce553Ted Kremenek } 1736550f2234fc9218914c325041067052342dfce553Ted Kremenek else { 1737550f2234fc9218914c325041067052342dfce553Ted Kremenek if (CFGBlock *newBlock = Visit(Init)) 1738550f2234fc9218914c325041067052342dfce553Ted Kremenek LastBlock = newBlock; 1739550f2234fc9218914c325041067052342dfce553Ted Kremenek } 17404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } 17411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17424f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // If the type of VD is a VLA, then we must process its size expressions. 1743f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); 17448f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) { 17458f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek if (CFGBlock *newBlock = addStmt(VA->getSizeExpr())) 17468f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek LastBlock = newBlock; 17478f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek } 17481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1749fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski // Remove variable from local scope. 1750fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski if (ScopePos && VD == *ScopePos) 1751fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski ++ScopePos; 1752fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski 17530f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek CFGBlock *B = LastBlock; 17545062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek if (blockAfterStaticInit) { 1755fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek Succ = B; 17560f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek Block = createBlock(false); 17570f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek Block->setTerminator(DS); 17585062bb22706c8f2ceec5815533ff5a88d169d098Ted Kremenek addSuccessor(Block, blockAfterStaticInit); 17590f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek addSuccessor(Block, B); 17600f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek B = Block; 1761fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek } 1762fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek 1763fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek return B; 1764d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1765fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 17669c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { 17676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We may see an if statement in the middle of a basic block, or it may be the 17686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // first statement we are processing. In either case, we create a new basic 17696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. First, we create the blocks for the then...else statements, and 17706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // then we create the block containing the if statement. If we were in the 17716c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // middle of a block, we stop processing that block. That block is then the 17726c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // implicit successor for the "then" and "else" clauses. 17736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 177404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 177504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // won't be restored when traversing AST. 177604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 177704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 177804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Create local scope for possible condition variable. 177904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // Store scope position. Add implicit destructor. 17809c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 178104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 178204e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeForVarDecl(VD); 178304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, I); 178404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski } 178504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 1786fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // The block we were processing is now finished. Make it the successor 17876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 17886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 1789d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = Block; 1790d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 17914e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 1792c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 17936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1794b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the false branch. 17959c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ElseBlock = Succ; 17966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 17979c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Else = I->getElse()) { 1798d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 17996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1800d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block so that the recursive call to Visit will 18016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // create a new basic block. 1802d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 180304e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 180404e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 180504e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 180604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Else)) 180704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Else); 180804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 18094f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ElseBlock = addStmt(Else); 18106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1811b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek if (!ElseBlock) // Can occur when the Else body has all NullStmts. 1812b6f7b72047b3fd3f96a5040e1e4d520a9dea01cdTed Kremenek ElseBlock = sv.get(); 18134e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 1814d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18154e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18164e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 1817c310e933a9b023a280f3aa02e5a0c75398555e13Ted Kremenek } 18186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1819b6f1d782e0dc5fad138a17e6aa0ff6f9bc4788c6Ted Kremenek // Process the true branch. 18209c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ThenBlock; 1821d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 18229c378f705405d37f49795d5e915989de774fe11fTed Kremenek Stmt *Then = I->getThen(); 18236db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Then); 1824d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> sv(Succ); 18256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Block = NULL; 182604e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 182704e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // If branch is not a compound statement create implicit scope 182804e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski // and add destructors. 182904e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski if (!isa<CompoundStmt>(Then)) 183004e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski addLocalScopeAndDtors(Then); 183104e046cbf7153fc261d730d460f081322d5c42f6Marcin Swiderski 18324f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek ThenBlock = addStmt(Then); 18336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1834dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek if (!ThenBlock) { 1835dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // We can reach here if the "then" body has all NullStmts. 1836dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // Create an empty block so we can distinguish between true and false 1837dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek // branches in path-sensitive analyses. 1838dbdf7949a7a50f5a65055a3e95f6432ecc541056Ted Kremenek ThenBlock = createBlock(false); 18390a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ThenBlock, sv.get()); 18406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else if (Block) { 1841d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 18424e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 18436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 18440cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek } 1845d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 18463f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by 18473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // having these handle the actual control-flow jump. Note that 18483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // if we introduce a condition variable, e.g. "if (int x = exp1 || exp2)" 18493f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // we resort to the old control-flow behavior. This special handling 18503f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // removes infeasible paths from the control-flow graph by having the 18513f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // control-flow transfer of '&&' or '||' go directly into the then/else 18523f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // blocks directly. 18533f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!I->getConditionVariable()) 185456df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 185556df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast<BinaryOperator>(I->getCond()->IgnoreParens())) 18563f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) 18573f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return VisitLogicalOperator(Cond, I, ThenBlock, ElseBlock).first; 18583f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 18596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now create a new block containing the if statement. 1860d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 18616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1862d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Set the terminator of the new block to the If statement. 1863d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(I); 18646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 186500998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 18660a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(I->getCond()); 186700998a068e50945118f334c98af05ed44d7c22a6Mike Stump 1868d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now add the successors. 18690a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock); 18700a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock); 18716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the condition as the last statement in the new block. This may create 18736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // new blocks as the condition may contain control-flow. Any newly created 18746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // blocks will be pointed to be "Block". 18758f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek CFGBlock *LastBlock = addStmt(I->getCond()); 1876ad5a894df1841698c824381b414630799adc26caTed Kremenek 187761dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // Finally, if the IfStmt contains a condition variable, add both the IfStmt 187861dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek // and the condition variable initialization to the CFG. 187961dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (VarDecl *VD = I->getConditionVariable()) { 188061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek if (Expr *Init = VD->getInit()) { 188161dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek autoCreateBlock(); 1882d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, I->getConditionVariableDeclStmt()); 18838f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek LastBlock = addStmt(Init); 188461dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 188561dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek } 1886ad5a894df1841698c824381b414630799adc26caTed Kremenek 18878f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek return LastBlock; 1888d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 18896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 18919c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) { 18926c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 1893d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // 18946d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // NOTE: If a "return" appears in the middle of a block, this means that the 18956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // code afterwards is DEAD (unreachable). We still keep a basic block 18966d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for that code; a simple "mark-and-sweep" from the entry block will be 18976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // able to report such dead blocks. 1898d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 1899d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the new block. 1900d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 19016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1902fcb72ac985c26372315fabc08d43d6f66ff906b4Marcin Swiderski addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R); 19031ae74842cd1be37a8d99d0865623ef16432d3b67Pavel Labath 19041ae74842cd1be37a8d99d0865623ef16432d3b67Pavel Labath // If the one of the destructors does not return, we already have the Exit 19051ae74842cd1be37a8d99d0865623ef16432d3b67Pavel Labath // block as a successor. 19061ae74842cd1be37a8d99d0865623ef16432d3b67Pavel Labath if (!Block->hasNoReturnElement()) 19071ae74842cd1be37a8d99d0865623ef16432d3b67Pavel Labath addSuccessor(Block, &cfg->getExit()); 19086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the return statement to the block. This may create new blocks if R 19106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // contains control-flow (short-circuit operations). 1911852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(R, AddStmtChoice::AlwaysAdd); 1912d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 19130cebe3e29b22d11f2c65ef28fcfb5f0431877266Ted Kremenek 19149c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { 1915d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Get the block of the labeled statement. Add it to our map. 19164f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(L->getSubStmt()); 1917ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner CFGBlock *LabelBlock = Block; 19186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!LabelBlock) // This can happen when the body is empty, i.e. 19204f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LabelBlock = createBlock(); // scopes that only contains NullStmts. 19216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1922ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner assert(LabelMap.find(L->getDecl()) == LabelMap.end() && 1923ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner "label already in map"); 1924ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos); 19256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19266d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Labels partition blocks, so this is the end of the basic block we were 19276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing (L is the block's label). Because this is label (and we have 19286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // already processed the substatement) there is no extra control-flow to worry 19296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // about. 19309cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek LabelBlock->setLabel(L); 1931d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 19324e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 19336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary); 1935d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 19366d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1937d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // This block is now the implicit successor of other blocks. 1938d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = LabelBlock; 19396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1940d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return LabelBlock; 1941d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 194231dcd3c8c4df5a656f58f50ea73afc177c101c67Ted Kremenek 194383748e2f41ea0ac7c954946feb5da9ccc6ab8becTed KremenekCFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { 194483748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *LastBlock = VisitNoRecurse(E, asc); 194583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), 194683748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek et = E->capture_init_end(); it != et; ++it) { 194783748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Expr *Init = *it) { 194883748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek CFGBlock *Tmp = Visit(Init); 194983748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek if (Tmp != 0) 195083748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek LastBlock = Tmp; 195183748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 195283748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek } 195383748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek return LastBlock; 195483748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek} 195583748e2f41ea0ac7c954946feb5da9ccc6ab8becTed Kremenek 19569c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { 19576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Goto is a control-flow statement. Thus we stop processing the current 19586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block and create a new one. 19594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 1960d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 1961d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(G); 19626d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 19636d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we already know the mapping to the label block add the successor now. 1964d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LabelMapTy::iterator I = LabelMap.find(G->getLabel()); 19656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 1966d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (I == LabelMap.end()) 1967d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We will need to backpatch this block later. 1968f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BackpatchBlocks.push_back(JumpSource(Block, ScopePos)); 1969f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski else { 1970f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski JumpTarget JT = I->second; 19719ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, JT.scopePosition, G); 19729ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, JT.block); 1973f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } 1974d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 19756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Block; 1976d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 1977d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 19789c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { 19799c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 19806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 198147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 198247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // won't be restored when traversing AST. 198347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 198447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 198547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Create local scope for init statement and possible condition variable. 198647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Add destructor for init statement and condition variable. 198747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // Store scope position for continue statement. 19889c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Init = F->getInit()) 198947575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForStmt(Init); 1990f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 1991f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 19929c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = F->getConditionVariable()) 199347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeForVarDecl(VD); 199447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski LocalScope::const_iterator ContinueScopePos = ScopePos; 199547575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 199647575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); 199747575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 1998fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "for" is a control-flow statement. Thus we stop processing the current 1999fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 2000d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2001d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20024e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2003d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 20044f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 20054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 20066d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20073f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // Save the current value for the break targets. 20083f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek // All breaks should go to the code following the loop. 2009f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 201047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 20113f64a0e3be2c9408f8256bd3aa9f0ce9e268982cTed Kremenek 20123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *BodyBlock = 0, *TransitionBlock = 0; 201300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2014d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create the loop body. 2015d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 20166db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(F->getBody()); 20176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Save the current values for Block, Succ, continue and break targets. 20193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 20203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 20216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20223f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Create an empty block to represent the transition block for looping back 20233f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // to the head of the loop. If we have increment code, it will 20243f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // go in this block as well. 20253f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = Succ = TransitionBlock = createBlock(false); 20263f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TransitionBlock->setLoopTarget(F); 20276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20289c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInc()) { 20296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Generate increment code in its own basic block. This is the target of 20306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // continue statements. 20314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek Succ = addStmt(I); 2032e933450535ab077b95e59f929a4ccb25b6f360e6Ted Kremenek } 20336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20343575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek // Finish up the increment (or empty) block if it hasn't been already. 20353575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek if (Block) { 20363575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek assert(Block == Succ); 2037d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 20384e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 20393575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek Block = 0; 20403575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek } 20416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20423f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The starting block for the loop increment is the block that should 20433f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // represent the 'loop target' for looping back to the start of the loop. 20443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 20453f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ContinueJumpTarget.block->setLoopTarget(F); 20466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20473f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Loop body should end with destructor of Condition variable (if any). 20483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); 20493575f84e459033d6427b84b4b795b22c85c4d27dTed Kremenek 205047575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // If body is not a compound statement create implicit scope 205147575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski // and add destructors. 205247575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski if (!isa<CompoundStmt>(F->getBody())) 205347575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski addLocalScopeAndDtors(F->getBody()); 205447575f1f775f5f250be4f395fa694a7274a65f33Marcin Swiderski 20556d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now populate the body block, and in the process create new blocks as we 20566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // walk the body of the loop. 20573f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = addStmt(F->getBody()); 2058af603f742491dc4707138c0293d295171fdd51baTed Kremenek 20593f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (!BodyBlock) { 20603f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // In the case of "for (...;...;...);" we can have a null BodyBlock. 20613f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Use the continue jump target as the proxy for the body. 20623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = ContinueJumpTarget.block; 20633f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 2064d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu else if (badCFG) 2065941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek return 0; 20663f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20673f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20683f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because of short-circuit evaluation, the condition of the loop can span 20693f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 20703f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // evaluate the condition. 20713f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0; 20723f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20733f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 20743f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *C = F->getCond(); 20753f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20763f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle logical operators, which have a slightly 20773f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // more optimal CFG representation. 207856df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = 207956df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith dyn_cast_or_null<BinaryOperator>(C ? C->IgnoreParens() : 0)) 20803f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) { 20813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(EntryConditionBlock, ExitConditionBlock) = 20823f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(Cond, F, BodyBlock, LoopSuccessor); 20833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 20843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 20856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 20863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The default case when not handling logical operators. 20873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = ExitConditionBlock = createBlock(false); 20883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitConditionBlock->setTerminator(F); 20893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20903f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // See if this is a known constant. 20913f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TryResult KnownVal(true); 20923f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 20933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (C) { 20943f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Now add the actual condition to the condition block. 20953f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because the condition itself may contain control-flow, new blocks may 20963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // be created. Thus we update "Succ" after adding the condition. 20973f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = ExitConditionBlock; 20983f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(C); 20993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 21003f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // If this block contains a condition variable, add both the condition 21013f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // variable and initializer to the CFG. 21023f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (VarDecl *VD = F->getConditionVariable()) { 21033f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Expr *Init = VD->getInit()) { 21043f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek autoCreateBlock(); 21053f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek appendStmt(Block, F->getConditionVariableDeclStmt()); 21063f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(Init); 21073f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(Block == EntryConditionBlock); 21083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 21093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 21103f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 21113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Block && badCFG) 21123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 21133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 21143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek KnownVal = tryEvaluateBool(C); 21153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 21163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 21173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Add the loop body entry as a successor to the condition. 21180a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 21193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the condition block with the code that follows the loop. (the 21203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // false branch). 21213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 21226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21233f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } while (false); 21243f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 21253f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the loop-back block to the entry condition block. 21263f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(TransitionBlock, EntryConditionBlock); 21273f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 21283f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The condition block is the implicit successor for any code above the loop. 21293f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Succ = EntryConditionBlock; 21306d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2131d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If the loop contains initialization, create a new block for those 21326d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statements. This block can also contain statements that precede the loop. 21339c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *I = F->getInit()) { 2134d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(); 213549af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return addStmt(I); 21362bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek } 213736f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan 213836f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // There is no loop initialization. We are thus basically a while loop. 213936f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan // NULL out Block to force lazy block construction. 214036f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Block = NULL; 214136f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan Succ = EntryConditionBlock; 214236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan return EntryConditionBlock; 2143d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2144d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2145115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted KremenekCFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { 21463179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, M)) { 2147115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek autoCreateBlock(); 2148247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, M); 2149115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek } 2150892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(M->getBase()); 2151115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek} 2152115c1b9cc758d15f38e1d2ad4cf07b1cacfb3115Ted Kremenek 21539c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { 2154514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Objective-C fast enumeration 'for' statements: 2155514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC 2156514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2157514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( Type newVariable in collection_expression ) { statements } 2158514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2159514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 2160514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2161514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // prologue: 2162514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. collection_expression 2163514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 2164514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // loop_entry: 21654cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // 1. side-effects of element expression 2166514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 1. ObjCForCollectionStmt [performs binding to newVariable] 2167514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil] 2168514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // TB: 2169514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // statements 2170514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // T. jump to loop_entry 2171514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // FB: 2172514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // what comes after 2173514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2174514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // and 2175514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2176514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Type existingItem; 2177514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // for ( existingItem in expression ) { statements } 2178514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 2179514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // becomes: 2180514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 21816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same with newVariable replaced with existingItem; the binding works 21826d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the same except that for one ObjCForCollectionStmt::getElement() returns 21836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // a DeclStmt and the other returns a DeclRefExpr. 2184514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // 21856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21869c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = 0; 21876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2188514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek if (Block) { 2189d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 21904e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2191514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek LoopSuccessor = Block; 2192514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek Block = 0; 21934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 21944f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 21956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21964cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Build the condition blocks. 21979c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 21986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 21994cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Set the terminator for the "exit" condition block. 22006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(S); 22016d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The last statement in the block should be the ObjCForCollectionStmt, which 22036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // performs the actual binding to 'element' and determines if there are any 22046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // more items in the collection. 2205892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(ExitConditionBlock, S); 22064cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = ExitConditionBlock; 22076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22084cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Walk the 'element' expression to see if there are any side-effects. We 2209fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // generate new blocks as necessary. We DON'T add the statement by default to 22106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the CFG unless it contains control-flow. 2211012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek CFGBlock *EntryConditionBlock = Visit(S->getElement(), 2212012614ecf78442368ec82ee30efb3bc047b413e6Ted Kremenek AddStmtChoice::NotAlwaysAdd); 22136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump if (Block) { 2214d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22154e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 22164e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek Block = 0; 22174e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 22186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // The condition block is the implicit successor for the loop body as well as 22206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // any code above the loop. 22214cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Succ = EntryConditionBlock; 22226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22234cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Now create the true branch. 22246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump { 22254cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Save the current values for Succ, continue and break targets. 22264c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2227f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 22284c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks save_break(BreakJumpTarget); 22294c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks 22304c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks // Add an intermediate block between the BodyBlock and the 22314c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks // EntryConditionBlock to represent the "loop back" transition, for looping 22324c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks // back to the head of the loop. 22334c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks CFGBlock *LoopBackBlock = 0; 22344c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks Succ = LoopBackBlock = createBlock(); 22354c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks LoopBackBlock->setLoopTarget(S); 22364c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks 2237f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 22384c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks ContinueJumpTarget = JumpTarget(Succ, ScopePos); 22396d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22409c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = addStmt(S->getBody()); 22416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22424cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek if (!BodyBlock) 22434c98b1f67cdf385e05a86d54201b319cf1f1c042Anna Zaks BodyBlock = ContinueJumpTarget.block; // can happen for "for (X in Y) ;" 22444e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2245d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 22464e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 22474e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 22486d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22494cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // This new body block is a successor to our "exit" condition block. 22500a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, BodyBlock); 22514cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek } 22526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22534cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // Link up the condition block with the code that follows the loop. 22544cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek // (the false branch). 22550a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopSuccessor); 22564cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek 2257514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek // Now create a prologue block to contain the collection expression. 22584cb3a855df3b3f8d551565cae9f43939a301ea89Ted Kremenek Block = createBlock(); 2259514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek return addStmt(S->getCollection()); 22606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 22616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22628e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted KremenekCFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { 22638e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // Inline the body. 22648e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek return addStmt(S->getSubStmt()); 22658e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek // TODO: consider adding cleanups for the end of @autoreleasepool scope. 22668e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek} 22678e282c332f8ad51dedf86a185a4dcb78ef93fb51Ted Kremenek 22689c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 2269b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // FIXME: Add locking 'primitives' to CFG for @synchronized. 22706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2271b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the body. 22724f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CFGBlock *SyncBlock = addStmt(S->getSynchBody()); 22736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2274da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // The sync body starts its own basic block. This makes it a little easier 2275da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek // for diagnostic clients. 2276da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek if (SyncBlock) { 2277d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2278da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek return 0; 22796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2280da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek Block = 0; 2281fadebbafe622752c3c6565b53ce8cd42bbbbd90cTed Kremenek Succ = SyncBlock; 2282da5348eda7bb45d715561249dec9833d51dfda67Ted Kremenek } 22836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22844beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek // Add the @synchronized to the CFG. 22854beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek autoCreateBlock(); 2286247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, S); 22874beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek 2288b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek // Inline the sync expression. 22894f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return addStmt(S->getSynchExpr()); 2290b3b0b3624e462c2940f65b86e773bfc300005203Ted Kremenek} 22916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 22929c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { 22934f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME 229490658ec72542df44eb462c69056184d2946bdbceTed Kremenek return NYS(); 2295e31c0d206b872b056dc42c3af21b11d5de4edfd9Ted Kremenek} 2296514de5a21645900c92cf4f4f7313d6f66945d134Ted Kremenek 22974b9c2d235fb9449e249d74f48ecfec601650de93John McCallCFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { 22984b9c2d235fb9449e249d74f48ecfec601650de93John McCall autoCreateBlock(); 22994b9c2d235fb9449e249d74f48ecfec601650de93John McCall 23004b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Add the PseudoObject as the last thing. 23014b9c2d235fb9449e249d74f48ecfec601650de93John McCall appendStmt(Block, E); 23024b9c2d235fb9449e249d74f48ecfec601650de93John McCall 23034b9c2d235fb9449e249d74f48ecfec601650de93John McCall CFGBlock *lastBlock = Block; 23044b9c2d235fb9449e249d74f48ecfec601650de93John McCall 23054b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Before that, evaluate all of the semantics in order. In 23064b9c2d235fb9449e249d74f48ecfec601650de93John McCall // CFG-land, that means appending them in reverse order. 23074b9c2d235fb9449e249d74f48ecfec601650de93John McCall for (unsigned i = E->getNumSemanticExprs(); i != 0; ) { 23084b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *Semantic = E->getSemanticExpr(--i); 23094b9c2d235fb9449e249d74f48ecfec601650de93John McCall 23104b9c2d235fb9449e249d74f48ecfec601650de93John McCall // If the semantic is an opaque value, we're being asked to bind 23114b9c2d235fb9449e249d74f48ecfec601650de93John McCall // it to its source expression. 23124b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) 23134b9c2d235fb9449e249d74f48ecfec601650de93John McCall Semantic = OVE->getSourceExpr(); 23144b9c2d235fb9449e249d74f48ecfec601650de93John McCall 23154b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (CFGBlock *B = Visit(Semantic)) 23164b9c2d235fb9449e249d74f48ecfec601650de93John McCall lastBlock = B; 23174b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 23184b9c2d235fb9449e249d74f48ecfec601650de93John McCall 23194b9c2d235fb9449e249d74f48ecfec601650de93John McCall return lastBlock; 23204b9c2d235fb9449e249d74f48ecfec601650de93John McCall} 23214b9c2d235fb9449e249d74f48ecfec601650de93John McCall 23229c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { 23239c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 23246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 232505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 232605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // won't be restored when traversing AST. 232705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 232805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 232905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Create local scope for possible condition variable. 233005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Store scope position for continue statement. 2331f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski LocalScope::const_iterator LoopBeginScopePos = ScopePos; 23329c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 233305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeForVarDecl(VD); 233405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 233505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski } 2336f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski 2337fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // "while" is a control-flow statement. Thus we stop processing the current 2338fefb9f7009702befaf715e7a8debc9505c3c8634Mike Stump // block. 2339d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2340d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 23414e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2342d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 23436b12da9f89b7863e6fc995312355b94197b75657Ted Kremenek Block = 0; 23443f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } else { 23454f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 234649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 23476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 23483f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *BodyBlock = 0, *TransitionBlock = 0; 234900998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2350d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 2351d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 2352f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek assert(W->getBody()); 2353d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 23543f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Save the current values for Block, Succ, continue and break targets. 2355f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2356f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 23573f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek save_break(BreakJumpTarget); 2358f6e8541dd884029b85483a319ce7d32f3e476dccTed Kremenek 23596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Create an empty block to represent the transition block for looping back 23606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to the head of the loop. 23613f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Succ = TransitionBlock = createBlock(false); 23623f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek TransitionBlock->setLoopTarget(W); 2363f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); 23646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2365d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 236605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 23676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 236805adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // Loop body should end with destructor of Condition variable (if any). 236905adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); 237005adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 237105adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 237205adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 237305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(W->getBody())) 237405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(W->getBody()); 237505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2376d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 23773f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek BodyBlock = addStmt(W->getBody()); 23786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2379af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 23809ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;" 23813f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek else if (Block && badCFG) 23823f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 23833f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 23843f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23853f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because of short-circuit evaluation, the condition of the loop can span 23863f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 23873f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // evaluate the condition. 23883f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek CFGBlock *EntryConditionBlock = 0, *ExitConditionBlock = 0; 23893f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23903f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek do { 23913f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Expr *C = W->getCond(); 23923f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 23933f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Specially handle logical operators, which have a slightly 23943f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // more optimal CFG representation. 239556df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith if (BinaryOperator *Cond = dyn_cast<BinaryOperator>(C->IgnoreParens())) 23963f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Cond->isLogicalOp()) { 23973f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek llvm::tie(EntryConditionBlock, ExitConditionBlock) = 23983f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek VisitLogicalOperator(Cond, W, BodyBlock, 23993f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek LoopSuccessor); 24003f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek break; 24013f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 24023f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 24033f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // The default case when not handling logical operators. 2404857f5681f5e2bbb482f41f461add502b556c712aTed Kremenek ExitConditionBlock = createBlock(false); 24053f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek ExitConditionBlock->setTerminator(W); 24063f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 24073f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Now add the actual condition to the condition block. 24083f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Because the condition itself may contain control-flow, new blocks may 24093f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // be created. Thus we update "Succ" after adding the condition. 24103f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = ExitConditionBlock; 24113f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek Block = EntryConditionBlock = addStmt(C); 24123f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 24133f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // If this block contains a condition variable, add both the condition 24143f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // variable and initializer to the CFG. 24153f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (VarDecl *VD = W->getConditionVariable()) { 24163f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Expr *Init = VD->getInit()) { 24173f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek autoCreateBlock(); 24183f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek appendStmt(Block, W->getConditionVariableDeclStmt()); 24193f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek EntryConditionBlock = addStmt(Init); 24203f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek assert(Block == EntryConditionBlock); 24213f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } 24224e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 24236d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24243f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek if (Block && badCFG) 24253f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek return 0; 24263f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 24273f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // See if this is a known constant. 24283f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek const TryResult& KnownVal = tryEvaluateBool(C); 24293f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 2430941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Add the loop body entry as a successor to the condition. 24310a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock); 24323f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the condition block with the code that follows the loop. (the 24333f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // false branch). 24343f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 24353f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek 24363f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek } while(false); 24376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24383f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek // Link up the loop-back block to the entry condition block. 24393f635c08b2d0b2d5bafb38da09589cb238407faaTed Kremenek addSuccessor(TransitionBlock, EntryConditionBlock); 24406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24416d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the condition block since we loop back 24426d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // to this block. NULL out Block to force lazy creation of another block. 2443d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 24446d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24454ec010a6ccf4db2ab2ef9e68942642d50f7f193cTed Kremenek // Return the condition block, which is the dominating block for the loop. 24465482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = EntryConditionBlock; 244749af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek return EntryConditionBlock; 2448d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 24491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 24519c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { 24524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // FIXME: For now we pretend that @catch and the code it contains does not 24534f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // exit. 24544f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return Block; 24554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 24566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24579c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { 24582fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // FIXME: This isn't complete. We basically treat @throw like a return 24592fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // statement. 24606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24616c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2462d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24634f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 24646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24652fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // Create the new block. 24662fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek Block = createBlock(false); 24676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24682fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek // The Exit block is the only successor. 24690a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 24706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add the statement to the block. This may create new blocks if S contains 24726d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow (short-circuit operations). 2473852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(S, AddStmtChoice::AlwaysAdd); 24742fda504dccd79f91ac9a7d82acecfbab3eaa1719Ted Kremenek} 2475989d52d469df0c202f7de82f54407066c7db2e63Ted Kremenek 24769c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { 24776c2497248bc4f7fd8e5fb0a206d20abbf0e16645Ted Kremenek // If we were in the middle of a block we stop processing that block. 2478d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 24790979d80615df97c675423de631c1b884819f4712Mike Stump return 0; 24800979d80615df97c675423de631c1b884819f4712Mike Stump 24810979d80615df97c675423de631c1b884819f4712Mike Stump // Create the new block. 24820979d80615df97c675423de631c1b884819f4712Mike Stump Block = createBlock(false); 24830979d80615df97c675423de631c1b884819f4712Mike Stump 24845d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (TryTerminatedBlock) 24855d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The current try statement is the only successor. 24860a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, TryTerminatedBlock); 2487ad5a894df1841698c824381b414630799adc26caTed Kremenek else 24885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // otherwise the Exit block is the only successor. 24890a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, &cfg->getExit()); 24900979d80615df97c675423de631c1b884819f4712Mike Stump 24910979d80615df97c675423de631c1b884819f4712Mike Stump // Add the statement to the block. This may create new blocks if S contains 24920979d80615df97c675423de631c1b884819f4712Mike Stump // control-flow (short-circuit operations). 2493852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return VisitStmt(T, AddStmtChoice::AlwaysAdd); 24940979d80615df97c675423de631c1b884819f4712Mike Stump} 24950979d80615df97c675423de631c1b884819f4712Mike Stump 24969c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { 24979c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 24986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 24998f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // "do...while" is a control-flow statement. Thus we stop processing the 25008f9893a2beeacd5149bd2d3d4c6e130516915068Mike Stump // current block. 2501d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2502d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25034e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2504d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek LoopSuccessor = Block; 25054f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek } else 25064f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek LoopSuccessor = Succ; 25076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Because of short-circuit evaluation, the condition of the loop can span 25096d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that 25106d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // evaluate the condition. 25119c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ExitConditionBlock = createBlock(false); 25129c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *EntryConditionBlock = ExitConditionBlock; 25136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 251449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Set the terminator for the "exit" condition block. 25156d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump ExitConditionBlock->setTerminator(D); 25166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Now add the actual condition to the condition block. Because the condition 25186d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // itself may contain control-flow, new blocks may be created. 25199c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) { 252049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = ExitConditionBlock; 252149af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek EntryConditionBlock = addStmt(C); 25224e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2523d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25244e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 25254e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 252649af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek } 25276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25285482713d70ecbfe608940018046aa248b3d03443Ted Kremenek // The condition block is the implicit successor for the loop body. 252949af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Succ = EntryConditionBlock; 253049af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 253100998a068e50945118f334c98af05ed44d7c22a6Mike Stump // See if this is a known constant. 25320a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(D->getCond()); 253300998a068e50945118f334c98af05ed44d7c22a6Mike Stump 2534d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Process the loop body. 25359c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *BodyBlock = NULL; 2536d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek { 25376db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(D->getBody()); 25386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2539d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current values for Block, Succ, and continue and break targets 2540f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 2541f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget), 2542f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski save_break(BreakJumpTarget); 25436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2544d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All continues within this loop should go to the condition block 2545f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos); 25466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2547d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // All breaks should go to the code following the loop. 2548f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 25496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2550d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // NULL out Block to force lazy instantiation of blocks for the body. 2551b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek Block = NULL; 25526d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 255305adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // If body is not a compound statement create implicit scope 255405adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski // and add destructors. 255505adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski if (!isa<CompoundStmt>(D->getBody())) 255605adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski addLocalScopeAndDtors(D->getBody()); 255705adedcb5e199e377e35f576288caf5ceed40136Marcin Swiderski 2558d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create the body. The returned block is the entry to the loop body. 25594f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek BodyBlock = addStmt(D->getBody()); 25606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2561af603f742491dc4707138c0293d295171fdd51baTed Kremenek if (!BodyBlock) 2562a9d996dbeb719200c4a9d86f68166a237583025fTed Kremenek BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)" 25634e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek else if (Block) { 2564d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 25654e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 25664e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 25676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2568d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek if (!KnownVal.isFalse()) { 2569d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add an intermediate block between the BodyBlock and the 2570d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // ExitConditionBlock to represent the "loop back" transition. Create an 2571d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // empty block to represent the transition block for looping back to the 2572d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // head of the loop. 2573d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // FIXME: Can we do this more efficiently without adding another block? 2574d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Block = NULL; 2575d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek Succ = BodyBlock; 2576d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek CFGBlock *LoopBackBlock = createBlock(); 2577d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek LoopBackBlock->setLoopTarget(D); 2578d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek 2579d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek // Add the loop body entry as a successor to the condition. 25800a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, LoopBackBlock); 2581d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek } 2582d173dc7825e999edab836f8215a82a96eae7c738Ted Kremenek else 25830a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, NULL); 2584b5c13b0f4e438391b31dacb87641be7a1b990b57Ted Kremenek } 25856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2586941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // Link up the condition block with the code that follows the loop. 2587941fde8019d47c694b8483db45d5878818fa69d1Ted Kremenek // (the false branch). 25880a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor); 25896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 25906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // There can be no more statements in the body block(s) since we loop back to 25916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the body. NULL out Block to force lazy creation of another block. 2592d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 25936d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2594d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Return the loop body, which is the dominating block for the loop. 25955482713d70ecbfe608940018046aa248b3d03443Ted Kremenek Succ = BodyBlock; 2596d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return BodyBlock; 2597d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2598d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 25999c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { 2600d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // "continue" is a control-flow statement. Thus we stop processing the 2601d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // current block. 2602d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 2603d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu return 0; 26046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2605d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now create a new block that ends with the continue statement. 2606d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = createBlock(false); 2607d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block->setTerminator(C); 26086d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2609d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // If there is no target for the continue, then we are looking at an 2610235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek // incomplete AST. This means the CFG cannot be constructed. 26119ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek if (ContinueJumpTarget.block) { 26129ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C); 26139ce5270f0aadaaf03a0cf705787f42ce9eb1194cTed Kremenek addSuccessor(Block, ContinueJumpTarget.block); 2614f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski } else 2615235c5ed8bee5bbcb45de1707d6988635e49b10b8Ted Kremenek badCFG = true; 26166d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2617d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek return Block; 2618d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 26191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2620f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter CollingbourneCFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, 2621f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne AddStmtChoice asc) { 262213fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek 26233179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 262413fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2625892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, E); 262613fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 26271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26284f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek // VLA types have expressions that must be evaluated. 262997e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek CFGBlock *lastBlock = Block; 263097e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek 26314f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (E->isArgumentType()) { 2632f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall for (const VariableArrayType *VA =FindVA(E->getArgumentType().getTypePtr()); 26334f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek VA != 0; VA = FindVA(VA->getElementType().getTypePtr())) 263497e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek lastBlock = addStmt(VA->getSizeExpr()); 2635f91a5b008d1a63630ae483247204c2651e512fa1Ted Kremenek } 263697e50714c262cc421f960303171d2c1afbc9bb4fTed Kremenek return lastBlock; 2637d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 26381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26394f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// VisitStmtExpr - Utility method to handle (nested) statement 26404f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek/// expressions (a GCC extension). 26419c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { 26423179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, SE)) { 264313fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek autoCreateBlock(); 2644892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek appendStmt(Block, SE); 264513fc08a323b29dd97a46def1e3a15bf082476efaTed Kremenek } 26464f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return VisitCompoundStmt(SE->getSubStmt()); 26474f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek} 2648d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 26499c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { 26506d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // "switch" is a control-flow statement. Thus we stop processing the current 26516d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 26529c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *SwitchSuccessor = NULL; 26536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26548ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Save local scope position because in case of condition variable ScopePos 26558ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // won't be restored when traversing AST. 26568ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 26578ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 26588ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Create local scope for possible condition variable. 26598ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // Store scope position. Add implicit destructor. 26609c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 26618ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski LocalScope::const_iterator SwitchBeginScopePos = ScopePos; 26628ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeForVarDecl(VD); 26638ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); 26648ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski } 26658ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2666d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek if (Block) { 2667d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 26684e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2669d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchSuccessor = Block; 26706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } else SwitchSuccessor = Succ; 2671d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 2672d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Save the current "switch" context. 2673d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock), 2674eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek save_default(DefaultCaseBlock); 2675f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 2676eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 26776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Set the "default" case to be the block after the switch statement. If the 26786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // switch statement contains a "default:", this value will be overwritten with 26796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // the block for that code. 2680eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = SwitchSuccessor; 26816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2682d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Create a new block that will contain the switch statement. 2683d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek SwitchTerminatedBlock = createBlock(false); 26846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2685d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Now process the switch body. The code after the switch is the implicit 2686d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // successor. 2687d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Succ = SwitchSuccessor; 2688f1308c738dc1e7a36101d9e96071d0d241bc2ccbMarcin Swiderski BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos); 26896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 26906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // When visiting the body, the case statements should automatically get linked 26916d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // up to the switch. We also don't keep a pointer to the body, since all 26926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // control-flow from the switch goes to case/default statements. 26936db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getBody() && "switch must contain a non-NULL body"); 269449af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek Block = NULL; 26958ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2696e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // For pruning unreachable case statements, save the current state 2697e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // for tracking the condition value. 2698e71f3d587844110d836c82250830b27b1651afdbTed Kremenek SaveAndRestore<bool> save_switchExclusivelyCovered(switchExclusivelyCovered, 2699e71f3d587844110d836c82250830b27b1651afdbTed Kremenek false); 27000498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2701e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Determine if the switch condition can be explicitly evaluated. 2702e71f3d587844110d836c82250830b27b1651afdbTed Kremenek assert(Terminator->getCond() && "switch condition must be non-NULL"); 27030498247f87ea0d716e0c2931fea812280649e33dTed Kremenek Expr::EvalResult result; 2704e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek bool b = tryEvaluate(Terminator->getCond(), result); 2705e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek SaveAndRestore<Expr::EvalResult*> save_switchCond(switchCond, 2706e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek b ? &result : 0); 27070498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 27088ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // If body is not a compound statement create implicit scope 27098ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski // and add destructors. 27108ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski if (!isa<CompoundStmt>(Terminator->getBody())) 27118ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski addLocalScopeAndDtors(Terminator->getBody()); 27128ae6058cecba902c0069c24bdc9c26d475559291Marcin Swiderski 2713d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu addStmt(Terminator->getBody()); 27144e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek if (Block) { 2715d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 27164e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 27174e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek } 271849af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek 27196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // If we have no "default:" case, the default transition is to the code 2720432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // following the switch body. Moreover, take into account if all the 2721432c478fe0fec3946610d5dc7905daf5fbadf47bTed Kremenek // cases of a switch are covered (e.g., switching on an enum value). 27222a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer // 27232a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer // Note: We add a successor to a switch that is considered covered yet has no 27242a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer // case statements if the enumeration has no enumerators. 27252a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer bool SwitchAlwaysHasSuccessor = false; 27262a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer SwitchAlwaysHasSuccessor |= switchExclusivelyCovered; 27272a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer SwitchAlwaysHasSuccessor |= Terminator->isAllEnumCasesCovered() && 27282a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer Terminator->getSwitchCaseList(); 2729e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 27302a1551fa14728891bf8e325d3eb686ed404cd8b2David Majnemer SwitchAlwaysHasSuccessor ? 0 : DefaultCaseBlock); 27316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 273249af7cb8a3aca79783e7a0708b97a8f856f0da22Ted Kremenek // Add the terminator and condition in the switch block. 2733411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek SwitchTerminatedBlock->setTerminator(Terminator); 2734d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = SwitchTerminatedBlock; 27358f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek CFGBlock *LastBlock = addStmt(Terminator->getCond()); 2736ad5a894df1841698c824381b414630799adc26caTed Kremenek 27376b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // Finally, if the SwitchStmt contains a condition variable, add both the 27386b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek // SwitchStmt and the condition variable initialization to the CFG. 27396b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (VarDecl *VD = Terminator->getConditionVariable()) { 27406b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek if (Expr *Init = VD->getInit()) { 27416b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek autoCreateBlock(); 2742d40066b0fb883839a9100e5455e33190b9b8abacTed Kremenek appendStmt(Block, Terminator->getConditionVariableDeclStmt()); 27438f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek LastBlock = addStmt(Init); 27446b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 27456b501ebaf172b28d6d7e1737db27f915175ad3c8Ted Kremenek } 2746ad5a894df1841698c824381b414630799adc26caTed Kremenek 27478f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek return LastBlock; 2748d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 2749e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2750e71f3d587844110d836c82250830b27b1651afdbTed Kremenekstatic bool shouldAddCase(bool &switchExclusivelyCovered, 2751e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const Expr::EvalResult *switchCond, 2752e71f3d587844110d836c82250830b27b1651afdbTed Kremenek const CaseStmt *CS, 2753e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ASTContext &Ctx) { 2754e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (!switchCond) 2755e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek return true; 2756e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek 2757e71f3d587844110d836c82250830b27b1651afdbTed Kremenek bool addCase = false; 27580498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 2759e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (!switchExclusivelyCovered) { 2760e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek if (switchCond->Val.isInt()) { 2761e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the LHS of the case value. 276285df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &lhsInt = CS->getLHS()->EvaluateKnownConstInt(Ctx); 2763e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek const llvm::APSInt &condInt = switchCond->Val.getInt(); 2764e71f3d587844110d836c82250830b27b1651afdbTed Kremenek 2765e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (condInt == lhsInt) { 2766e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2767e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2768e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2769e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else if (condInt < lhsInt) { 2770e71f3d587844110d836c82250830b27b1651afdbTed Kremenek if (const Expr *RHS = CS->getRHS()) { 2771e71f3d587844110d836c82250830b27b1651afdbTed Kremenek // Evaluate the RHS of the case value. 277285df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith const llvm::APSInt &V2 = RHS->EvaluateKnownConstInt(Ctx); 277385df96c1f04867e26ba069aa0cc6a4cd6a01292eRichard Smith if (V2 <= condInt) { 2774e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2775e71f3d587844110d836c82250830b27b1651afdbTed Kremenek switchExclusivelyCovered = true; 2776e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2777e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2778e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2779e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2780e71f3d587844110d836c82250830b27b1651afdbTed Kremenek else 2781e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addCase = true; 2782e71f3d587844110d836c82250830b27b1651afdbTed Kremenek } 2783e71f3d587844110d836c82250830b27b1651afdbTed Kremenek return addCase; 2784e71f3d587844110d836c82250830b27b1651afdbTed Kremenek} 2785d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 27869c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) { 27876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // CaseStmts are essentially labels, so they are the first statement in a 27886d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // block. 27890fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CFGBlock *TopBlock = 0, *LastBlock = 0; 27900498247f87ea0d716e0c2931fea812280649e33dTed Kremenek 27910fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (Stmt *Sub = CS->getSubStmt()) { 27920fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // For deeply nested chains of CaseStmts, instead of doing a recursion 27930fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // (which can blow out the stack), manually unroll and create blocks 27940fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // along the way. 27950fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek while (isa<CaseStmt>(Sub)) { 27960a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek CFGBlock *currentBlock = createBlock(false); 27970a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek currentBlock->setLabel(CS); 27980fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 27990fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) 28000a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, currentBlock); 28010fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek else 28020a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TopBlock = currentBlock; 28030fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2804e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2805e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2806e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2807e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? currentBlock : 0); 28080fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek 2809e71f3d587844110d836c82250830b27b1651afdbTed Kremenek LastBlock = currentBlock; 28100fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek CS = cast<CaseStmt>(Sub); 28110fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Sub = CS->getSubStmt(); 28120fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 281329ccaa186ac27bcb414c5acb069f6438b27dd5e7Ted Kremenek 28140fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek addStmt(Sub); 28150fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 28161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28179c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CaseBlock = Block; 28184f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!CaseBlock) 28194f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock = createBlock(); 28206d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28216d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Cases statements partition blocks, so this is the top of the basic block we 28226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // were processing (the "case XXX:" is the label). 28234f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek CaseBlock->setLabel(CS); 28244f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 2825d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 28264e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 28276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Add this block to the list of successors for the block with the switch 28296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // statement. 28304f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek assert(SwitchTerminatedBlock); 2831e71f3d587844110d836c82250830b27b1651afdbTed Kremenek addSuccessor(SwitchTerminatedBlock, 2832e9cd9c0016f103fd45d41d136d5d1084aa42eb75Ted Kremenek shouldAddCase(switchExclusivelyCovered, switchCond, 2833e71f3d587844110d836c82250830b27b1651afdbTed Kremenek CS, *Context) 2834e71f3d587844110d836c82250830b27b1651afdbTed Kremenek ? CaseBlock : 0); 28356d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2836d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2837d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek Block = NULL; 28386d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28390fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek if (TopBlock) { 28400a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LastBlock, CaseBlock); 28410fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = TopBlock; 284236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan } else { 28430fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek // This block is now the implicit successor of other blocks. 28440fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek Succ = CaseBlock; 28450fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek } 28466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28470fc67e2d619088945ac71e9d2590d5158650885dTed Kremenek return Succ; 2848d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek} 28496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28509c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) { 28514f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (Terminator->getSubStmt()) 28524f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek addStmt(Terminator->getSubStmt()); 28531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2854eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek DefaultCaseBlock = Block; 28554f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 28564f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek if (!DefaultCaseBlock) 28574f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek DefaultCaseBlock = createBlock(); 28586d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Default statements partition blocks, so this is the top of the basic block 28606d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // we were processing (the "default:" is the label). 2861411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek DefaultCaseBlock->setLabel(Terminator); 28621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2863d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 28644e8df2eb7072db8f66572c3db31a2a08b12a752eTed Kremenek return 0; 2865eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek 28666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Unlike case statements, we don't add the default block to the successors 28676d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // for the switch statement immediately. This is done when we finish 28686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // processing the switch statement. This allows for the default case 28696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // (including a fall-through to the code after the switch statement) to always 28706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // be the last successor of a switch-terminated block. 28716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2872eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // We set Block to NULL to allow lazy creation of a new block (if necessary) 2873eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Block = NULL; 28746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 2875eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek // This block is now the implicit successor of other blocks. 2876eef5a9ac59f4f8b868ef0657ccf6bec81b4fe37aTed Kremenek Succ = DefaultCaseBlock; 28776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 28786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return DefaultCaseBlock; 2879295222c1f0926d84de77f076e79903523eeb5dbfTed Kremenek} 2880d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek 28815d1d20227878cd03db8b2dd23efd4cedfe874feeMike StumpCFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { 28825d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // "try"/"catch" is a control-flow statement. Thus we stop processing the 28835d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // current block. 28849c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *TrySuccessor = NULL; 28855d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28865d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (Block) { 2887d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 28885d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 28895d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump TrySuccessor = Block; 28905d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else TrySuccessor = Succ; 28915d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2892a1f93631a84621d77aeb627691da85a8991af188Mike Stump CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock; 28935d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 28945d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Create a new block that will contain the try statement. 2895f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump CFGBlock *NewTryTerminatedBlock = createBlock(false); 28965d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add the terminator in the try block. 2897f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump NewTryTerminatedBlock->setTerminator(Terminator); 28985d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2899a1f93631a84621d77aeb627691da85a8991af188Mike Stump bool HasCatchAll = false; 29005d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) { 29015d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 29025d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 29035d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CXXCatchStmt *CS = Terminator->getHandler(h); 2904a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl() == 0) { 2905a1f93631a84621d77aeb627691da85a8991af188Mike Stump HasCatchAll = true; 2906a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 29075d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 29085d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CFGBlock *CatchBlock = VisitCXXCatchStmt(CS); 29095d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CatchBlock == 0) 29105d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 29115d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // Add this block to the list of successors for the block with the try 29125d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // statement. 29130a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, CatchBlock); 29145d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 2915a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (!HasCatchAll) { 2916a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (PrevTryTerminatedBlock) 29170a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock); 2918a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 29190a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(NewTryTerminatedBlock, &cfg->getExit()); 2920a1f93631a84621d77aeb627691da85a8991af188Mike Stump } 29215d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29225d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // The code after the try is the implicit successor. 29235d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Succ = TrySuccessor; 29245d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2925f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump // Save the current "try" context. 2926f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock, NewTryTerminatedBlock); 2927f0e71aede7ccf3e311feac6a414c431f7a0fc3c8Ted Kremenek cfg->addTryDispatchBlock(TryTerminatedBlock); 2928f00cca5e05bb9ea51a3a21c8014ff9f3508d46e9Mike Stump 29296db0ad32fa0987ff76d4c41393991ef4b6895ea3Ted Kremenek assert(Terminator->getTryBlock() && "try must contain a non-NULL body"); 29305d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 29318f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek return addStmt(Terminator->getTryBlock()); 29325d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 29335d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29349c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { 29355d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // CXXCatchStmt are treated like labels, so they are the first statement in a 29365d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // block. 29375d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29380e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Save local scope position because in case of exception variable ScopePos 29390e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // won't be restored when traversing AST. 29400e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 29410e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 29420e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Create local scope for possible exception variable. 29430e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski // Store scope position. Add implicit destructor. 29449c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (VarDecl *VD = CS->getExceptionDecl()) { 29450e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski LocalScope::const_iterator BeginScopePos = ScopePos; 29460e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addLocalScopeForVarDecl(VD); 29470e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski addAutomaticObjDtors(ScopePos, BeginScopePos, CS); 29480e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski } 29490e97bcbee9d5f7735edecbccfb5031a2f065f286Marcin Swiderski 29505d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (CS->getHandlerBlock()) 29515d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump addStmt(CS->getHandlerBlock()); 29525d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29539c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *CatchBlock = Block; 29545d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump if (!CatchBlock) 29555d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock = createBlock(); 2956337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2957337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // CXXCatchStmt is more than just a label. They have semantic meaning 2958337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // as well, as they implicitly "initialize" the catch variable. Add 2959337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // it to the CFG as a CFGElement so that the control-flow of these 2960337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // semantics gets captured. 2961337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek appendStmt(CatchBlock, CS); 2962337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek 2963337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Also add the CXXCatchStmt as a label, to mirror handling of regular 2964337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // labels. 29655d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump CatchBlock->setLabel(CS); 29665d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 2967337e4dbc6859589b8878146a88bebf754e916702Ted Kremenek // Bail out if the CFG is bad. 2968d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 29695d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return 0; 29705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29715d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump // We set Block to NULL to allow lazy creation of a new block (if necessary) 29725d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump Block = NULL; 29735d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29745d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump return CatchBlock; 29755d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump} 29765d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 29779c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { 2978ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // C++0x for-range statements are specified as [stmt.ranged]: 2979ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // 2980ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // { 2981ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // auto && __range = range-init; 2982ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for ( auto __begin = begin-expr, 2983ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __end = end-expr; 2984ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // __begin != __end; 2985ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // ++__begin ) { 2986ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // for-range-declaration = *__begin; 2987ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // statement 2988ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2989ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // } 2990ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2991ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save local scope position before the addition of the implicit variables. 2992ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<LocalScope::const_iterator> save_scope_pos(ScopePos); 2993ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 2994ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Create local scopes and destructors for range, begin and end variables. 2995ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *Range = S->getRangeStmt()) 2996ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(Range); 2997ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Stmt *BeginEnd = S->getBeginEndStmt()) 2998ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeForStmt(BeginEnd); 2999ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S); 3000ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3001ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LocalScope::const_iterator ContinueScopePos = ScopePos; 3002ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3003ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // "for" is a control-flow statement. Thus we stop processing the current 3004ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // block. 30059c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *LoopSuccessor = NULL; 3006ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Block) { 3007ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3008ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 3009ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Block; 3010ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } else 3011ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith LoopSuccessor = Succ; 3012ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3013ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current value for the break targets. 3014ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // All breaks should go to the code following the loop. 3015ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_break(BreakJumpTarget); 3016ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); 3017ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3018ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The block for the __begin != __end expression. 30199c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *ConditionBlock = createBlock(false); 3020ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ConditionBlock->setTerminator(S); 3021ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3022ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now add the actual condition to the condition block. 3023ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (Expr *C = S->getCond()) { 3024ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = ConditionBlock; 3025ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith CFGBlock *BeginConditionBlock = addStmt(C); 3026ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3027ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 3028ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(BeginConditionBlock == ConditionBlock && 3029ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith "condition block in for-range was unexpectedly complex"); 3030ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith (void)BeginConditionBlock; 3031ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 3032ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3033ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The condition block is the implicit successor for the loop body as well as 3034ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // any code above the loop. 3035ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = ConditionBlock; 3036ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3037ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // See if this is a known constant. 3038ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith TryResult KnownVal(true); 3039ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3040ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (S->getCond()) 3041ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith KnownVal = tryEvaluateBool(S->getCond()); 3042ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3043ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Now create the loop body. 3044ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith { 3045ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(S->getBody()); 3046ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3047ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Save the current values for Block, Succ, and continue targets. 3048ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ); 3049ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget); 3050ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3051ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Generate increment code in its own basic block. This is the target of 3052ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // continue statements. 3053ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 3054ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Succ = addStmt(S->getInc()); 3055ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); 3056ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3057ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // The starting block for the loop increment is the block that should 3058ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // represent the 'loop target' for looping back to the start of the loop. 3059ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith ContinueJumpTarget.block->setLoopTarget(S); 3060ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3061ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Finish up the increment block and prepare to start the loop body. 3062ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith assert(Block); 3063ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3064ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 3065ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = 0; 3066ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3067ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3068ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add implicit scope and dtors for loop variable. 3069ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addLocalScopeAndDtors(S->getLoopVarStmt()); 3070ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3071ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Populate a new block to contain the loop body and loop variable. 30728f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek addStmt(S->getBody()); 3073ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3074ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 30758f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt()); 3076ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith if (badCFG) 3077ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith return 0; 3078ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3079ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // This new body block is a successor to our condition block. 30808f81acfa95a5d2a22fc875c1a10901eaa30b8405Ted Kremenek addSuccessor(ConditionBlock, KnownVal.isFalse() ? 0 : LoopVarStmtBlock); 3081ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith } 3082ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3083ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Link up the condition block with the code that follows the loop (the 3084ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // false branch). 3085ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith addSuccessor(ConditionBlock, KnownVal.isTrue() ? 0 : LoopSuccessor); 3086ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 3087ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith // Add the initialization statements. 3088ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith Block = createBlock(); 3089b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith addStmt(S->getBeginEndStmt()); 3090b403d6d746239095a2c7bac958c924d92434e2b4Richard Smith return addStmt(S->getRangeStmt()); 3091ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith} 3092ad762fcdc16b9e4705b12b09d92b8c026212b906Richard Smith 30934765fa05b5652fcc4356371c2f481d0ea9a1b007John McCallCFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E, 30948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski AddStmtChoice asc) { 30955a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose if (BuildOpts.AddTemporaryDtors) { 30968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If adding implicit destructors visit the full expression for adding 30978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // destructors of temporaries. 30988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski VisitForTemporaryDtors(E->getSubExpr()); 30998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 31008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Full expression has to be added as CFGStmt so it will be sequenced 31018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before destructors of it's temporaries. 310294a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(true); 31038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Visit(E->getSubExpr(), asc); 31058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 31068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3107a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, 3108a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 31093179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3110a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3111247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3112a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 3113a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 311494a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 3115a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3116a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 3117a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3118a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 311981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, 312081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 312181bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 312297a72c35a62304c3781aa280e28cb97a59afd585Zhongxing Xu appendStmt(Block, C); 312394a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan 312481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 312581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 312681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 312736d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose 312836d558d85653315edb389677e995ec9ccdbfbf3dJordan RoseCFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE, 312936d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose AddStmtChoice asc) { 313036d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose autoCreateBlock(); 313136d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose appendStmt(Block, DE); 313236d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose QualType DTy = DE->getDestroyedType(); 313336d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose DTy = DTy.getNonReferenceType(); 313436d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl(); 313536d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose if (RD) { 313636d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose if (!RD->hasTrivialDestructor()) 313736d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose appendDeleteDtor(Block, RD, DE); 313836d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose } 313936d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose 314036d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose return VisitChildren(DE); 314136d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose} 314236d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose 3143a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, 3144a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 31453179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3146a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3147247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3148a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu // We do not want to propagate the AlwaysAdd property. 314994a3dcf146451eb6b0192873e267c4cb0f6147e8Zhanyong Wan asc = asc.withAlwaysAdd(false); 3150a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3151a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu return Visit(E->getSubExpr(), asc); 3152a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3153a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 315481bc7d07b701042371a5723b6f394cd2482ed7beZhongxing XuCFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, 315581bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu AddStmtChoice asc) { 315681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu autoCreateBlock(); 3157247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, C); 315881bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu return VisitChildren(C); 315981bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 316081bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu 3161a725ed468585b881c43654eeb56b28554a84808aZhongxing XuCFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, 3162a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu AddStmtChoice asc) { 31633179a45a0e91c1dcf3492222170cf4499531bb92Ted Kremenek if (asc.alwaysAdd(*this, E)) { 3164a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu autoCreateBlock(); 3165247e9665d897a7bbbf60c1c0d3b6609c4504a961Ted Kremenek appendStmt(Block, E); 3166a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu } 3167892697dd2287caf7c29aaaa82909b0e90b8b63feTed Kremenek return Visit(E->getSubExpr(), AddStmtChoice()); 3168a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu} 3169a725ed468585b881c43654eeb56b28554a84808aZhongxing Xu 31709c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) { 31716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump // Lazily create the indirect-goto dispatch block if there isn't one already. 31729c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlock *IBlock = cfg->getIndirectGotoBlock(); 31736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 317419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek if (!IBlock) { 317519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek IBlock = createBlock(false); 317619bb356317952445b03ee341c02f6147083c9eeaTed Kremenek cfg->setIndirectGotoBlock(IBlock); 317719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek } 31786d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 317919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // IndirectGoto is a control-flow statement. Thus we stop processing the 318019bb356317952445b03ee341c02f6147083c9eeaTed Kremenek // current block and create a new one. 3181d438b3dbdcde4df4f61a99054104643e6aadf78bZhongxing Xu if (badCFG) 31824f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek return 0; 31834f88063677a2d990a44bb0d5f8437d2498b91d7fTed Kremenek 318419bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block = createBlock(false); 318519bb356317952445b03ee341c02f6147083c9eeaTed Kremenek Block->setTerminator(I); 31860a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, IBlock); 318719bb356317952445b03ee341c02f6147083c9eeaTed Kremenek return addStmt(I->getTarget()); 318819bb356317952445b03ee341c02f6147083c9eeaTed Kremenek} 318919bb356317952445b03ee341c02f6147083c9eeaTed Kremenek 31908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool BindToTemporary) { 31915a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose assert(BuildOpts.AddImplicitDtors && BuildOpts.AddTemporaryDtors); 31925a1ffe98b04120846a15f7105905b5f363b08635Jordan Rose 31938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskitryAgain: 31948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!E) { 31958599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski badCFG = true; 31968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 31978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 31988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski switch (E->getStmtClass()) { 31998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski default: 32008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitChildrenForTemporaryDtors(E); 32018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::BinaryOperatorClass: 32038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitBinaryOperatorForTemporaryDtors(cast<BinaryOperator>(E)); 32048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::CXXBindTemporaryExprClass: 32068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitCXXBindTemporaryExprForTemporaryDtors( 32078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski cast<CXXBindTemporaryExpr>(E), BindToTemporary); 32088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 320956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 32108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ConditionalOperatorClass: 32118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return VisitConditionalOperatorForTemporaryDtors( 321256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall cast<AbstractConditionalOperator>(E), BindToTemporary); 32138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ImplicitCastExprClass: 32158599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For implicit cast we want BindToTemporary to be passed further. 32168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<CastExpr>(E)->getSubExpr(); 32178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 32188599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32198599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski case Stmt::ParenExprClass: 32208599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski E = cast<ParenExpr>(E)->getSubExpr(); 32218599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski goto tryAgain; 322203e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor 322303e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor case Stmt::MaterializeTemporaryExprClass: 322403e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor E = cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(); 322503e80030515c800d1ab44125b9052dfffd1bd04cDouglas Gregor goto tryAgain; 32268599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32278599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 32288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { 32308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // When visiting children for destructors we want to visit them in reverse 32315846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // order that they will appear in the CFG. Because the CFG is built 32325846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // bottom-up, this means we visit them in their natural order, which 32335846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek // reverses them in the CFG. 32348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = Block; 32355846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek for (Stmt::child_range I = E->children(); I; ++I) { 32365846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (Stmt *Child = *I) 32375846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek if (CFGBlock *R = VisitForTemporaryDtors(Child)) 32385846720f08a6b225484bfe663599c2b057a99bc8Ted Kremenek B = R; 32398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 32418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 32428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32438599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(BinaryOperator *E) { 32448599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->isLogicalOp()) { 32458599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Destructors for temporaries in LHS expression should be called after 32468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // those for RHS expression. Even if this will unnecessarily create a block, 32478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // this block will be used at least by the full expression. 32488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 32498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getLHS()); 32508599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32518599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 32528599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32538599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 32548599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 32558599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 32568599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32578599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (RHSBlock) { 32588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 32598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 32608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32618599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If RHS expression did produce destructors we need to connect created 32628599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // blocks to CFG in same manner as for binary operator itself. 32638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = createBlock(false); 32648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski LHSBlock->setTerminator(CFGTerminator(E, true)); 32658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For binary operator LHS block is before RHS in list of predecessors 32678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // of ConfluenceBlock. 32688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), 32698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski ConfluenceBlock->pred_end()); 32708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 32720a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek TryResult KnownVal = tryEvaluateBool(E->getLHS()); 32738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (KnownVal.isKnown() && (E->getOpcode() == BO_LOr)) 32748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski KnownVal.negate(); 32758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Link LHSBlock with RHSBlock exactly the same way as for binary operator 32778599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // itself. 32788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (E->getOpcode() == BO_LOr) { 32790a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 32800a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 32818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 32828599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski assert (E->getOpcode() == BO_LAnd); 32830a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock); 32840a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock); 32858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = LHSBlock; 32888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock; 32898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32908599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 32918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 32928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return ConfluenceBlock; 32938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 32948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 329536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan if (E->isAssignmentOp()) { 32968599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For assignment operator (=) LHS expression is visited 32978599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // before RHS expression. For destructors visit them in reverse order. 32988599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 32998599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 33008599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return LHSBlock ? LHSBlock : RHSBlock; 33018599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 33028599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33038599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // For any other binary operator RHS expression is visited before 33048599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // LHS expression (order of children). For destructors visit them in reverse 33058599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // order. 33068599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *LHSBlock = VisitForTemporaryDtors(E->getLHS()); 33078599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getRHS()); 33088599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return RHSBlock ? RHSBlock : LHSBlock; 33098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 33108599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33118599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors( 33128599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CXXBindTemporaryExpr *E, bool BindToTemporary) { 33138599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for temporaries in subexpression. 33148599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *B = VisitForTemporaryDtors(E->getSubExpr()); 3315249c9458e2cc5b671634baefe8517d7598883a20Zhongxing Xu if (!BindToTemporary) { 33168599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If lifetime of temporary is not prolonged (by assigning to constant 33178599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // reference) add destructor for it. 3318c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 3319c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // If the destructor is marked as a no-return destructor, we need to create 3320c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // a new block for the destructor which does not have as a successor 3321c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth // anything built thus far. Control won't flow out of this block. 3322c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor(); 3323cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (Dtor->isNoReturn()) 3324dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth Block = createNoReturnBlock(); 3325dba3fb5413437dc613734fa4ffac892b11a37d25Chandler Carruth else 3326c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth autoCreateBlock(); 3327c8cfc74bdcc999828bc232294d937fb191940d5bChandler Carruth 33288599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski appendTemporaryDtor(Block, E); 33298599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski B = Block; 33308599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 33318599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return B; 33328599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 33338599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33348599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin SwiderskiCFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( 333556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall AbstractConditionalOperator *E, bool BindToTemporary) { 33368599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // First add destructors for condition expression. Even if this will 33378599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // unnecessarily create a block, this block will be used at least by the full 33388599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // expression. 33398599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski autoCreateBlock(); 33408599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski CFGBlock *ConfluenceBlock = VisitForTemporaryDtors(E->getCond()); 33418599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 33428599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 334356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (BinaryConditionalOperator *BCO 334456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall = dyn_cast<BinaryConditionalOperator>(E)) { 334556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall ConfluenceBlock = VisitForTemporaryDtors(BCO->getCommon()); 33468599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 33478599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 33488599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 33498599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 335056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall // Try to add block with destructors for LHS expression. 335156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *LHSBlock = NULL; 335256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Succ = ConfluenceBlock; 335356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall Block = NULL; 335456ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall LHSBlock = VisitForTemporaryDtors(E->getTrueExpr(), BindToTemporary); 335556ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall if (badCFG) 335656ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall return NULL; 335756ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 33588599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // Try to add block with destructors for RHS expression; 33598599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Succ = ConfluenceBlock; 33608599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = NULL; 336156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CFGBlock *RHSBlock = VisitForTemporaryDtors(E->getFalseExpr(), 336256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall BindToTemporary); 33638599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (badCFG) 33648599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return NULL; 33658599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33668599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock && !LHSBlock) { 33678599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // If neither LHS nor RHS expression had temporaries to destroy don't create 33688599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // more blocks. 33698599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = ConfluenceBlock; 33708599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 33718599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 33728599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33738599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block = createBlock(false); 33748599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski Block->setTerminator(CFGTerminator(E, true)); 33758599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33768599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski // See if this is a known constant. 33770a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek const TryResult &KnownVal = tryEvaluateBool(E->getCond()); 33788599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33798599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (LHSBlock) { 33800a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); 33818599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else if (KnownVal.isFalse()) { 33820a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, NULL); 33838599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } else { 33840a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, ConfluenceBlock); 33858599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski std::reverse(ConfluenceBlock->pred_begin(), ConfluenceBlock->pred_end()); 33868599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski } 33878599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33888599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski if (!RHSBlock) 33898599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski RHSBlock = ConfluenceBlock; 33900a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); 33918599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 33928599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski return Block; 33938599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski} 33948599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3395befef2f69759d7338e2b7c5ce6c8b6f47fe6e667Ted Kremenek} // end anonymous namespace 3396026473c2175424a039f51ca8949937268721b965Ted Kremenek 33976d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has 33986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// no successors or predecessors. If this is the first block created in the 33996d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump/// CFG, it is automatically set to be the Entry and Exit of the CFG. 34009c378f705405d37f49795d5e915989de774fe11fTed KremenekCFGBlock *CFG::createBlock() { 3401026473c2175424a039f51ca8949937268721b965Ted Kremenek bool first_block = begin() == end(); 3402026473c2175424a039f51ca8949937268721b965Ted Kremenek 3403026473c2175424a039f51ca8949937268721b965Ted Kremenek // Create the block. 3404ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek CFGBlock *Mem = getAllocator().Allocate<CFGBlock>(); 340502f34c5003b2c5067675f89ffce0a84c28faf722Anna Zaks new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this); 3406ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Blocks.push_back(Mem, BlkBVC); 3407026473c2175424a039f51ca8949937268721b965Ted Kremenek 3408026473c2175424a039f51ca8949937268721b965Ted Kremenek // If this is the first block, set it as the Entry and Exit. 3409ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (first_block) 3410ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek Entry = Exit = &back(); 3411026473c2175424a039f51ca8949937268721b965Ted Kremenek 3412026473c2175424a039f51ca8949937268721b965Ted Kremenek // Return the block. 3413ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek return &back(); 3414026473c2175424a039f51ca8949937268721b965Ted Kremenek} 3415026473c2175424a039f51ca8949937268721b965Ted Kremenek 3416026473c2175424a039f51ca8949937268721b965Ted Kremenek/// buildCFG - Constructs a CFG from an AST. Ownership of the returned 3417026473c2175424a039f51ca8949937268721b965Ted Kremenek/// CFG is returned to the caller. 34189c378f705405d37f49795d5e915989de774fe11fTed KremenekCFG* CFG::buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, 3419b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek const BuildOptions &BO) { 3420b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek CFGBuilder Builder(C, BO); 3421b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04Ted Kremenek return Builder.buildCFG(D, Statement); 3422fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek} 3423fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 3424c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekconst CXXDestructorDecl * 3425c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed KremenekCFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { 3426c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek switch (getKind()) { 3427c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Statement: 3428c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::Initializer: 3429c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek llvm_unreachable("getDestructorDecl should only be used with " 3430c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek "ImplicitDtors"); 3431c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::AutomaticObjectDtor: { 3432fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie const VarDecl *var = castAs<CFGAutomaticObjDtor>().getVarDecl(); 3433c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek QualType ty = var->getType(); 3434697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek ty = ty.getNonReferenceType(); 34354cf225382a8b061dce41733c962d62b6db9721f8Ted Kremenek while (const ArrayType *arrayType = astContext.getAsArrayType(ty)) { 3436c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek ty = arrayType->getElementType(); 3437c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek } 3438c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const RecordType *recordType = ty->getAs<RecordType>(); 3439c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXRecordDecl *classDecl = 3440697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek cast<CXXRecordDecl>(recordType->getDecl()); 3441c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return classDecl->getDestructor(); 3442c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 344336d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose case CFGElement::DeleteDtor: { 344436d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose const CXXDeleteExpr *DE = castAs<CFGDeleteDtor>().getDeleteExpr(); 344536d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose QualType DTy = DE->getDestroyedType(); 344636d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose DTy = DTy.getNonReferenceType(); 344736d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose const CXXRecordDecl *classDecl = 344836d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose astContext.getBaseElementType(DTy)->getAsCXXRecordDecl(); 344936d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose return classDecl->getDestructor(); 345036d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose } 3451c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::TemporaryDtor: { 3452c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXBindTemporaryExpr *bindExpr = 3453fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie castAs<CFGTemporaryDtor>().getBindTemporaryExpr(); 3454c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek const CXXTemporary *temp = bindExpr->getTemporary(); 3455c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return temp->getDestructor(); 3456c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3457c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::BaseDtor: 3458c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek case CFGElement::MemberDtor: 3459c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3460c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // Not yet supported. 3461c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return 0; 3462c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 3463697d42db6cba7a5994d955ce31be2c097902cf0cTed Kremenek llvm_unreachable("getKind() returned bogus value"); 3464c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek} 3465c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 3466c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenekbool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { 3467cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith if (const CXXDestructorDecl *DD = getDestructorDecl(astContext)) 3468cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith return DD->isNoReturn(); 3469c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek return false; 34703c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek} 34713c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 347263f5887f316fb52d243fcbb3631c039de6c4b993Ted Kremenek//===----------------------------------------------------------------------===// 3473ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek// Filtered walking of the CFG. 3474ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 3475ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3476ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenekbool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, 3477be39a566a914df8561d7a1e9654708297f0908c1Ted Kremenek const CFGBlock *From, const CFGBlock *To) { 3478ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 34796e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (To && F.IgnoreDefaultsWithCoveredEnums) { 3480ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // If the 'To' has no label or is labeled but the label isn't a 3481ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek // CaseStmt then filter this edge. 3482ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (const SwitchStmt *S = 34836e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek dyn_cast_or_null<SwitchStmt>(From->getTerminator().getStmt())) { 3484ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek if (S->isAllEnumCasesCovered()) { 34856e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek const Stmt *L = To->getLabel(); 34866e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek if (!L || !isa<CaseStmt>(L)) 34876e40035988965340555c942d6e7afb6c7527beb1Ted Kremenek return true; 3488ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3489ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3490ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek } 3491ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3492ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek return false; 3493ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek} 3494ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek 3495ee7f84d509c6382491673883598eb9ed2d3a6a8bTed Kremenek//===----------------------------------------------------------------------===// 34967dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG pretty printing 34977dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 34987dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 349942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremeneknamespace { 35002bac4ea765a4a6e1f6149964663f62d4bca6743bTed Kremenek 3501ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass StmtPrinterHelper : public PrinterHelper { 35023c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Stmt*,std::pair<unsigned,unsigned> > StmtMapTy; 35033c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek typedef llvm::DenseMap<const Decl*,std::pair<unsigned,unsigned> > DeclMapTy; 350442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtMapTy StmtMap; 35051cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy DeclMap; 35060a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek signed currentBlock; 350766c486f275531df6362b3511fc3af6563561801bTed Kremenek unsigned currStmt; 3508e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &LangOpts; 350942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenekpublic: 35101c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek 3511e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) 351266c486f275531df6362b3511fc3af6563561801bTed Kremenek : currentBlock(0), currStmt(0), LangOpts(LO) 35133c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek { 351442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 351542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek unsigned j = 1; 3516ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 35171cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski BI != BEnd; ++BI, ++j ) { 3518b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> SE = BI->getAs<CFGStmt>()) { 3519b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *stmt= SE->getStmt(); 35201cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski std::pair<unsigned, unsigned> P((*I)->getBlockID(), j); 35213c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek StmtMap[stmt] = P; 35223c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 35233c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek switch (stmt->getStmtClass()) { 35243c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::DeclStmtClass: 35253c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[cast<DeclStmt>(stmt)->getSingleDecl()] = P; 35263c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35273c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::IfStmtClass: { 35283c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<IfStmt>(stmt)->getConditionVariable(); 35293c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35303c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35313c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35323c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35333c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::ForStmtClass: { 35343c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = cast<ForStmt>(stmt)->getConditionVariable(); 35353c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35363c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35373c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35383c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35393c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::WhileStmtClass: { 35403c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 35413c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<WhileStmt>(stmt)->getConditionVariable(); 35423c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35433c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35443c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35453c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35463c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::SwitchStmtClass: { 35473c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 35483c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<SwitchStmt>(stmt)->getConditionVariable(); 35493c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35503c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35513c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35523c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35533c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek case Stmt::CXXCatchStmtClass: { 35543c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek const VarDecl *var = 35553c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek cast<CXXCatchStmt>(stmt)->getExceptionDecl(); 35563c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (var) 35573c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek DeclMap[var] = P; 35583c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35593c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek } 35603c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek default: 35613c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek break; 35621cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 35631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 356442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 3565b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 3566fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 35673c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek 35686d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 356942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek virtual ~StmtPrinterHelper() {} 35706d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3571e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const LangOptions &getLangOpts() const { return LangOpts; } 35720a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek void setBlockID(signed i) { currentBlock = i; } 357366c486f275531df6362b3511fc3af6563561801bTed Kremenek void setStmtID(unsigned i) { currStmt = i; } 35746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35759c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual bool handledStmt(Stmt *S, raw_ostream &OS) { 35761cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski StmtMapTy::iterator I = StmtMap.find(S); 3577fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek 357842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (I == StmtMap.end()) 357942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 35806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35810a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 358266c486f275531df6362b3511fc3af6563561801bTed Kremenek && I->second.second == currStmt) { 358342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek return false; 35843fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek } 35856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 35863fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "[B" << I->second.first << "." << I->second.second << "]"; 35871c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek return true; 358842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 35891cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35909c378f705405d37f49795d5e915989de774fe11fTed Kremenek bool handleDecl(const Decl *D, raw_ostream &OS) { 35911cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski DeclMapTy::iterator I = DeclMap.find(D); 35921cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35931cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I == DeclMap.end()) 35941cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 35951cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 35960a3ed3143b00f237decb1288c1ff574ae09eba4eTed Kremenek if (currentBlock >= 0 && I->second.first == (unsigned) currentBlock 359766c486f275531df6362b3511fc3af6563561801bTed Kremenek && I->second.second == currStmt) { 35981cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return false; 35991cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 36001cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 36011cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "[B" << I->second.first << "." << I->second.second << "]"; 36021cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return true; 36031cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 360442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek}; 3605e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3606e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 3607e8ee26b49d68ae3ffdf9a990ff7511ef55afa04cTed Kremenek 3608e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnernamespace { 3609ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass CFGBlockTerminatorPrint 36106fa9b88e2c3d47d606a273df2f8d03509bcff0b9Ted Kremenek : public StmtVisitor<CFGBlockTerminatorPrint,void> { 36116d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36129c378f705405d37f49795d5e915989de774fe11fTed Kremenek raw_ostream &OS; 361342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek StmtPrinterHelper* Helper; 3614d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PrintingPolicy Policy; 3615d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenekpublic: 36169c378f705405d37f49795d5e915989de774fe11fTed Kremenek CFGBlockTerminatorPrint(raw_ostream &os, StmtPrinterHelper* helper, 3617e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner const PrintingPolicy &Policy) 3618d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor : OS(os), Helper(helper), Policy(Policy) {} 36196d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36209c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIfStmt(IfStmt *I) { 3621d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "if "; 3622d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getCond()->printPretty(OS,Helper,Policy); 3623d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 36246d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3625d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek // Default case. 36269c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitStmt(Stmt *Terminator) { 36276d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump Terminator->printPretty(OS, Helper, Policy); 36286d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 36296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3630fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek void VisitDeclStmt(DeclStmt *DS) { 3631fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); 3632fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek OS << "static init " << VD->getName(); 3633fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek } 3634fbd4b5dc7febd1d8b4fa64ab00a29d72b44bec7bTed Kremenek 36359c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitForStmt(ForStmt *F) { 3636d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "for (" ; 36373fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInit()) 36383fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3639535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 36409c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = F->getCond()) 36413fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3642535bb20b6e252809bc17cc59b5d71b5e5e549e70Ted Kremenek OS << "; "; 36433fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek if (F->getInc()) 36443fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek OS << "..."; 3645a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << ")"; 3646d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 36476d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36489c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitWhileStmt(WhileStmt *W) { 3649d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "while " ; 36509c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = W->getCond()) 36513fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 3652d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek } 36536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36549c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitDoStmt(DoStmt *D) { 3655d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek OS << "do ... while "; 36569c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *C = D->getCond()) 36573fa1e4b27300a4ea4cf273182d4b6427ef87f3f8Ted Kremenek C->printPretty(OS, Helper, Policy); 36589da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 36596d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36609c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitSwitchStmt(SwitchStmt *Terminator) { 36619da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek OS << "switch "; 3662d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor Terminator->getCond()->printPretty(OS, Helper, Policy); 36639da2fb773c473b989c78c513c5ce61641e9bbb4dTed Kremenek } 36646d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36659c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitCXXTryStmt(CXXTryStmt *CS) { 36665d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "try ..."; 36675d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } 36685d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 366956ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) { 3670d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 36716d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump OS << " ? ... : ..."; 3672805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36736d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36749c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitChooseExpr(ChooseExpr *C) { 3675aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek OS << "__builtin_choose_expr( "; 3676d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor C->getCond()->printPretty(OS, Helper, Policy); 3677a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " )"; 3678aeddbf689eb3e3afca5117ca83c7b2e18260b0d8Ted Kremenek } 36796d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 36809c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitIndirectGotoStmt(IndirectGotoStmt *I) { 36811c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek OS << "goto *"; 3682d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor I->getTarget()->printPretty(OS, Helper, Policy); 36831c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 36846d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3685805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek void VisitBinaryOperator(BinaryOperator* B) { 3686805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek if (!B->isLogicalOp()) { 3687805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek VisitExpr(B); 3688805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3689805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 36906d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3691d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor B->getLHS()->printPretty(OS, Helper, Policy); 36926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3693805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek switch (B->getOpcode()) { 36942de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LOr: 3695a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " || ..."; 3696805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 36972de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall case BO_LAnd: 3698a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << " && ..."; 3699805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek return; 3700805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek default: 3701b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid logical operator."); 37026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3703805e9a8300af9489ec13cd804c070267b7c4cfecTed Kremenek } 37046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37059c378f705405d37f49795d5e915989de774fe11fTed Kremenek void VisitExpr(Expr *E) { 3706d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor E->printPretty(OS, Helper, Policy); 37076d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 3708d4fdee35477e439759eea5f67ea03ff0c570fabaTed Kremenek}; 3709e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} // end anonymous namespace 3710e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner 37115f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void print_elem(raw_ostream &OS, StmtPrinterHelper* Helper, 3712079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump const CFGElement &E) { 3713b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) { 3714b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const Stmt *S = CS->getStmt(); 37151cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37161cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (Helper) { 37171cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37181cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for statement-expressions. 3719f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) { 3720f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const CompoundStmt *Sub = SE->getSubStmt(); 37211cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37227502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall if (Sub->children()) { 37231cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "({ ... ; "; 37241cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS); 37251cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " })\n"; 37261cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 37271cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 37281cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 37291cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // special printing for comma expressions. 3730f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { 37311cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (B->getOpcode() == BO_Comma) { 37321cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "... , "; 37331cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handledStmt(B->getRHS(),OS); 37341cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 37351cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski return; 37361cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 37371c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 37381c29bba6da40bbe59fb1f81c4cd5ab5471554ffeTed Kremenek } 37391cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 37406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37411cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<CXXOperatorCallExpr>(S)) { 374236f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (OperatorCall)"; 3743893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 3744893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (isa<CXXBindTemporaryExpr>(S)) { 374536f327c309b1fb6b82f1987190f0be74000b14c1Zhanyong Wan OS << " (BindTemporary)"; 37466d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump } 37473b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek else if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(S)) { 37483b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek OS << " (CXXConstructExpr, " << CCE->getType().getAsString() << ")"; 37493b7a48fbc681c6fb59e5304a210c30dbb49dabeaTed Kremenek } 3750893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek else if (const CastExpr *CE = dyn_cast<CastExpr>(S)) { 3751893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek OS << " (" << CE->getStmtClassName() << ", " 3752893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << CE->getCastKindName() 3753893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ", " << CE->getType().getAsString() 3754893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek << ")"; 3755893d414534273e153e12aef39a1ad991c6fa94c0Ted Kremenek } 37566d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37571cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski // Expressions need a newline. 37581cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (isa<Expr>(S)) 37591cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << '\n'; 37604e0cfa8eacf76f203d6ee6ce164162ccd4275ccdTed Kremenek 3761b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGInitializer> IE = E.getAs<CFGInitializer>()) { 3762b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const CXXCtorInitializer *I = IE->getInitializer(); 37631cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 37641cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << I->getBaseClass()->getAsCXXRecordDecl()->getName(); 376500eb3f9c5b33e3d99aee1f8b75dd9c9678fdd66bFrancois Pichet else OS << I->getAnyMember()->getName(); 37666d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 37671cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << "("; 37689c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Expr *IE = I->getInit()) 37691cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski IE->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); 37701cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ")"; 37711cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37721cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (I->isBaseInitializer()) 37731cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Base initializer)\n"; 37741cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski else OS << " (Member initializer)\n"; 37751cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3776b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGAutomaticObjDtor> DE = 3777b07805485c603be3d8011f72611465324c9e664bDavid Blaikie E.getAs<CFGAutomaticObjDtor>()) { 3778b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const VarDecl *VD = DE->getVarDecl(); 37791cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski Helper->handleDecl(VD, OS); 37801cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 3781b1c52870b8c2feaa7cd112295368bec53af490a0Marcin Swiderski const Type* T = VD->getType().getTypePtr(); 37821cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski if (const ReferenceType* RT = T->getAs<ReferenceType>()) 37831cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski T = RT->getPointeeType().getTypePtr(); 378456df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith T = T->getBaseElementTypeUnsafe(); 37851cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski 37861cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName().str() << "()"; 37871cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski OS << " (Implicit destructor)\n"; 37887c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 378936d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose } else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) { 379036d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose const CXXRecordDecl *RD = DE->getCXXRecordDecl(); 379136d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose if (!RD) 379236d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose return; 379336d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose CXXDeleteExpr *DelExpr = 379436d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose const_cast<CXXDeleteExpr*>(DE->getDeleteExpr()); 379536d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose Helper->handledStmt(cast<Stmt>(DelExpr->getArgument()), OS); 379636d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose OS << "->~" << RD->getName().str() << "()"; 379736d558d85653315edb389677e995ec9ccdbfbf3dJordan Rose OS << " (Implicit destructor)\n"; 3798b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGBaseDtor> BE = E.getAs<CFGBaseDtor>()) { 3799b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const CXXBaseSpecifier *BS = BE->getBaseSpecifier(); 38007c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "~" << BS->getType()->getAsCXXRecordDecl()->getName() << "()"; 38014e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Base object destructor)\n"; 38027c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski 3803b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGMemberDtor> ME = E.getAs<CFGMemberDtor>()) { 3804b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const FieldDecl *FD = ME->getFieldDecl(); 380556df4a9e0461d4dfb2a740cb6b0ce531d6c82538Richard Smith const Type *T = FD->getType()->getBaseElementTypeUnsafe(); 38067c625d8ffc20b92fff9e1690cd2484fcb6498183Marcin Swiderski OS << "this->" << FD->getName(); 38078c5e5d6d8a316af5a9842169f541cac49717887dMarcin Swiderski OS << ".~" << T->getAsCXXRecordDecl()->getName() << "()"; 38084e493e0dbac2aaac04c041f3d7dee9eccfb97689Zhongxing Xu OS << " (Member object destructor)\n"; 38098599e7677e067fd01d3b2ee4c0875747d367fd8eMarcin Swiderski 3810b07805485c603be3d8011f72611465324c9e664bDavid Blaikie } else if (Optional<CFGTemporaryDtor> TE = E.getAs<CFGTemporaryDtor>()) { 3811b07805485c603be3d8011f72611465324c9e664bDavid Blaikie const CXXBindTemporaryExpr *BT = TE->getBindTemporaryExpr(); 381295ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath OS << "~"; 381395ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath BT->getType().print(OS, PrintingPolicy(Helper->getLangOpts())); 381495ab9e306f4deefeabd89ea61987f4a8d67e0890Pavel Labath OS << "() (Temporary object destructor)\n"; 38151cff132e48e0ccc253c34e5a2fb12718bd4e7d2eMarcin Swiderski } 381681bc7d07b701042371a5723b6f394cd2482ed7beZhongxing Xu} 38176d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38189c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void print_block(raw_ostream &OS, const CFG* cfg, 38199c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CFGBlock &B, 3820682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek StmtPrinterHelper* Helper, bool print_edges, 3821682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) { 38226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3823682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (Helper) 3824682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek Helper->setBlockID(B.getBlockID()); 38256d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38267dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Print the header. 3827682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3828682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::YELLOW, true); 3829682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3830682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n [B" << B.getBlockID(); 38316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 383242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (&B == &cfg->getEntry()) 3833682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (ENTRY)]\n"; 383442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == &cfg->getExit()) 3835682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (EXIT)]\n"; 383642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else if (&B == cfg->getIndirectGotoBlock()) 3837682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " (INDIRECT GOTO DISPATCH)]\n"; 383842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek else 3839682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "]\n"; 3840682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3841682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3842682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 38436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38449cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the label of this block. 38459c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (Stmt *Label = const_cast<Stmt*>(B.getLabel())) { 384642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 384742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3848682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 38496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38509c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (LabelStmt *L = dyn_cast<LabelStmt>(Label)) 38519cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << L->getName(); 38529c378f705405d37f49795d5e915989de774fe11fTed Kremenek else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) { 38539cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "case "; 3854e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getLHS()->printPretty(OS, Helper, 3855e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 38569cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (C->getRHS()) { 38579cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << " ... "; 3858e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner C->getRHS()->printPretty(OS, Helper, 3859e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(Helper->getLangOpts())); 38609cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 3861079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump } else if (isa<DefaultStmt>(Label)) 38629cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << "default"; 3863079bd72439448b78629a28da6b1f8abe2cdeaf4dMike Stump else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) { 38645d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << "catch ("; 3865a1f93631a84621d77aeb627691da85a8991af188Mike Stump if (CS->getExceptionDecl()) 3866a1f93631a84621d77aeb627691da85a8991af188Mike Stump CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()), 3867a1f93631a84621d77aeb627691da85a8991af188Mike Stump 0); 3868a1f93631a84621d77aeb627691da85a8991af188Mike Stump else 3869a1f93631a84621d77aeb627691da85a8991af188Mike Stump OS << "..."; 38705d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump OS << ")"; 38715d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump 38725d1d20227878cd03db8b2dd23efd4cedfe874feeMike Stump } else 3873b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid label statement in CFGBlock."); 38746d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38759cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek OS << ":\n"; 38769cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 38776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3878fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek // Iterate through the statements in the block and print them. 3879fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek unsigned j = 1; 38806d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 388142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (CFGBlock::const_iterator I = B.begin(), E = B.end() ; 388242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek I != E ; ++I, ++j ) { 38836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38849cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the statement # in the basic block and the statement itself. 388542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (print_edges) 3886682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " "; 38876d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3888a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek OS << llvm::format("%3d", j) << ": "; 38896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 389042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) 389142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek Helper->setStmtID(j); 38926d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3893682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_elem(OS, Helper, *I); 3894fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 38956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 38969cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the terminator of this block. 389742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (B.getTerminator()) { 3898682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3899682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(raw_ostream::GREEN); 39006d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3901682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " T: "; 39026d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 390342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek if (Helper) Helper->setBlockID(-1); 39046d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3905507d106c758e745d3f71f44639092eb97d356525Ted Kremenek PrintingPolicy PP(Helper ? Helper->getLangOpts() : LangOptions()); 3906507d106c758e745d3f71f44639092eb97d356525Ted Kremenek CFGBlockTerminatorPrint TPrinter(OS, Helper, PP); 39074ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(B.getTerminator().getStmt())); 3908a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek OS << '\n'; 3909682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3910682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3911682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3912fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 39136d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 39149cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek if (print_edges) { 39159cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the predecessors of this block. 3916682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.pred_empty()) { 3917682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::BLUE; 3918682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3919682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3920682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Preds " ; 3921682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3922682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3923682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.pred_size() << "):"; 3924682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3925682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3926682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3927682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3928682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3929682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end(); 3930682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 393142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 3932dac62528c1a66db867e21cfa7cfc439d557d6f0cWill Dietz if (i % 10 == 8) 3933682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 39346d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3935682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3936682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3937682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3938682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3939682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 39406d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3941682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 39429cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek } 39436d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 39449cffe7366ea3beb33c2d58f43a8c3a04c1873e11Ted Kremenek // Print the successors of this block. 3945682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (!B.succ_empty()) { 3946682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const raw_ostream::Colors Color = raw_ostream::MAGENTA; 3947682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3948682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3949682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " Succs "; 3950682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3951682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3952682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '(' << B.succ_size() << "):"; 3953682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek unsigned i = 0; 3954682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3955682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3956682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.changeColor(Color); 3957682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3958682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end(); 3959682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek I != E; ++I, ++i) { 3960682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3961dac62528c1a66db867e21cfa7cfc439d557d6f0cWill Dietz if (i % 10 == 8) 3962682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << "\n "; 3963682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3964682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (*I) 3965682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " B" << (*I)->getBlockID(); 3966682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek else 3967682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << " NULL"; 3968682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek } 3969682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek 3970682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek if (ShowColors) 3971682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS.resetColor(); 3972682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 3973fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 3974fddd51853f8ccaa1df2476376e6fd74d2f315c73Ted Kremenek } 39756d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 397642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 397742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 397842a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simple pretty printer of a CFG that outputs to stderr. 3979682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::dump(const LangOptions &LO, bool ShowColors) const { 3980682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), LO, ShowColors); 3981682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek} 398242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 398342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFG that outputs to an ostream. 3984682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const { 3985e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(this, LO); 39866d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 398742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the entry block. 3988682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getEntry(), &Helper, true, ShowColors); 39896d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 399042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Iterate through the CFGBlocks and print them one by one. 399142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) { 399242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Skip the entry block, because we already printed it. 3993ee82d9bdc5025b82de8ce2a4ad4685e0a8b79da9Ted Kremenek if (&(**I) == &getEntry() || &(**I) == &getExit()) 399442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek continue; 39956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 3996682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, **I, &Helper, true, ShowColors); 399742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek } 39986d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 399942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek // Print the exit block. 4000682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, this, getExit(), &Helper, true, ShowColors); 4001682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 4002d0172439194b28bae62a94a0a25d58e6d21e7a14Ted Kremenek OS.flush(); 40036d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump} 400442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 400542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// dump - A simply pretty printer of a CFGBlock that outputs to stderr. 4006682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenekvoid CFGBlock::dump(const CFG* cfg, const LangOptions &LO, 4007682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek bool ShowColors) const { 4008682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print(llvm::errs(), cfg, LO, ShowColors); 4009e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner} 401042a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 401142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. 401242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek/// Generally this will only be called from CFG::print. 40139c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid CFGBlock::print(raw_ostream &OS, const CFG* cfg, 4014682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek const LangOptions &LO, bool ShowColors) const { 4015e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper Helper(cfg, LO); 4016682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(OS, cfg, *this, &Helper, true, ShowColors); 4017682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek OS << '\n'; 4018026473c2175424a039f51ca8949937268721b965Ted Kremenek} 40197dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 4020a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek/// printTerminator - A simple pretty printer of the terminator of a CFGBlock. 40215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid CFGBlock::printTerminator(raw_ostream &OS, 40226d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump const LangOptions &LO) const { 4023e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); 40244ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski TPrinter.Visit(const_cast<Stmt*>(getTerminator().getStmt())); 4025a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek} 4026a292585207adbf6dcf6347db3526a7ec861d8eacTed Kremenek 40279c378f705405d37f49795d5e915989de774fe11fTed KremenekStmt *CFGBlock::getTerminatorCondition() { 40284ba72a0b28135209c435630682febe1f854ccfa6Marcin Swiderski Stmt *Terminator = this->Terminator; 4029411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek if (!Terminator) 4030411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return NULL; 40316d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 40329c378f705405d37f49795d5e915989de774fe11fTed Kremenek Expr *E = NULL; 40336d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4034411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek switch (Terminator->getStmtClass()) { 4035411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek default: 4036411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40376d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 403849a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose case Stmt::CXXForRangeStmtClass: 403949a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose E = cast<CXXForRangeStmt>(Terminator)->getCond(); 404049a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose break; 404149a246f4fad959888bb0164c624c3c2b03078e91Jordan Rose 4042411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ForStmtClass: 4043411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ForStmt>(Terminator)->getCond(); 4044411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40456d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4046411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::WhileStmtClass: 4047411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<WhileStmt>(Terminator)->getCond(); 4048411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40496d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4050411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::DoStmtClass: 4051411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<DoStmt>(Terminator)->getCond(); 4052411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40536d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4054411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IfStmtClass: 4055411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IfStmt>(Terminator)->getCond(); 4056411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40576d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4058411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ChooseExprClass: 4059411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ChooseExpr>(Terminator)->getCond(); 4060411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40616d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4062411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::IndirectGotoStmtClass: 4063411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<IndirectGotoStmt>(Terminator)->getTarget(); 4064411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40656d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4066411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::SwitchStmtClass: 4067411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<SwitchStmt>(Terminator)->getCond(); 4068411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40696d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 407056ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall case Stmt::BinaryConditionalOperatorClass: 407156ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall E = cast<BinaryConditionalOperator>(Terminator)->getCond(); 407256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall break; 407356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall 4074411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::ConditionalOperatorClass: 4075411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<ConditionalOperator>(Terminator)->getCond(); 4076411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek break; 40776d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4078411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek case Stmt::BinaryOperatorClass: // '&&' and '||' 4079411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek E = cast<BinaryOperator>(Terminator)->getLHS(); 4080390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek break; 40816d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4082390e48b15ad93f85bfd1e33b9992c198fa0db475Ted Kremenek case Stmt::ObjCForCollectionStmtClass: 40836d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump return Terminator; 4084411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek } 40856d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 4086411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek return E ? E->IgnoreParens() : NULL; 4087411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek} 4088411cdee0b490f79428c9eb977f25199eb7d21cd8Ted Kremenek 40897dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 40907dba8607e59096014b7139ff20ef00870041d518Ted Kremenek// CFG Graphviz Visualization 40917dba8607e59096014b7139ff20ef00870041d518Ted Kremenek//===----------------------------------------------------------------------===// 40927dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 409342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 409442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 40956d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stumpstatic StmtPrinterHelper* GraphHelper; 409642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 409742a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 4098e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattnervoid CFG::viewCFG(const LangOptions &LO) const { 409942a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#ifndef NDEBUG 4100e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner StmtPrinterHelper H(this, LO); 410142a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = &H; 410242a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek llvm::ViewGraph(this,"CFG"); 410342a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek GraphHelper = NULL; 410442a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek#endif 410542a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek} 410642a509f6a4f71bb805cc4abbb26722a34dffdddeTed Kremenek 41077dba8607e59096014b7139ff20ef00870041d518Ted Kremeneknamespace llvm { 41087dba8607e59096014b7139ff20ef00870041d518Ted Kremenektemplate<> 41097dba8607e59096014b7139ff20ef00870041d518Ted Kremenekstruct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { 4110006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 4111006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 4112006b0eb3e11162d8c06372db813ac9f71a7a16e8Tobias Grosser 41139c378f705405d37f49795d5e915989de774fe11fTed Kremenek static std::string getNodeLabel(const CFGBlock *Node, const CFG* Graph) { 41147dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 4115bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#ifndef NDEBUG 4116a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string OutSStr; 4117a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream Out(OutSStr); 4118682060c5d95f6e4f79536013781ab0870cdd3850Ted Kremenek print_block(Out,Graph, *Node, GraphHelper, false, false); 4119a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string& OutStr = Out.str(); 41207dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 41217dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 41227dba8607e59096014b7139ff20ef00870041d518Ted Kremenek 41237dba8607e59096014b7139ff20ef00870041d518Ted Kremenek // Process string output to make it nicer... 41247dba8607e59096014b7139ff20ef00870041d518Ted Kremenek for (unsigned i = 0; i != OutStr.length(); ++i) 41257dba8607e59096014b7139ff20ef00870041d518Ted Kremenek if (OutStr[i] == '\n') { // Left justify 41267dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr[i] = '\\'; 41277dba8607e59096014b7139ff20ef00870041d518Ted Kremenek OutStr.insert(OutStr.begin()+i+1, 'l'); 41287dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 41296d9828c82c9321f042ab416fd2ffaa3034347d45Mike Stump 41307dba8607e59096014b7139ff20ef00870041d518Ted Kremenek return OutStr; 4131bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#else 4132bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser return ""; 4133bd250b44d60622e7c0b60c6def6f6fe7e347addfHartmut Kaiser#endif 41347dba8607e59096014b7139ff20ef00870041d518Ted Kremenek } 41357dba8607e59096014b7139ff20ef00870041d518Ted Kremenek}; 41367dba8607e59096014b7139ff20ef00870041d518Ted Kremenek} // end namespace llvm 4137