1 //===- CFG.h - Classes for representing and building CFGs -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the CFG and CFGBuilder classes for representing and 10 // building Control-Flow Graphs (CFGs) from ASTs. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_ANALYSIS_CFG_H 15 #define LLVM_CLANG_ANALYSIS_CFG_H 16 17 #include "clang/AST/Attr.h" 18 #include "clang/AST/ExprCXX.h" 19 #include "clang/AST/ExprObjC.h" 20 #include "clang/Analysis/ConstructionContext.h" 21 #include "clang/Analysis/Support/BumpVector.h" 22 #include "clang/Basic/LLVM.h" 23 #include "llvm/ADT/DenseMap.h" 24 #include "llvm/ADT/GraphTraits.h" 25 #include "llvm/ADT/PointerIntPair.h" 26 #include "llvm/ADT/iterator_range.h" 27 #include "llvm/Support/Allocator.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <bitset> 30 #include <cassert> 31 #include <cstddef> 32 #include <iterator> 33 #include <memory> 34 #include <optional> 35 #include <vector> 36 37 namespace clang { 38 39 class ASTContext; 40 class BinaryOperator; 41 class CFG; 42 class CXXBaseSpecifier; 43 class CXXBindTemporaryExpr; 44 class CXXCtorInitializer; 45 class CXXDeleteExpr; 46 class CXXDestructorDecl; 47 class CXXNewExpr; 48 class CXXRecordDecl; 49 class Decl; 50 class FieldDecl; 51 class LangOptions; 52 class VarDecl; 53 54 /// Represents a top-level expression in a basic block. 55 class CFGElement { 56 public: 57 enum Kind { 58 // main kind 59 Initializer, 60 ScopeBegin, 61 ScopeEnd, 62 NewAllocator, 63 LifetimeEnds, 64 LoopExit, 65 // stmt kind 66 Statement, 67 Constructor, 68 CXXRecordTypedCall, 69 STMT_BEGIN = Statement, 70 STMT_END = CXXRecordTypedCall, 71 // dtor kind 72 AutomaticObjectDtor, 73 DeleteDtor, 74 BaseDtor, 75 MemberDtor, 76 TemporaryDtor, 77 DTOR_BEGIN = AutomaticObjectDtor, 78 DTOR_END = TemporaryDtor, 79 CleanupFunction, 80 }; 81 82 protected: 83 // The int bits are used to mark the kind. 84 llvm::PointerIntPair<void *, 2> Data1; 85 llvm::PointerIntPair<void *, 2> Data2; 86 87 CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr) 88 : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), 89 Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { 90 assert(getKind() == kind); 91 } 92 93 CFGElement() = default; 94 95 public: 96 /// Convert to the specified CFGElement type, asserting that this 97 /// CFGElement is of the desired type. 98 template<typename T> castAs()99 T castAs() const { 100 assert(T::isKind(*this)); 101 T t; 102 CFGElement& e = t; 103 e = *this; 104 return t; 105 } 106 107 /// Convert to the specified CFGElement type, returning std::nullopt if this 108 /// CFGElement is not of the desired type. getAs()109 template <typename T> std::optional<T> getAs() const { 110 if (!T::isKind(*this)) 111 return std::nullopt; 112 T t; 113 CFGElement& e = t; 114 e = *this; 115 return t; 116 } 117 getKind()118 Kind getKind() const { 119 unsigned x = Data2.getInt(); 120 x <<= 2; 121 x |= Data1.getInt(); 122 return (Kind) x; 123 } 124 125 void dumpToStream(llvm::raw_ostream &OS, 126 bool TerminateWithNewLine = true) const; 127 dump()128 void dump() const { 129 dumpToStream(llvm::errs()); 130 } 131 }; 132 133 class CFGStmt : public CFGElement { 134 public: CFGElement(K,S)135 explicit CFGStmt(const Stmt *S, Kind K = Statement) : CFGElement(K, S) { 136 assert(isKind(*this)); 137 } 138 getStmt()139 const Stmt *getStmt() const { 140 return static_cast<const Stmt *>(Data1.getPointer()); 141 } 142 143 private: 144 friend class CFGElement; 145 isKind(const CFGElement & E)146 static bool isKind(const CFGElement &E) { 147 return E.getKind() >= STMT_BEGIN && E.getKind() <= STMT_END; 148 } 149 150 protected: 151 CFGStmt() = default; 152 }; 153 154 /// Represents C++ constructor call. Maintains information necessary to figure 155 /// out what memory is being initialized by the constructor expression. For now 156 /// this is only used by the analyzer's CFG. 157 class CFGConstructor : public CFGStmt { 158 public: CFGConstructor(const CXXConstructExpr * CE,const ConstructionContext * C)159 explicit CFGConstructor(const CXXConstructExpr *CE, 160 const ConstructionContext *C) 161 : CFGStmt(CE, Constructor) { 162 assert(C); 163 Data2.setPointer(const_cast<ConstructionContext *>(C)); 164 } 165 getConstructionContext()166 const ConstructionContext *getConstructionContext() const { 167 return static_cast<ConstructionContext *>(Data2.getPointer()); 168 } 169 170 private: 171 friend class CFGElement; 172 173 CFGConstructor() = default; 174 isKind(const CFGElement & E)175 static bool isKind(const CFGElement &E) { 176 return E.getKind() == Constructor; 177 } 178 }; 179 180 /// Represents a function call that returns a C++ object by value. This, like 181 /// constructor, requires a construction context in order to understand the 182 /// storage of the returned object . In C such tracking is not necessary because 183 /// no additional effort is required for destroying the object or modeling copy 184 /// elision. Like CFGConstructor, this element is for now only used by the 185 /// analyzer's CFG. 186 class CFGCXXRecordTypedCall : public CFGStmt { 187 public: 188 /// Returns true when call expression \p CE needs to be represented 189 /// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt. isCXXRecordTypedCall(const Expr * E)190 static bool isCXXRecordTypedCall(const Expr *E) { 191 assert(isa<CallExpr>(E) || isa<ObjCMessageExpr>(E)); 192 // There is no such thing as reference-type expression. If the function 193 // returns a reference, it'll return the respective lvalue or xvalue 194 // instead, and we're only interested in objects. 195 return !E->isGLValue() && 196 E->getType().getCanonicalType()->getAsCXXRecordDecl(); 197 } 198 CFGCXXRecordTypedCall(const Expr * E,const ConstructionContext * C)199 explicit CFGCXXRecordTypedCall(const Expr *E, const ConstructionContext *C) 200 : CFGStmt(E, CXXRecordTypedCall) { 201 assert(isCXXRecordTypedCall(E)); 202 assert(C && (isa<TemporaryObjectConstructionContext>(C) || 203 // These are possible in C++17 due to mandatory copy elision. 204 isa<ReturnedValueConstructionContext>(C) || 205 isa<VariableConstructionContext>(C) || 206 isa<ConstructorInitializerConstructionContext>(C) || 207 isa<ArgumentConstructionContext>(C) || 208 isa<LambdaCaptureConstructionContext>(C))); 209 Data2.setPointer(const_cast<ConstructionContext *>(C)); 210 } 211 getConstructionContext()212 const ConstructionContext *getConstructionContext() const { 213 return static_cast<ConstructionContext *>(Data2.getPointer()); 214 } 215 216 private: 217 friend class CFGElement; 218 219 CFGCXXRecordTypedCall() = default; 220 isKind(const CFGElement & E)221 static bool isKind(const CFGElement &E) { 222 return E.getKind() == CXXRecordTypedCall; 223 } 224 }; 225 226 /// Represents C++ base or member initializer from constructor's initialization 227 /// list. 228 class CFGInitializer : public CFGElement { 229 public: CFGInitializer(const CXXCtorInitializer * initializer)230 explicit CFGInitializer(const CXXCtorInitializer *initializer) 231 : CFGElement(Initializer, initializer) {} 232 getInitializer()233 CXXCtorInitializer* getInitializer() const { 234 return static_cast<CXXCtorInitializer*>(Data1.getPointer()); 235 } 236 237 private: 238 friend class CFGElement; 239 240 CFGInitializer() = default; 241 isKind(const CFGElement & E)242 static bool isKind(const CFGElement &E) { 243 return E.getKind() == Initializer; 244 } 245 }; 246 247 /// Represents C++ allocator call. 248 class CFGNewAllocator : public CFGElement { 249 public: CFGNewAllocator(const CXXNewExpr * S)250 explicit CFGNewAllocator(const CXXNewExpr *S) 251 : CFGElement(NewAllocator, S) {} 252 253 // Get the new expression. getAllocatorExpr()254 const CXXNewExpr *getAllocatorExpr() const { 255 return static_cast<CXXNewExpr *>(Data1.getPointer()); 256 } 257 258 private: 259 friend class CFGElement; 260 261 CFGNewAllocator() = default; 262 isKind(const CFGElement & elem)263 static bool isKind(const CFGElement &elem) { 264 return elem.getKind() == NewAllocator; 265 } 266 }; 267 268 /// Represents the point where a loop ends. 269 /// This element is only produced when building the CFG for the static 270 /// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag. 271 /// 272 /// Note: a loop exit element can be reached even when the loop body was never 273 /// entered. 274 class CFGLoopExit : public CFGElement { 275 public: CFGLoopExit(const Stmt * stmt)276 explicit CFGLoopExit(const Stmt *stmt) : CFGElement(LoopExit, stmt) {} 277 getLoopStmt()278 const Stmt *getLoopStmt() const { 279 return static_cast<Stmt *>(Data1.getPointer()); 280 } 281 282 private: 283 friend class CFGElement; 284 285 CFGLoopExit() = default; 286 isKind(const CFGElement & elem)287 static bool isKind(const CFGElement &elem) { 288 return elem.getKind() == LoopExit; 289 } 290 }; 291 292 /// Represents the point where the lifetime of an automatic object ends 293 class CFGLifetimeEnds : public CFGElement { 294 public: CFGLifetimeEnds(const VarDecl * var,const Stmt * stmt)295 explicit CFGLifetimeEnds(const VarDecl *var, const Stmt *stmt) 296 : CFGElement(LifetimeEnds, var, stmt) {} 297 getVarDecl()298 const VarDecl *getVarDecl() const { 299 return static_cast<VarDecl *>(Data1.getPointer()); 300 } 301 getTriggerStmt()302 const Stmt *getTriggerStmt() const { 303 return static_cast<Stmt *>(Data2.getPointer()); 304 } 305 306 private: 307 friend class CFGElement; 308 309 CFGLifetimeEnds() = default; 310 isKind(const CFGElement & elem)311 static bool isKind(const CFGElement &elem) { 312 return elem.getKind() == LifetimeEnds; 313 } 314 }; 315 316 /// Represents beginning of a scope implicitly generated 317 /// by the compiler on encountering a CompoundStmt 318 class CFGScopeBegin : public CFGElement { 319 public: CFGScopeBegin()320 CFGScopeBegin() {} CFGScopeBegin(const VarDecl * VD,const Stmt * S)321 CFGScopeBegin(const VarDecl *VD, const Stmt *S) 322 : CFGElement(ScopeBegin, VD, S) {} 323 324 // Get statement that triggered a new scope. getTriggerStmt()325 const Stmt *getTriggerStmt() const { 326 return static_cast<Stmt*>(Data2.getPointer()); 327 } 328 329 // Get VD that triggered a new scope. getVarDecl()330 const VarDecl *getVarDecl() const { 331 return static_cast<VarDecl *>(Data1.getPointer()); 332 } 333 334 private: 335 friend class CFGElement; isKind(const CFGElement & E)336 static bool isKind(const CFGElement &E) { 337 Kind kind = E.getKind(); 338 return kind == ScopeBegin; 339 } 340 }; 341 342 /// Represents end of a scope implicitly generated by 343 /// the compiler after the last Stmt in a CompoundStmt's body 344 class CFGScopeEnd : public CFGElement { 345 public: CFGScopeEnd()346 CFGScopeEnd() {} CFGScopeEnd(const VarDecl * VD,const Stmt * S)347 CFGScopeEnd(const VarDecl *VD, const Stmt *S) : CFGElement(ScopeEnd, VD, S) {} 348 getVarDecl()349 const VarDecl *getVarDecl() const { 350 return static_cast<VarDecl *>(Data1.getPointer()); 351 } 352 getTriggerStmt()353 const Stmt *getTriggerStmt() const { 354 return static_cast<Stmt *>(Data2.getPointer()); 355 } 356 357 private: 358 friend class CFGElement; isKind(const CFGElement & E)359 static bool isKind(const CFGElement &E) { 360 Kind kind = E.getKind(); 361 return kind == ScopeEnd; 362 } 363 }; 364 365 /// Represents C++ object destructor implicitly generated by compiler on various 366 /// occasions. 367 class CFGImplicitDtor : public CFGElement { 368 protected: 369 CFGImplicitDtor() = default; 370 371 CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr) CFGElement(kind,data1,data2)372 : CFGElement(kind, data1, data2) { 373 assert(kind >= DTOR_BEGIN && kind <= DTOR_END); 374 } 375 376 public: 377 const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const; 378 bool isNoReturn(ASTContext &astContext) const; 379 380 private: 381 friend class CFGElement; 382 isKind(const CFGElement & E)383 static bool isKind(const CFGElement &E) { 384 Kind kind = E.getKind(); 385 return kind >= DTOR_BEGIN && kind <= DTOR_END; 386 } 387 }; 388 389 class CFGCleanupFunction final : public CFGElement { 390 public: 391 CFGCleanupFunction() = default; CFGCleanupFunction(const VarDecl * VD)392 CFGCleanupFunction(const VarDecl *VD) 393 : CFGElement(Kind::CleanupFunction, VD) { 394 assert(VD->hasAttr<CleanupAttr>()); 395 } 396 getVarDecl()397 const VarDecl *getVarDecl() const { 398 return static_cast<VarDecl *>(Data1.getPointer()); 399 } 400 401 /// Returns the function to be called when cleaning up the var decl. getFunctionDecl()402 const FunctionDecl *getFunctionDecl() const { 403 const CleanupAttr *A = getVarDecl()->getAttr<CleanupAttr>(); 404 return A->getFunctionDecl(); 405 } 406 407 private: 408 friend class CFGElement; 409 isKind(const CFGElement E)410 static bool isKind(const CFGElement E) { 411 return E.getKind() == Kind::CleanupFunction; 412 } 413 }; 414 415 /// Represents C++ object destructor implicitly generated for automatic object 416 /// or temporary bound to const reference at the point of leaving its local 417 /// scope. 418 class CFGAutomaticObjDtor: public CFGImplicitDtor { 419 public: CFGAutomaticObjDtor(const VarDecl * var,const Stmt * stmt)420 CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt) 421 : CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {} 422 getVarDecl()423 const VarDecl *getVarDecl() const { 424 return static_cast<VarDecl*>(Data1.getPointer()); 425 } 426 427 // Get statement end of which triggered the destructor call. getTriggerStmt()428 const Stmt *getTriggerStmt() const { 429 return static_cast<Stmt*>(Data2.getPointer()); 430 } 431 432 private: 433 friend class CFGElement; 434 435 CFGAutomaticObjDtor() = default; 436 isKind(const CFGElement & elem)437 static bool isKind(const CFGElement &elem) { 438 return elem.getKind() == AutomaticObjectDtor; 439 } 440 }; 441 442 /// Represents C++ object destructor generated from a call to delete. 443 class CFGDeleteDtor : public CFGImplicitDtor { 444 public: CFGDeleteDtor(const CXXRecordDecl * RD,const CXXDeleteExpr * DE)445 CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE) 446 : CFGImplicitDtor(DeleteDtor, RD, DE) {} 447 getCXXRecordDecl()448 const CXXRecordDecl *getCXXRecordDecl() const { 449 return static_cast<CXXRecordDecl*>(Data1.getPointer()); 450 } 451 452 // Get Delete expression which triggered the destructor call. getDeleteExpr()453 const CXXDeleteExpr *getDeleteExpr() const { 454 return static_cast<CXXDeleteExpr *>(Data2.getPointer()); 455 } 456 457 private: 458 friend class CFGElement; 459 460 CFGDeleteDtor() = default; 461 isKind(const CFGElement & elem)462 static bool isKind(const CFGElement &elem) { 463 return elem.getKind() == DeleteDtor; 464 } 465 }; 466 467 /// Represents C++ object destructor implicitly generated for base object in 468 /// destructor. 469 class CFGBaseDtor : public CFGImplicitDtor { 470 public: CFGBaseDtor(const CXXBaseSpecifier * base)471 CFGBaseDtor(const CXXBaseSpecifier *base) 472 : CFGImplicitDtor(BaseDtor, base) {} 473 getBaseSpecifier()474 const CXXBaseSpecifier *getBaseSpecifier() const { 475 return static_cast<const CXXBaseSpecifier*>(Data1.getPointer()); 476 } 477 478 private: 479 friend class CFGElement; 480 481 CFGBaseDtor() = default; 482 isKind(const CFGElement & E)483 static bool isKind(const CFGElement &E) { 484 return E.getKind() == BaseDtor; 485 } 486 }; 487 488 /// Represents C++ object destructor implicitly generated for member object in 489 /// destructor. 490 class CFGMemberDtor : public CFGImplicitDtor { 491 public: CFGMemberDtor(const FieldDecl * field)492 CFGMemberDtor(const FieldDecl *field) 493 : CFGImplicitDtor(MemberDtor, field, nullptr) {} 494 getFieldDecl()495 const FieldDecl *getFieldDecl() const { 496 return static_cast<const FieldDecl*>(Data1.getPointer()); 497 } 498 499 private: 500 friend class CFGElement; 501 502 CFGMemberDtor() = default; 503 isKind(const CFGElement & E)504 static bool isKind(const CFGElement &E) { 505 return E.getKind() == MemberDtor; 506 } 507 }; 508 509 /// Represents C++ object destructor implicitly generated at the end of full 510 /// expression for temporary object. 511 class CFGTemporaryDtor : public CFGImplicitDtor { 512 public: CFGTemporaryDtor(const CXXBindTemporaryExpr * expr)513 CFGTemporaryDtor(const CXXBindTemporaryExpr *expr) 514 : CFGImplicitDtor(TemporaryDtor, expr, nullptr) {} 515 getBindTemporaryExpr()516 const CXXBindTemporaryExpr *getBindTemporaryExpr() const { 517 return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer()); 518 } 519 520 private: 521 friend class CFGElement; 522 523 CFGTemporaryDtor() = default; 524 isKind(const CFGElement & E)525 static bool isKind(const CFGElement &E) { 526 return E.getKind() == TemporaryDtor; 527 } 528 }; 529 530 /// Represents CFGBlock terminator statement. 531 /// 532 class CFGTerminator { 533 public: 534 enum Kind { 535 /// A branch that corresponds to a statement in the code, 536 /// such as an if-statement. 537 StmtBranch, 538 /// A branch in control flow of destructors of temporaries. In this case 539 /// terminator statement is the same statement that branches control flow 540 /// in evaluation of matching full expression. 541 TemporaryDtorsBranch, 542 /// A shortcut around virtual base initializers. It gets taken when 543 /// virtual base classes have already been initialized by the constructor 544 /// of the most derived class while we're in the base class. 545 VirtualBaseBranch, 546 547 /// Number of different kinds, for assertions. We subtract 1 so that 548 /// to keep receiving compiler warnings when we don't cover all enum values 549 /// in a switch. 550 NumKindsMinusOne = VirtualBaseBranch 551 }; 552 553 private: 554 static constexpr int KindBits = 2; 555 static_assert((1 << KindBits) > NumKindsMinusOne, 556 "Not enough room for kind!"); 557 llvm::PointerIntPair<Stmt *, KindBits> Data; 558 559 public: CFGTerminator()560 CFGTerminator() { assert(!isValid()); } Data(S,K)561 CFGTerminator(Stmt *S, Kind K = StmtBranch) : Data(S, K) {} 562 isValid()563 bool isValid() const { return Data.getOpaqueValue() != nullptr; } getStmt()564 Stmt *getStmt() { return Data.getPointer(); } getStmt()565 const Stmt *getStmt() const { return Data.getPointer(); } getKind()566 Kind getKind() const { return static_cast<Kind>(Data.getInt()); } 567 isStmtBranch()568 bool isStmtBranch() const { 569 return getKind() == StmtBranch; 570 } isTemporaryDtorsBranch()571 bool isTemporaryDtorsBranch() const { 572 return getKind() == TemporaryDtorsBranch; 573 } isVirtualBaseBranch()574 bool isVirtualBaseBranch() const { 575 return getKind() == VirtualBaseBranch; 576 } 577 }; 578 579 /// Represents a single basic block in a source-level CFG. 580 /// It consists of: 581 /// 582 /// (1) A set of statements/expressions (which may contain subexpressions). 583 /// (2) A "terminator" statement (not in the set of statements). 584 /// (3) A list of successors and predecessors. 585 /// 586 /// Terminator: The terminator represents the type of control-flow that occurs 587 /// at the end of the basic block. The terminator is a Stmt* referring to an 588 /// AST node that has control-flow: if-statements, breaks, loops, etc. 589 /// If the control-flow is conditional, the condition expression will appear 590 /// within the set of statements in the block (usually the last statement). 591 /// 592 /// Predecessors: the order in the set of predecessors is arbitrary. 593 /// 594 /// Successors: the order in the set of successors is NOT arbitrary. We 595 /// currently have the following orderings based on the terminator: 596 /// 597 /// Terminator | Successor Ordering 598 /// ------------------|------------------------------------ 599 /// if | Then Block; Else Block 600 /// ? operator | LHS expression; RHS expression 601 /// logical and/or | expression that consumes the op, RHS 602 /// vbase inits | already handled by the most derived class; not yet 603 /// 604 /// But note that any of that may be NULL in case of optimized-out edges. 605 class CFGBlock { 606 class ElementList { 607 using ImplTy = BumpVector<CFGElement>; 608 609 ImplTy Impl; 610 611 public: ElementList(BumpVectorContext & C)612 ElementList(BumpVectorContext &C) : Impl(C, 4) {} 613 614 using iterator = std::reverse_iterator<ImplTy::iterator>; 615 using const_iterator = std::reverse_iterator<ImplTy::const_iterator>; 616 using reverse_iterator = ImplTy::iterator; 617 using const_reverse_iterator = ImplTy::const_iterator; 618 using const_reference = ImplTy::const_reference; 619 push_back(CFGElement e,BumpVectorContext & C)620 void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } 621 insert(reverse_iterator I,size_t Cnt,CFGElement E,BumpVectorContext & C)622 reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E, 623 BumpVectorContext &C) { 624 return Impl.insert(I, Cnt, E, C); 625 } 626 front()627 const_reference front() const { return Impl.back(); } back()628 const_reference back() const { return Impl.front(); } 629 begin()630 iterator begin() { return Impl.rbegin(); } end()631 iterator end() { return Impl.rend(); } begin()632 const_iterator begin() const { return Impl.rbegin(); } end()633 const_iterator end() const { return Impl.rend(); } rbegin()634 reverse_iterator rbegin() { return Impl.begin(); } rend()635 reverse_iterator rend() { return Impl.end(); } rbegin()636 const_reverse_iterator rbegin() const { return Impl.begin(); } rend()637 const_reverse_iterator rend() const { return Impl.end(); } 638 639 CFGElement operator[](size_t i) const { 640 assert(i < Impl.size()); 641 return Impl[Impl.size() - 1 - i]; 642 } 643 size()644 size_t size() const { return Impl.size(); } empty()645 bool empty() const { return Impl.empty(); } 646 }; 647 648 /// A convenience class for comparing CFGElements, since methods of CFGBlock 649 /// like operator[] return CFGElements by value. This is practically a wrapper 650 /// around a (CFGBlock, Index) pair. 651 template <bool IsConst> class ElementRefImpl { 652 653 template <bool IsOtherConst> friend class ElementRefImpl; 654 655 using CFGBlockPtr = 656 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>; 657 658 using CFGElementPtr = 659 std::conditional_t<IsConst, const CFGElement *, CFGElement *>; 660 661 protected: 662 CFGBlockPtr Parent; 663 size_t Index; 664 665 public: ElementRefImpl(CFGBlockPtr Parent,size_t Index)666 ElementRefImpl(CFGBlockPtr Parent, size_t Index) 667 : Parent(Parent), Index(Index) {} 668 669 template <bool IsOtherConst> ElementRefImpl(ElementRefImpl<IsOtherConst> Other)670 ElementRefImpl(ElementRefImpl<IsOtherConst> Other) 671 : ElementRefImpl(Other.Parent, Other.Index) {} 672 getIndexInBlock()673 size_t getIndexInBlock() const { return Index; } 674 getParent()675 CFGBlockPtr getParent() { return Parent; } getParent()676 CFGBlockPtr getParent() const { return Parent; } 677 678 bool operator<(ElementRefImpl Other) const { 679 return std::make_pair(Parent, Index) < 680 std::make_pair(Other.Parent, Other.Index); 681 } 682 683 bool operator==(ElementRefImpl Other) const { 684 return Parent == Other.Parent && Index == Other.Index; 685 } 686 687 bool operator!=(ElementRefImpl Other) const { return !(*this == Other); } 688 CFGElement operator*() const { return (*Parent)[Index]; } 689 CFGElementPtr operator->() const { return &*(Parent->begin() + Index); } 690 dumpToStream(llvm::raw_ostream & OS)691 void dumpToStream(llvm::raw_ostream &OS) const { 692 OS << getIndexInBlock() + 1 << ": "; 693 (*this)->dumpToStream(OS); 694 } 695 dump()696 void dump() const { 697 dumpToStream(llvm::errs()); 698 } 699 Profile(llvm::FoldingSetNodeID & ID)700 void Profile(llvm::FoldingSetNodeID &ID) const { 701 ID.AddPointer(Parent); 702 ID.AddInteger(Index); 703 } 704 }; 705 706 template <bool IsReverse, bool IsConst> class ElementRefIterator { 707 708 template <bool IsOtherReverse, bool IsOtherConst> 709 friend class ElementRefIterator; 710 711 using CFGBlockRef = 712 std::conditional_t<IsConst, const CFGBlock *, CFGBlock *>; 713 714 using UnderlayingIteratorTy = std::conditional_t< 715 IsConst, 716 std::conditional_t<IsReverse, ElementList::const_reverse_iterator, 717 ElementList::const_iterator>, 718 std::conditional_t<IsReverse, ElementList::reverse_iterator, 719 ElementList::iterator>>; 720 721 using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>; 722 using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>; 723 724 public: 725 using difference_type = typename IteratorTraits::difference_type; 726 using value_type = ElementRef; 727 using pointer = ElementRef *; 728 using iterator_category = typename IteratorTraits::iterator_category; 729 730 private: 731 CFGBlockRef Parent; 732 UnderlayingIteratorTy Pos; 733 734 public: ElementRefIterator(CFGBlockRef Parent,UnderlayingIteratorTy Pos)735 ElementRefIterator(CFGBlockRef Parent, UnderlayingIteratorTy Pos) 736 : Parent(Parent), Pos(Pos) {} 737 738 template <bool IsOtherConst> ElementRefIterator(ElementRefIterator<false,IsOtherConst> E)739 ElementRefIterator(ElementRefIterator<false, IsOtherConst> E) 740 : ElementRefIterator(E.Parent, E.Pos.base()) {} 741 742 template <bool IsOtherConst> ElementRefIterator(ElementRefIterator<true,IsOtherConst> E)743 ElementRefIterator(ElementRefIterator<true, IsOtherConst> E) 744 : ElementRefIterator(E.Parent, std::make_reverse_iterator(E.Pos)) {} 745 746 bool operator<(ElementRefIterator Other) const { 747 assert(Parent == Other.Parent); 748 return Pos < Other.Pos; 749 } 750 751 bool operator==(ElementRefIterator Other) const { 752 return Parent == Other.Parent && Pos == Other.Pos; 753 } 754 755 bool operator!=(ElementRefIterator Other) const { 756 return !(*this == Other); 757 } 758 759 private: 760 template <bool IsOtherConst> 761 static size_t getIndexInBlock(CFGBlock::ElementRefIterator<true,IsOtherConst> E)762 getIndexInBlock(CFGBlock::ElementRefIterator<true, IsOtherConst> E) { 763 return E.Parent->size() - (E.Pos - E.Parent->rbegin()) - 1; 764 } 765 766 template <bool IsOtherConst> 767 static size_t getIndexInBlock(CFGBlock::ElementRefIterator<false,IsOtherConst> E)768 getIndexInBlock(CFGBlock::ElementRefIterator<false, IsOtherConst> E) { 769 return E.Pos - E.Parent->begin(); 770 } 771 772 public: 773 value_type operator*() { return {Parent, getIndexInBlock(*this)}; } 774 775 difference_type operator-(ElementRefIterator Other) const { 776 return Pos - Other.Pos; 777 } 778 779 ElementRefIterator operator++() { 780 ++this->Pos; 781 return *this; 782 } 783 ElementRefIterator operator++(int) { 784 ElementRefIterator Ret = *this; 785 ++*this; 786 return Ret; 787 } 788 ElementRefIterator operator+(size_t count) { 789 this->Pos += count; 790 return *this; 791 } 792 ElementRefIterator operator-(size_t count) { 793 this->Pos -= count; 794 return *this; 795 } 796 }; 797 798 public: 799 /// The set of statements in the basic block. 800 ElementList Elements; 801 802 /// An (optional) label that prefixes the executable statements in the block. 803 /// When this variable is non-NULL, it is either an instance of LabelStmt, 804 /// SwitchCase or CXXCatchStmt. 805 Stmt *Label = nullptr; 806 807 /// The terminator for a basic block that indicates the type of control-flow 808 /// that occurs between a block and its successors. 809 CFGTerminator Terminator; 810 811 /// Some blocks are used to represent the "loop edge" to the start of a loop 812 /// from within the loop body. This Stmt* will be refer to the loop statement 813 /// for such blocks (and be null otherwise). 814 const Stmt *LoopTarget = nullptr; 815 816 /// A numerical ID assigned to a CFGBlock during construction of the CFG. 817 unsigned BlockID; 818 819 public: 820 /// This class represents a potential adjacent block in the CFG. It encodes 821 /// whether or not the block is actually reachable, or can be proved to be 822 /// trivially unreachable. For some cases it allows one to encode scenarios 823 /// where a block was substituted because the original (now alternate) block 824 /// is unreachable. 825 class AdjacentBlock { 826 enum Kind { 827 AB_Normal, 828 AB_Unreachable, 829 AB_Alternate 830 }; 831 832 CFGBlock *ReachableBlock; 833 llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock; 834 835 public: 836 /// Construct an AdjacentBlock with a possibly unreachable block. 837 AdjacentBlock(CFGBlock *B, bool IsReachable); 838 839 /// Construct an AdjacentBlock with a reachable block and an alternate 840 /// unreachable block. 841 AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock); 842 843 /// Get the reachable block, if one exists. getReachableBlock()844 CFGBlock *getReachableBlock() const { 845 return ReachableBlock; 846 } 847 848 /// Get the potentially unreachable block. getPossiblyUnreachableBlock()849 CFGBlock *getPossiblyUnreachableBlock() const { 850 return UnreachableBlock.getPointer(); 851 } 852 853 /// Provide an implicit conversion to CFGBlock* so that 854 /// AdjacentBlock can be substituted for CFGBlock*. 855 operator CFGBlock*() const { 856 return getReachableBlock(); 857 } 858 859 CFGBlock& operator *() const { 860 return *getReachableBlock(); 861 } 862 863 CFGBlock* operator ->() const { 864 return getReachableBlock(); 865 } 866 isReachable()867 bool isReachable() const { 868 Kind K = (Kind) UnreachableBlock.getInt(); 869 return K == AB_Normal || K == AB_Alternate; 870 } 871 }; 872 873 private: 874 /// Keep track of the predecessor / successor CFG blocks. 875 using AdjacentBlocks = BumpVector<AdjacentBlock>; 876 AdjacentBlocks Preds; 877 AdjacentBlocks Succs; 878 879 /// This bit is set when the basic block contains a function call 880 /// or implicit destructor that is attributed as 'noreturn'. In that case, 881 /// control cannot technically ever proceed past this block. All such blocks 882 /// will have a single immediate successor: the exit block. This allows them 883 /// to be easily reached from the exit block and using this bit quickly 884 /// recognized without scanning the contents of the block. 885 /// 886 /// Optimization Note: This bit could be profitably folded with Terminator's 887 /// storage if the memory usage of CFGBlock becomes an issue. 888 LLVM_PREFERRED_TYPE(bool) 889 unsigned HasNoReturnElement : 1; 890 891 /// The parent CFG that owns this CFGBlock. 892 CFG *Parent; 893 894 public: CFGBlock(unsigned blockid,BumpVectorContext & C,CFG * parent)895 explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent) 896 : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1), 897 Succs(C, 1), HasNoReturnElement(false), Parent(parent) {} 898 899 // Statement iterators 900 using iterator = ElementList::iterator; 901 using const_iterator = ElementList::const_iterator; 902 using reverse_iterator = ElementList::reverse_iterator; 903 using const_reverse_iterator = ElementList::const_reverse_iterator; 904 905 size_t getIndexInCFG() const; 906 front()907 CFGElement front() const { return Elements.front(); } back()908 CFGElement back() const { return Elements.back(); } 909 begin()910 iterator begin() { return Elements.begin(); } end()911 iterator end() { return Elements.end(); } begin()912 const_iterator begin() const { return Elements.begin(); } end()913 const_iterator end() const { return Elements.end(); } 914 rbegin()915 reverse_iterator rbegin() { return Elements.rbegin(); } rend()916 reverse_iterator rend() { return Elements.rend(); } rbegin()917 const_reverse_iterator rbegin() const { return Elements.rbegin(); } rend()918 const_reverse_iterator rend() const { return Elements.rend(); } 919 920 using CFGElementRef = ElementRefImpl<false>; 921 using ConstCFGElementRef = ElementRefImpl<true>; 922 923 using ref_iterator = ElementRefIterator<false, false>; 924 using ref_iterator_range = llvm::iterator_range<ref_iterator>; 925 using const_ref_iterator = ElementRefIterator<false, true>; 926 using const_ref_iterator_range = llvm::iterator_range<const_ref_iterator>; 927 928 using reverse_ref_iterator = ElementRefIterator<true, false>; 929 using reverse_ref_iterator_range = llvm::iterator_range<reverse_ref_iterator>; 930 931 using const_reverse_ref_iterator = ElementRefIterator<true, true>; 932 using const_reverse_ref_iterator_range = 933 llvm::iterator_range<const_reverse_ref_iterator>; 934 ref_begin()935 ref_iterator ref_begin() { return {this, begin()}; } ref_end()936 ref_iterator ref_end() { return {this, end()}; } ref_begin()937 const_ref_iterator ref_begin() const { return {this, begin()}; } ref_end()938 const_ref_iterator ref_end() const { return {this, end()}; } 939 rref_begin()940 reverse_ref_iterator rref_begin() { return {this, rbegin()}; } rref_end()941 reverse_ref_iterator rref_end() { return {this, rend()}; } rref_begin()942 const_reverse_ref_iterator rref_begin() const { return {this, rbegin()}; } rref_end()943 const_reverse_ref_iterator rref_end() const { return {this, rend()}; } 944 refs()945 ref_iterator_range refs() { return {ref_begin(), ref_end()}; } refs()946 const_ref_iterator_range refs() const { return {ref_begin(), ref_end()}; } rrefs()947 reverse_ref_iterator_range rrefs() { return {rref_begin(), rref_end()}; } rrefs()948 const_reverse_ref_iterator_range rrefs() const { 949 return {rref_begin(), rref_end()}; 950 } 951 size()952 unsigned size() const { return Elements.size(); } empty()953 bool empty() const { return Elements.empty(); } 954 955 CFGElement operator[](size_t i) const { return Elements[i]; } 956 957 // CFG iterators 958 using pred_iterator = AdjacentBlocks::iterator; 959 using const_pred_iterator = AdjacentBlocks::const_iterator; 960 using pred_reverse_iterator = AdjacentBlocks::reverse_iterator; 961 using const_pred_reverse_iterator = AdjacentBlocks::const_reverse_iterator; 962 using pred_range = llvm::iterator_range<pred_iterator>; 963 using pred_const_range = llvm::iterator_range<const_pred_iterator>; 964 965 using succ_iterator = AdjacentBlocks::iterator; 966 using const_succ_iterator = AdjacentBlocks::const_iterator; 967 using succ_reverse_iterator = AdjacentBlocks::reverse_iterator; 968 using const_succ_reverse_iterator = AdjacentBlocks::const_reverse_iterator; 969 using succ_range = llvm::iterator_range<succ_iterator>; 970 using succ_const_range = llvm::iterator_range<const_succ_iterator>; 971 pred_begin()972 pred_iterator pred_begin() { return Preds.begin(); } pred_end()973 pred_iterator pred_end() { return Preds.end(); } pred_begin()974 const_pred_iterator pred_begin() const { return Preds.begin(); } pred_end()975 const_pred_iterator pred_end() const { return Preds.end(); } 976 pred_rbegin()977 pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); } pred_rend()978 pred_reverse_iterator pred_rend() { return Preds.rend(); } pred_rbegin()979 const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); } pred_rend()980 const_pred_reverse_iterator pred_rend() const { return Preds.rend(); } 981 preds()982 pred_range preds() { 983 return pred_range(pred_begin(), pred_end()); 984 } 985 preds()986 pred_const_range preds() const { 987 return pred_const_range(pred_begin(), pred_end()); 988 } 989 succ_begin()990 succ_iterator succ_begin() { return Succs.begin(); } succ_end()991 succ_iterator succ_end() { return Succs.end(); } succ_begin()992 const_succ_iterator succ_begin() const { return Succs.begin(); } succ_end()993 const_succ_iterator succ_end() const { return Succs.end(); } 994 succ_rbegin()995 succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); } succ_rend()996 succ_reverse_iterator succ_rend() { return Succs.rend(); } succ_rbegin()997 const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); } succ_rend()998 const_succ_reverse_iterator succ_rend() const { return Succs.rend(); } 999 succs()1000 succ_range succs() { 1001 return succ_range(succ_begin(), succ_end()); 1002 } 1003 succs()1004 succ_const_range succs() const { 1005 return succ_const_range(succ_begin(), succ_end()); 1006 } 1007 succ_size()1008 unsigned succ_size() const { return Succs.size(); } succ_empty()1009 bool succ_empty() const { return Succs.empty(); } 1010 pred_size()1011 unsigned pred_size() const { return Preds.size(); } pred_empty()1012 bool pred_empty() const { return Preds.empty(); } 1013 1014 1015 class FilterOptions { 1016 public: 1017 LLVM_PREFERRED_TYPE(bool) 1018 unsigned IgnoreNullPredecessors : 1; 1019 LLVM_PREFERRED_TYPE(bool) 1020 unsigned IgnoreDefaultsWithCoveredEnums : 1; 1021 FilterOptions()1022 FilterOptions() 1023 : IgnoreNullPredecessors(1), IgnoreDefaultsWithCoveredEnums(0) {} 1024 }; 1025 1026 static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, 1027 const CFGBlock *Dst); 1028 1029 template <typename IMPL, bool IsPred> 1030 class FilteredCFGBlockIterator { 1031 private: 1032 IMPL I, E; 1033 const FilterOptions F; 1034 const CFGBlock *From; 1035 1036 public: FilteredCFGBlockIterator(const IMPL & i,const IMPL & e,const CFGBlock * from,const FilterOptions & f)1037 explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, 1038 const CFGBlock *from, 1039 const FilterOptions &f) 1040 : I(i), E(e), F(f), From(from) { 1041 while (hasMore() && Filter(*I)) 1042 ++I; 1043 } 1044 hasMore()1045 bool hasMore() const { return I != E; } 1046 1047 FilteredCFGBlockIterator &operator++() { 1048 do { ++I; } while (hasMore() && Filter(*I)); 1049 return *this; 1050 } 1051 1052 const CFGBlock *operator*() const { return *I; } 1053 1054 private: Filter(const CFGBlock * To)1055 bool Filter(const CFGBlock *To) { 1056 return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To); 1057 } 1058 }; 1059 1060 using filtered_pred_iterator = 1061 FilteredCFGBlockIterator<const_pred_iterator, true>; 1062 1063 using filtered_succ_iterator = 1064 FilteredCFGBlockIterator<const_succ_iterator, false>; 1065 filtered_pred_start_end(const FilterOptions & f)1066 filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const { 1067 return filtered_pred_iterator(pred_begin(), pred_end(), this, f); 1068 } 1069 filtered_succ_start_end(const FilterOptions & f)1070 filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const { 1071 return filtered_succ_iterator(succ_begin(), succ_end(), this, f); 1072 } 1073 1074 // Manipulation of block contents 1075 setTerminator(CFGTerminator Term)1076 void setTerminator(CFGTerminator Term) { Terminator = Term; } setLabel(Stmt * Statement)1077 void setLabel(Stmt *Statement) { Label = Statement; } setLoopTarget(const Stmt * loopTarget)1078 void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } setHasNoReturnElement()1079 void setHasNoReturnElement() { HasNoReturnElement = true; } 1080 1081 /// Returns true if the block would eventually end with a sink (a noreturn 1082 /// node). 1083 bool isInevitablySinking() const; 1084 getTerminator()1085 CFGTerminator getTerminator() const { return Terminator; } 1086 getTerminatorStmt()1087 Stmt *getTerminatorStmt() { return Terminator.getStmt(); } getTerminatorStmt()1088 const Stmt *getTerminatorStmt() const { return Terminator.getStmt(); } 1089 1090 /// \returns the last (\c rbegin()) condition, e.g. observe the following code 1091 /// snippet: 1092 /// if (A && B && C) 1093 /// A block would be created for \c A, \c B, and \c C. For the latter, 1094 /// \c getTerminatorStmt() would retrieve the entire condition, rather than 1095 /// C itself, while this method would only return C. 1096 const Expr *getLastCondition() const; 1097 1098 Stmt *getTerminatorCondition(bool StripParens = true); 1099 1100 const Stmt *getTerminatorCondition(bool StripParens = true) const { 1101 return const_cast<CFGBlock*>(this)->getTerminatorCondition(StripParens); 1102 } 1103 getLoopTarget()1104 const Stmt *getLoopTarget() const { return LoopTarget; } 1105 getLabel()1106 Stmt *getLabel() { return Label; } getLabel()1107 const Stmt *getLabel() const { return Label; } 1108 hasNoReturnElement()1109 bool hasNoReturnElement() const { return HasNoReturnElement; } 1110 getBlockID()1111 unsigned getBlockID() const { return BlockID; } 1112 getParent()1113 CFG *getParent() const { return Parent; } 1114 1115 void dump() const; 1116 1117 void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const; 1118 void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO, 1119 bool ShowColors) const; 1120 1121 void printTerminator(raw_ostream &OS, const LangOptions &LO) const; 1122 void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, 1123 bool AddQuotes) const; 1124 printAsOperand(raw_ostream & OS,bool)1125 void printAsOperand(raw_ostream &OS, bool /*PrintType*/) { 1126 OS << "BB#" << getBlockID(); 1127 } 1128 1129 /// Adds a (potentially unreachable) successor block to the current block. 1130 void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C); 1131 appendStmt(Stmt * statement,BumpVectorContext & C)1132 void appendStmt(Stmt *statement, BumpVectorContext &C) { 1133 Elements.push_back(CFGStmt(statement), C); 1134 } 1135 appendConstructor(CXXConstructExpr * CE,const ConstructionContext * CC,BumpVectorContext & C)1136 void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, 1137 BumpVectorContext &C) { 1138 Elements.push_back(CFGConstructor(CE, CC), C); 1139 } 1140 appendCXXRecordTypedCall(Expr * E,const ConstructionContext * CC,BumpVectorContext & C)1141 void appendCXXRecordTypedCall(Expr *E, 1142 const ConstructionContext *CC, 1143 BumpVectorContext &C) { 1144 Elements.push_back(CFGCXXRecordTypedCall(E, CC), C); 1145 } 1146 appendInitializer(CXXCtorInitializer * initializer,BumpVectorContext & C)1147 void appendInitializer(CXXCtorInitializer *initializer, 1148 BumpVectorContext &C) { 1149 Elements.push_back(CFGInitializer(initializer), C); 1150 } 1151 appendNewAllocator(CXXNewExpr * NE,BumpVectorContext & C)1152 void appendNewAllocator(CXXNewExpr *NE, 1153 BumpVectorContext &C) { 1154 Elements.push_back(CFGNewAllocator(NE), C); 1155 } 1156 appendScopeBegin(const VarDecl * VD,const Stmt * S,BumpVectorContext & C)1157 void appendScopeBegin(const VarDecl *VD, const Stmt *S, 1158 BumpVectorContext &C) { 1159 Elements.push_back(CFGScopeBegin(VD, S), C); 1160 } 1161 appendScopeEnd(const VarDecl * VD,const Stmt * S,BumpVectorContext & C)1162 void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) { 1163 Elements.push_back(CFGScopeEnd(VD, S), C); 1164 } 1165 appendBaseDtor(const CXXBaseSpecifier * BS,BumpVectorContext & C)1166 void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) { 1167 Elements.push_back(CFGBaseDtor(BS), C); 1168 } 1169 appendMemberDtor(FieldDecl * FD,BumpVectorContext & C)1170 void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C) { 1171 Elements.push_back(CFGMemberDtor(FD), C); 1172 } 1173 appendTemporaryDtor(CXXBindTemporaryExpr * E,BumpVectorContext & C)1174 void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C) { 1175 Elements.push_back(CFGTemporaryDtor(E), C); 1176 } 1177 appendAutomaticObjDtor(VarDecl * VD,Stmt * S,BumpVectorContext & C)1178 void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C) { 1179 Elements.push_back(CFGAutomaticObjDtor(VD, S), C); 1180 } 1181 appendCleanupFunction(const VarDecl * VD,BumpVectorContext & C)1182 void appendCleanupFunction(const VarDecl *VD, BumpVectorContext &C) { 1183 Elements.push_back(CFGCleanupFunction(VD), C); 1184 } 1185 appendLifetimeEnds(VarDecl * VD,Stmt * S,BumpVectorContext & C)1186 void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C) { 1187 Elements.push_back(CFGLifetimeEnds(VD, S), C); 1188 } 1189 appendLoopExit(const Stmt * LoopStmt,BumpVectorContext & C)1190 void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) { 1191 Elements.push_back(CFGLoopExit(LoopStmt), C); 1192 } 1193 appendDeleteDtor(CXXRecordDecl * RD,CXXDeleteExpr * DE,BumpVectorContext & C)1194 void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) { 1195 Elements.push_back(CFGDeleteDtor(RD, DE), C); 1196 } 1197 }; 1198 1199 using ConstCFGElementRef = CFGBlock::ConstCFGElementRef; 1200 1201 /// CFGCallback defines methods that should be called when a logical 1202 /// operator error is found when building the CFG. 1203 class CFGCallback { 1204 public: 1205 CFGCallback() = default; 1206 virtual ~CFGCallback() = default; 1207 logicAlwaysTrue(const BinaryOperator * B,bool isAlwaysTrue)1208 virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {} compareAlwaysTrue(const BinaryOperator * B,bool isAlwaysTrue)1209 virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {} compareBitwiseEquality(const BinaryOperator * B,bool isAlwaysTrue)1210 virtual void compareBitwiseEquality(const BinaryOperator *B, 1211 bool isAlwaysTrue) {} compareBitwiseOr(const BinaryOperator * B)1212 virtual void compareBitwiseOr(const BinaryOperator *B) {} 1213 }; 1214 1215 /// Represents a source-level, intra-procedural CFG that represents the 1216 /// control-flow of a Stmt. The Stmt can represent an entire function body, 1217 /// or a single expression. A CFG will always contain one empty block that 1218 /// represents the Exit point of the CFG. A CFG will also contain a designated 1219 /// Entry block. The CFG solely represents control-flow; it consists of 1220 /// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG 1221 /// was constructed from. 1222 class CFG { 1223 public: 1224 //===--------------------------------------------------------------------===// 1225 // CFG Construction & Manipulation. 1226 //===--------------------------------------------------------------------===// 1227 1228 class BuildOptions { 1229 // Stmt::lastStmtConstant has the same value as the last Stmt kind, 1230 // so make sure we add one to account for this! 1231 std::bitset<Stmt::lastStmtConstant + 1> alwaysAddMask; 1232 1233 public: 1234 using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>; 1235 1236 ForcedBlkExprs **forcedBlkExprs = nullptr; 1237 CFGCallback *Observer = nullptr; 1238 bool PruneTriviallyFalseEdges = true; 1239 bool AddEHEdges = false; 1240 bool AddInitializers = false; 1241 bool AddImplicitDtors = false; 1242 bool AddLifetime = false; 1243 bool AddLoopExit = false; 1244 bool AddTemporaryDtors = false; 1245 bool AddScopes = false; 1246 bool AddStaticInitBranches = false; 1247 bool AddCXXNewAllocator = false; 1248 bool AddCXXDefaultInitExprInCtors = false; 1249 bool AddCXXDefaultInitExprInAggregates = false; 1250 bool AddRichCXXConstructors = false; 1251 bool MarkElidedCXXConstructors = false; 1252 bool AddVirtualBaseBranches = false; 1253 bool OmitImplicitValueInitializers = false; 1254 1255 BuildOptions() = default; 1256 alwaysAdd(const Stmt * stmt)1257 bool alwaysAdd(const Stmt *stmt) const { 1258 return alwaysAddMask[stmt->getStmtClass()]; 1259 } 1260 1261 BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) { 1262 alwaysAddMask[stmtClass] = val; 1263 return *this; 1264 } 1265 setAllAlwaysAdd()1266 BuildOptions &setAllAlwaysAdd() { 1267 alwaysAddMask.set(); 1268 return *this; 1269 } 1270 }; 1271 1272 /// Builds a CFG from an AST. 1273 static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C, 1274 const BuildOptions &BO); 1275 1276 /// Create a new block in the CFG. The CFG owns the block; the caller should 1277 /// not directly free it. 1278 CFGBlock *createBlock(); 1279 1280 /// Set the entry block of the CFG. This is typically used only during CFG 1281 /// construction. Most CFG clients expect that the entry block has no 1282 /// predecessors and contains no statements. setEntry(CFGBlock * B)1283 void setEntry(CFGBlock *B) { Entry = B; } 1284 1285 /// Set the block used for indirect goto jumps. This is typically used only 1286 /// during CFG construction. setIndirectGotoBlock(CFGBlock * B)1287 void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; } 1288 1289 //===--------------------------------------------------------------------===// 1290 // Block Iterators 1291 //===--------------------------------------------------------------------===// 1292 1293 using CFGBlockListTy = BumpVector<CFGBlock *>; 1294 using iterator = CFGBlockListTy::iterator; 1295 using const_iterator = CFGBlockListTy::const_iterator; 1296 using reverse_iterator = std::reverse_iterator<iterator>; 1297 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 1298 front()1299 CFGBlock & front() { return *Blocks.front(); } back()1300 CFGBlock & back() { return *Blocks.back(); } 1301 begin()1302 iterator begin() { return Blocks.begin(); } end()1303 iterator end() { return Blocks.end(); } begin()1304 const_iterator begin() const { return Blocks.begin(); } end()1305 const_iterator end() const { return Blocks.end(); } 1306 nodes_begin()1307 iterator nodes_begin() { return iterator(Blocks.begin()); } nodes_end()1308 iterator nodes_end() { return iterator(Blocks.end()); } 1309 nodes()1310 llvm::iterator_range<iterator> nodes() { return {begin(), end()}; } const_nodes()1311 llvm::iterator_range<const_iterator> const_nodes() const { 1312 return {begin(), end()}; 1313 } 1314 nodes_begin()1315 const_iterator nodes_begin() const { return const_iterator(Blocks.begin()); } nodes_end()1316 const_iterator nodes_end() const { return const_iterator(Blocks.end()); } 1317 rbegin()1318 reverse_iterator rbegin() { return Blocks.rbegin(); } rend()1319 reverse_iterator rend() { return Blocks.rend(); } rbegin()1320 const_reverse_iterator rbegin() const { return Blocks.rbegin(); } rend()1321 const_reverse_iterator rend() const { return Blocks.rend(); } 1322 reverse_nodes()1323 llvm::iterator_range<reverse_iterator> reverse_nodes() { 1324 return {rbegin(), rend()}; 1325 } const_reverse_nodes()1326 llvm::iterator_range<const_reverse_iterator> const_reverse_nodes() const { 1327 return {rbegin(), rend()}; 1328 } 1329 getEntry()1330 CFGBlock & getEntry() { return *Entry; } getEntry()1331 const CFGBlock & getEntry() const { return *Entry; } getExit()1332 CFGBlock & getExit() { return *Exit; } getExit()1333 const CFGBlock & getExit() const { return *Exit; } 1334 getIndirectGotoBlock()1335 CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; } getIndirectGotoBlock()1336 const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; } 1337 1338 using try_block_iterator = std::vector<const CFGBlock *>::const_iterator; 1339 using try_block_range = llvm::iterator_range<try_block_iterator>; 1340 try_blocks_begin()1341 try_block_iterator try_blocks_begin() const { 1342 return TryDispatchBlocks.begin(); 1343 } 1344 try_blocks_end()1345 try_block_iterator try_blocks_end() const { 1346 return TryDispatchBlocks.end(); 1347 } 1348 try_blocks()1349 try_block_range try_blocks() const { 1350 return try_block_range(try_blocks_begin(), try_blocks_end()); 1351 } 1352 addTryDispatchBlock(const CFGBlock * block)1353 void addTryDispatchBlock(const CFGBlock *block) { 1354 TryDispatchBlocks.push_back(block); 1355 } 1356 1357 /// Records a synthetic DeclStmt and the DeclStmt it was constructed from. 1358 /// 1359 /// The CFG uses synthetic DeclStmts when a single AST DeclStmt contains 1360 /// multiple decls. addSyntheticDeclStmt(const DeclStmt * Synthetic,const DeclStmt * Source)1361 void addSyntheticDeclStmt(const DeclStmt *Synthetic, 1362 const DeclStmt *Source) { 1363 assert(Synthetic->isSingleDecl() && "Can handle single declarations only"); 1364 assert(Synthetic != Source && "Don't include original DeclStmts in map"); 1365 assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map"); 1366 SyntheticDeclStmts[Synthetic] = Source; 1367 } 1368 1369 using synthetic_stmt_iterator = 1370 llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator; 1371 using synthetic_stmt_range = llvm::iterator_range<synthetic_stmt_iterator>; 1372 1373 /// Iterates over synthetic DeclStmts in the CFG. 1374 /// 1375 /// Each element is a (synthetic statement, source statement) pair. 1376 /// 1377 /// \sa addSyntheticDeclStmt synthetic_stmt_begin()1378 synthetic_stmt_iterator synthetic_stmt_begin() const { 1379 return SyntheticDeclStmts.begin(); 1380 } 1381 1382 /// \sa synthetic_stmt_begin synthetic_stmt_end()1383 synthetic_stmt_iterator synthetic_stmt_end() const { 1384 return SyntheticDeclStmts.end(); 1385 } 1386 1387 /// \sa synthetic_stmt_begin synthetic_stmts()1388 synthetic_stmt_range synthetic_stmts() const { 1389 return synthetic_stmt_range(synthetic_stmt_begin(), synthetic_stmt_end()); 1390 } 1391 1392 //===--------------------------------------------------------------------===// 1393 // Member templates useful for various batch operations over CFGs. 1394 //===--------------------------------------------------------------------===// 1395 VisitBlockStmts(Callback & O)1396 template <typename Callback> void VisitBlockStmts(Callback &O) const { 1397 for (CFGBlock *BB : *this) 1398 for (const CFGElement &Elem : *BB) { 1399 if (std::optional<CFGStmt> stmt = Elem.getAs<CFGStmt>()) 1400 O(const_cast<Stmt *>(stmt->getStmt())); 1401 } 1402 } 1403 1404 //===--------------------------------------------------------------------===// 1405 // CFG Introspection. 1406 //===--------------------------------------------------------------------===// 1407 1408 /// Returns the total number of BlockIDs allocated (which start at 0). getNumBlockIDs()1409 unsigned getNumBlockIDs() const { return NumBlockIDs; } 1410 1411 /// Return the total number of CFGBlocks within the CFG This is simply a 1412 /// renaming of the getNumBlockIDs(). This is necessary because the dominator 1413 /// implementation needs such an interface. size()1414 unsigned size() const { return NumBlockIDs; } 1415 1416 /// Returns true if the CFG has no branches. Usually it boils down to the CFG 1417 /// having exactly three blocks (entry, the actual code, exit), but sometimes 1418 /// more blocks appear due to having control flow that can be fully 1419 /// resolved in compile time. 1420 bool isLinear() const; 1421 1422 //===--------------------------------------------------------------------===// 1423 // CFG Debugging: Pretty-Printing and Visualization. 1424 //===--------------------------------------------------------------------===// 1425 1426 void viewCFG(const LangOptions &LO) const; 1427 void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const; 1428 void dump(const LangOptions &LO, bool ShowColors) const; 1429 1430 //===--------------------------------------------------------------------===// 1431 // Internal: constructors and data. 1432 //===--------------------------------------------------------------------===// 1433 CFG()1434 CFG() : Blocks(BlkBVC, 10) {} 1435 getAllocator()1436 llvm::BumpPtrAllocator& getAllocator() { 1437 return BlkBVC.getAllocator(); 1438 } 1439 getBumpVectorContext()1440 BumpVectorContext &getBumpVectorContext() { 1441 return BlkBVC; 1442 } 1443 1444 private: 1445 CFGBlock *Entry = nullptr; 1446 CFGBlock *Exit = nullptr; 1447 1448 // Special block to contain collective dispatch for indirect gotos 1449 CFGBlock* IndirectGotoBlock = nullptr; 1450 1451 unsigned NumBlockIDs = 0; 1452 1453 BumpVectorContext BlkBVC; 1454 1455 CFGBlockListTy Blocks; 1456 1457 /// C++ 'try' statements are modeled with an indirect dispatch block. 1458 /// This is the collection of such blocks present in the CFG. 1459 std::vector<const CFGBlock *> TryDispatchBlocks; 1460 1461 /// Collects DeclStmts synthesized for this CFG and maps each one back to its 1462 /// source DeclStmt. 1463 llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts; 1464 }; 1465 1466 Expr *extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE); 1467 1468 } // namespace clang 1469 1470 //===----------------------------------------------------------------------===// 1471 // GraphTraits specializations for CFG basic block graphs (source-level CFGs) 1472 //===----------------------------------------------------------------------===// 1473 1474 namespace llvm { 1475 1476 /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from 1477 /// CFGTerminator to a specific Stmt class. 1478 template <> struct simplify_type< ::clang::CFGTerminator> { 1479 using SimpleType = ::clang::Stmt *; 1480 1481 static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) { 1482 return Val.getStmt(); 1483 } 1484 }; 1485 1486 // Traits for: CFGBlock 1487 1488 template <> struct GraphTraits< ::clang::CFGBlock *> { 1489 using NodeRef = ::clang::CFGBlock *; 1490 using ChildIteratorType = ::clang::CFGBlock::succ_iterator; 1491 1492 static NodeRef getEntryNode(::clang::CFGBlock *BB) { return BB; } 1493 static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } 1494 static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } 1495 }; 1496 1497 template <> struct GraphTraits< const ::clang::CFGBlock *> { 1498 using NodeRef = const ::clang::CFGBlock *; 1499 using ChildIteratorType = ::clang::CFGBlock::const_succ_iterator; 1500 1501 static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; } 1502 static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } 1503 static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } 1504 }; 1505 1506 template <> struct GraphTraits<Inverse< ::clang::CFGBlock *>> { 1507 using NodeRef = ::clang::CFGBlock *; 1508 using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; 1509 1510 static NodeRef getEntryNode(Inverse<::clang::CFGBlock *> G) { 1511 return G.Graph; 1512 } 1513 1514 static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } 1515 static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } 1516 }; 1517 1518 template <> struct GraphTraits<Inverse<const ::clang::CFGBlock *>> { 1519 using NodeRef = const ::clang::CFGBlock *; 1520 using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; 1521 1522 static NodeRef getEntryNode(Inverse<const ::clang::CFGBlock *> G) { 1523 return G.Graph; 1524 } 1525 1526 static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } 1527 static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } 1528 }; 1529 1530 // Traits for: CFG 1531 1532 template <> struct GraphTraits< ::clang::CFG* > 1533 : public GraphTraits< ::clang::CFGBlock *> { 1534 using nodes_iterator = ::clang::CFG::iterator; 1535 1536 static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); } 1537 static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();} 1538 static nodes_iterator nodes_end(::clang::CFG* F) { return F->nodes_end(); } 1539 static unsigned size(::clang::CFG* F) { return F->size(); } 1540 }; 1541 1542 template <> struct GraphTraits<const ::clang::CFG* > 1543 : public GraphTraits<const ::clang::CFGBlock *> { 1544 using nodes_iterator = ::clang::CFG::const_iterator; 1545 1546 static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); } 1547 1548 static nodes_iterator nodes_begin( const ::clang::CFG* F) { 1549 return F->nodes_begin(); 1550 } 1551 1552 static nodes_iterator nodes_end( const ::clang::CFG* F) { 1553 return F->nodes_end(); 1554 } 1555 1556 static unsigned size(const ::clang::CFG* F) { 1557 return F->size(); 1558 } 1559 }; 1560 1561 template <> struct GraphTraits<Inverse< ::clang::CFG *>> 1562 : public GraphTraits<Inverse< ::clang::CFGBlock *>> { 1563 using nodes_iterator = ::clang::CFG::iterator; 1564 1565 static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); } 1566 static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();} 1567 static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); } 1568 }; 1569 1570 template <> struct GraphTraits<Inverse<const ::clang::CFG *>> 1571 : public GraphTraits<Inverse<const ::clang::CFGBlock *>> { 1572 using nodes_iterator = ::clang::CFG::const_iterator; 1573 1574 static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); } 1575 1576 static nodes_iterator nodes_begin(const ::clang::CFG* F) { 1577 return F->nodes_begin(); 1578 } 1579 1580 static nodes_iterator nodes_end(const ::clang::CFG* F) { 1581 return F->nodes_end(); 1582 } 1583 }; 1584 1585 } // namespace llvm 1586 1587 #endif // LLVM_CLANG_ANALYSIS_CFG_H 1588