14 #ifndef LLVM_CLANG_ANALYSIS_CFG_H 15 #define LLVM_CLANG_ANALYSIS_CFG_H 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/GraphTraits.h" 24 #include "llvm/ADT/None.h" 25 #include "llvm/ADT/Optional.h" 26 #include "llvm/ADT/PointerIntPair.h" 27 #include "llvm/ADT/iterator_range.h" 28 #include "llvm/Support/Allocator.h" 29 #include "llvm/Support/raw_ostream.h" 42 class CXXBaseSpecifier;
43 class CXXBindTemporaryExpr;
44 class CXXCtorInitializer;
46 class CXXDestructorDecl;
83 llvm::PointerIntPair<void *, 2>
Data1;
84 llvm::PointerIntPair<void *, 2>
Data2;
87 : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
88 Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {
99 assert(T::isKind(*
this));
110 if (!T::isKind(*
this))
119 unsigned x = Data2.getInt();
129 assert(isKind(*
this));
133 return static_cast<const Stmt *
>(
Data1.getPointer());
155 Data2.setPointer(const_cast<ConstructionContext *>(C));
183 assert(isa<CallExpr>(E) || isa<ObjCMessageExpr>(E));
193 assert(isCXXRecordTypedCall(E));
194 assert(C && (isa<TemporaryObjectConstructionContext>(C) ||
196 isa<ReturnedValueConstructionContext>(C) ||
197 isa<VariableConstructionContext>(C) ||
198 isa<ConstructorInitializerConstructionContext>(C) ||
199 isa<ArgumentConstructionContext>(C)));
200 Data2.setPointer(const_cast<ConstructionContext *>(C));
270 return static_cast<Stmt *
>(
Data1.getPointer());
294 return static_cast<Stmt *
>(
Data2.getPointer());
317 return static_cast<Stmt*
>(
Data2.getPointer());
345 return static_cast<Stmt *
>(
Data2.getPointer());
369 bool isNoReturn(
ASTContext &astContext)
const;
394 return static_cast<Stmt*
>(
Data2.getPointer());
515 NumKindsMinusOne = VirtualBaseBranch
519 static constexpr
int KindBits = 2;
520 static_assert((1 << KindBits) > NumKindsMinusOne,
521 "Not enough room for kind!");
522 llvm::PointerIntPair<Stmt *, KindBits> Data;
528 bool isValid()
const {
return Data.getOpaqueValue() !=
nullptr; }
534 return getKind() == StmtBranch;
537 return getKind() == TemporaryDtorsBranch;
540 return getKind() == VirtualBaseBranch;
579 using iterator = std::reverse_iterator<ImplTy::iterator>;
580 using const_iterator = std::reverse_iterator<ImplTy::const_iterator>;
583 using const_reference = ImplTy::const_reference;
589 return Impl.insert(I, Cnt, E, C);
592 const_reference front()
const {
return Impl.back(); }
593 const_reference back()
const {
return Impl.front(); }
595 iterator begin() {
return Impl.rbegin(); }
596 iterator end() {
return Impl.rend(); }
605 assert(i < Impl.size());
606 return Impl[Impl.size() - 1 -
i];
609 size_t size()
const {
return Impl.size(); }
610 bool empty()
const {
return Impl.empty(); }
614 ElementList Elements;
628 const Stmt *LoopTarget =
nullptr;
647 llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock;
659 return ReachableBlock;
664 return UnreachableBlock.getPointer();
670 return getReachableBlock();
674 return *getReachableBlock();
678 return getReachableBlock();
682 Kind K = (
Kind) UnreachableBlock.getInt();
683 return K == AB_Normal || K == AB_Alternate;
702 unsigned HasNoReturnElement : 1;
709 : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1),
710 Succs(C, 1), HasNoReturnElement(
false), Parent(parent) {}
731 unsigned size()
const {
return Elements.size(); }
732 bool empty()
const {
return Elements.empty(); }
800 : IgnoreNullPredecessors(1), IgnoreDefaultsWithCoveredEnums(0) {}
806 template <
typename IMPL,
bool IsPred>
817 : I(i), E(e), F(f), From(from) {
818 while (hasMore() &&
Filter(*I))
825 do { ++I; }
while (hasMore() &&
Filter(*I));
833 return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To);
869 const Expr *getLastCondition()
const;
891 void print(raw_ostream &OS,
const CFG* cfg,
const LangOptions &LO,
892 bool ShowColors)
const;
894 void printTerminator(raw_ostream &OS,
const LangOptions &LO)
const;
895 void printTerminatorJson(raw_ostream &Out,
const LangOptions &LO,
896 bool AddQuotes)
const;
899 OS <<
"BB#" << getBlockID();
906 Elements.push_back(
CFGStmt(statement), C);
945 Elements.insert(Elements.rbegin(), 1,
CFGScopeEnd(VD, S),
C);
981 return iterator(Elements.insert(I.base(), Cnt,
1007 Elements.insert(I.base(), Cnt,
CFGScopeEnd(
nullptr,
nullptr),
C));
1025 bool isAlwaysTrue) {}
1042 std::bitset<Stmt::lastStmtConstant> alwaysAddMask;
1049 bool PruneTriviallyFalseEdges =
true;
1050 bool AddEHEdges =
false;
1051 bool AddInitializers =
false;
1052 bool AddImplicitDtors =
false;
1053 bool AddLifetime =
false;
1054 bool AddLoopExit =
false;
1055 bool AddTemporaryDtors =
false;
1056 bool AddScopes =
false;
1057 bool AddStaticInitBranches =
false;
1058 bool AddCXXNewAllocator =
false;
1059 bool AddCXXDefaultInitExprInCtors =
false;
1060 bool AddRichCXXConstructors =
false;
1061 bool MarkElidedCXXConstructors =
false;
1062 bool AddVirtualBaseBranches =
false;
1071 alwaysAddMask[stmtClass] = val;
1076 alwaysAddMask.set();
1137 return TryDispatchBlocks.begin();
1141 return TryDispatchBlocks.end();
1145 TryDispatchBlocks.push_back(block);
1154 assert(Synthetic->
isSingleDecl() &&
"Can handle single declarations only");
1155 assert(Synthetic != Source &&
"Don't include original DeclStmts in map");
1156 assert(!SyntheticDeclStmts.count(Synthetic) &&
"Already in map");
1157 SyntheticDeclStmts[Synthetic] = Source;
1161 llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator;
1170 return SyntheticDeclStmts.begin();
1175 return SyntheticDeclStmts.end();
1187 template <
typename CALLBACK>
1193 O(const_cast<Stmt*>(
stmt->getStmt()));
1207 unsigned size()
const {
return NumBlockIDs; }
1213 bool isLinear()
const;
1220 void print(raw_ostream &OS,
const LangOptions &LO,
bool ShowColors)
const;
1230 return BlkBVC.getAllocator();
1242 CFGBlock* IndirectGotoBlock =
nullptr;
1244 unsigned NumBlockIDs = 0;
1252 std::vector<const CFGBlock *> TryDispatchBlocks;
1256 llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
1349 static NodeRef
getEntryNode(const ::clang::CFG *F) {
return &F->getEntry(); }
1352 return F->nodes_begin();
1356 return F->nodes_end();
1359 static unsigned size(const ::clang::CFG* F) {
1365 :
public GraphTraits<Inverse< ::clang::CFGBlock *>> {
1374 :
public GraphTraits<Inverse<const ::clang::CFGBlock *>> {
1377 static NodeRef
getEntryNode(const ::clang::CFG *F) {
return &F->getExit(); }
1380 return F->nodes_begin();
1384 return F->nodes_end();
1390 #endif // LLVM_CLANG_ANALYSIS_CFG_H void setIndirectGotoBlock(CFGBlock *B)
Set the block used for indirect goto jumps.
Represents C++ allocator call.
static NodeRef getEntryNode(::clang::CFG *F)
const_iterator end() const
succ_reverse_iterator succ_rbegin()
static unsigned size(const ::clang::CFG *F)
CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
AdjacentBlocks::const_iterator const_pred_iterator
iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const Stmt * getStmt() const
ElementList::iterator iterator
succ_iterator succ_begin()
const_pred_reverse_iterator pred_rend() const
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
CFGLifetimeEnds(const VarDecl *var, const Stmt *stmt)
Stmt - This represents one statement.
const_iterator nodes_end() const
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
void prependScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
unsigned getBlockID() const
Decl - This represents one declaration (or definition), e.g.
AdjacentBlocks::iterator succ_iterator
CFGTerminator(Stmt *S, Kind K=StmtBranch)
void appendNewAllocator(CXXNewExpr *NE, BumpVectorContext &C)
std::reverse_iterator< iterator > reverse_iterator
CFGNewAllocator(const CXXNewExpr *S)
CFGElement operator[](size_t i) const
void appendLifetimeEnds(VarDecl *VD, Stmt *S, BumpVectorContext &C)
llvm::BumpPtrAllocator & getAllocator()
static ChildIteratorType child_end(NodeRef N)
::clang::CFGBlock::succ_iterator ChildIteratorType
Represents C++ object destructor generated from a call to delete.
const Stmt * getLoopTarget() const
Represents a call to a C++ constructor.
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const Stmt * getTriggerStmt() const
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator
unsigned IgnoreDefaultsWithCoveredEnums
A shortcut around virtual base initializers.
void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
Represents a point when we exit a loop.
unsigned succ_size() const
static ChildIteratorType child_begin(NodeRef N)
reverse_iterator rbegin()
Represents a variable declaration or definition.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
static ChildIteratorType child_end(NodeRef N)
const ConstructionContext * getConstructionContext() const
synthetic_stmt_range synthetic_stmts() const
const_reverse_iterator rbegin() const
CFGBlock * getReachableBlock() const
Get the reachable block, if one exists.
const CFGBlock & getEntry() const
const Stmt * getTriggerStmt() const
const_succ_reverse_iterator succ_rbegin() const
Defines the clang::Expr interface and subclasses for C++ expressions.
const_pred_iterator pred_begin() const
std::reverse_iterator< iterator > reverse_iterator
Represents a function call that returns a C++ object by value.
const ConstructionContext * getConstructionContext() const
pred_const_range preds() const
const_reverse_iterator rend() const
std::vector< const CFGBlock * >::const_iterator try_block_iterator
CFGBlock * getPossiblyUnreachableBlock() const
Get the potentially unreachable block.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void setLoopTarget(const Stmt *loopTarget)
::clang::CFGBlock::const_pred_iterator ChildIteratorType
CFGScopeBegin(const VarDecl *VD, const Stmt *S)
static NodeRef getEntryNode(const clang::CFGBlock *BB)
Represents a member of a struct/union/class.
static ChildIteratorType child_end(NodeRef N)
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S)
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const Stmt * getTerminatorStmt() const
void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C)
const CXXRecordDecl * getCXXRecordDecl() const
const_iterator nodes_begin() const
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
void setTerminator(CFGTerminator Term)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
llvm::iterator_range< succ_iterator > succ_range
const_iterator begin() const
AdjacentBlocks::const_iterator const_succ_iterator
const_iterator end() const
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
AdjacentBlocks::iterator pred_iterator
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
A builtin binary operation expression such as "x + y" or "x <= y".
static NodeRef getEntryNode(::clang::CFGBlock *BB)
CFGBlockListTy::iterator iterator
const VarDecl * getVarDecl() const
const CXXBaseSpecifier * getBaseSpecifier() const
void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C)
const_succ_iterator succ_end() const
FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, const CFGBlock *from, const FilterOptions &f)
Represents binding an expression to a temporary.
CFGScopeEnd(const VarDecl *VD, const Stmt *S)
llvm::DenseMap< const DeclStmt *, const DeclStmt * >::const_iterator synthetic_stmt_iterator
static ChildIteratorType child_end(NodeRef N)
llvm::DenseMap< const Stmt *, const CFGBlock * > ForcedBlkExprs
CFGBlockListTy::const_iterator const_iterator
CXXCtorInitializer * getInitializer() const
void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, BumpVectorContext &C)
static nodes_iterator nodes_begin(::clang::CFG *F)
static ChildIteratorType child_begin(NodeRef N)
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const FieldDecl * getFieldDecl() const
const_iterator begin() const
const CXXBindTemporaryExpr * getBindTemporaryExpr() const
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C)
Represents a single basic block in a source-level CFG.
const VarDecl * getVarDecl() const
CFGCXXRecordTypedCall(Expr *E, const ConstructionContext *C)
::clang::CFG::const_iterator nodes_iterator
This represents one expression.
const_succ_iterator succ_begin() const
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
::clang::CFGBlock::const_succ_iterator ChildIteratorType
Represents a C++ destructor within a class.
CFGLoopExit(const Stmt *stmt)
Represents C++ constructor call.
const_reverse_iterator rend() const
ElementList::const_iterator const_iterator
bool isTemporaryDtorsBranch() const
static SimpleType getSimplifiedValue(::clang::CFGTerminator Val)
filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const
const_pred_iterator pred_end() const
succ_const_range succs() const
std::reverse_iterator< const_iterator > const_reverse_iterator
static NodeRef getEntryNode(Inverse< const ::clang::CFGBlock *> G)
Represents C++ object destructor implicitly generated for base object in destructor.
void addTryDispatchBlock(const CFGBlock *block)
reverse_iterator rbegin()
try_block_iterator try_blocks_begin() const
const_succ_reverse_iterator succ_rend() const
void appendStmt(Stmt *statement, BumpVectorContext &C)
QualType getCanonicalType() const
CFGImplicitDtor(Kind kind, const void *data1, const void *data2=nullptr)
pred_reverse_iterator pred_rend()
BuildOptions & setAlwaysAdd(Stmt::StmtClass stmtClass, bool val=true)
reverse_iterator rbegin()
::clang::CFGBlock::const_pred_iterator ChildIteratorType
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
void setLabel(Stmt *Statement)
iterator insertScopeEnd(iterator I, VarDecl *VD, Stmt *S)
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
llvm::iterator_range< const_succ_iterator > succ_const_range
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue)
succ_reverse_iterator succ_rend()
static NodeRef getEntryNode(::clang::CFG *F)
A branch in control flow of destructors of temporaries.
static bool isCXXRecordTypedCall(Expr *E)
Returns true when call expression CE needs to be represented by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
llvm::PointerIntPair< void *, 2 > Data1
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C)
BumpVectorContext & getBumpVectorContext()
void appendScopeBegin(const VarDecl *VD, const Stmt *S, BumpVectorContext &C)
static ChildIteratorType child_begin(NodeRef N)
BuildOptions & setAllAlwaysAdd()
const_pred_reverse_iterator pred_rbegin() const
bool isStmtBranch() const
Represents end of a scope implicitly generated by the compiler after the last Stmt in a CompoundStmt'...
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
FilteredCFGBlockIterator & operator++()
const Stmt * getTerminatorCondition(bool StripParens=true) const
static NodeRef getEntryNode(const ::clang::CFG *F)
pred_iterator pred_begin()
static NodeRef getEntryNode(Inverse<::clang::CFGBlock *> G)
const VarDecl * getVarDecl() const
std::reverse_iterator< const_iterator > const_reverse_iterator
Dataflow Directional Tag Classes.
llvm::PointerIntPair< void *, 2 > Data2
void VisitBlockStmts(CALLBACK &O) const
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
static nodes_iterator nodes_begin(const ::clang::CFG *F)
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue)
const VarDecl * getVarDecl() const
llvm::iterator_range< const_pred_iterator > pred_const_range
static nodes_iterator nodes_begin(const ::clang::CFG *F)
void appendCXXRecordTypedCall(Expr *E, const ConstructionContext *CC, BumpVectorContext &C)
static unsigned size(::clang::CFG *F)
unsigned pred_size() const
A branch that corresponds to a statement in the code, such as an if-statement.
StmtClass getStmtClass() const
void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C)
bool isVirtualBaseBranch() const
Stmt * getTerminatorStmt()
static nodes_iterator nodes_begin(::clang::CFG *F)
void appendMemberDtor(FieldDecl *FD, BumpVectorContext &C)
void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C)
static const Stmt * getTerminatorCondition(const CFGBlock *B)
A customized wrapper for CFGBlock::getTerminatorCondition() which returns the element for ObjCForColl...
This class represents a potential adjacent block in the CFG.
CFGInitializer(CXXCtorInitializer *initializer)
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
const Stmt * getLoopStmt() const
static nodes_iterator nodes_end(const ::clang::CFG *F)
Represents the point where the lifetime of an automatic object ends.
::clang::CFG::iterator nodes_iterator
const CXXDeleteExpr * getDeleteExpr() const
pred_reverse_iterator pred_rbegin()
CFGBlock * getIndirectGotoBlock()
const CFGBlock * operator*() const
bool alwaysAdd(const Stmt *stmt) const
try_block_iterator try_blocks_end() const
Represents a C++ base or member initializer.
const CFGBlock * getIndirectGotoBlock() const
AdjacentBlocks::reverse_iterator succ_reverse_iterator
iterator insertLifetimeEnds(iterator I, VarDecl *VD, Stmt *S)
AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator
Represents a base class of a C++ class.
::clang::CFG::iterator nodes_iterator
CFGElement(Kind kind, const void *Ptr1, const void *Ptr2=nullptr)
CFGStmt(Stmt *S, Kind K=Statement)
unsigned IgnoreNullPredecessors
bool hasNoReturnElement() const
void setHasNoReturnElement()
CFGMemberDtor(const FieldDecl *field)
const CXXNewExpr * getAllocatorExpr() const
static nodes_iterator nodes_end(::clang::CFG *F)
ConstructionContext's subclasses describe different ways of constructing an object in C++...
void printAsOperand(raw_ostream &OS, bool)
Represents a C++ struct/union/class.
llvm::iterator_range< synthetic_stmt_iterator > synthetic_stmt_range
CFGCallback defines methods that should be called when a logical operator error is found when buildin...
static nodes_iterator nodes_end(const ::clang::CFG *F)
llvm::iterator_range< pred_iterator > pred_range
Represents C++ object destructor implicitly generated by compiler on various occasions.
Represents a top-level expression in a basic block.
const CFGBlock & getExit() const
const Stmt * getStmt() const
static NodeRef getEntryNode(const ::clang::CFG *F)
unsigned kind
All of the diagnostics that can be emitted by the frontend.
synthetic_stmt_iterator synthetic_stmt_end() const
Represents CFGBlock terminator statement.
Represents C++ object destructor implicitly generated for member object in destructor.
AdjacentBlocks::reverse_iterator pred_reverse_iterator
void appendTemporaryDtor(CXXBindTemporaryExpr *E, BumpVectorContext &C)
synthetic_stmt_iterator synthetic_stmt_begin() const
Iterates over synthetic DeclStmts in the CFG.
const Stmt * getTriggerStmt() const
const Stmt * getTriggerStmt() const
CFGBaseDtor(const CXXBaseSpecifier *base)
const AdjacentBlock * const_iterator
Represents C++ base or member initializer from constructor's initialization list. ...
const_reverse_iterator rbegin() const
filtered_succ_iterator filtered_succ_start_end(const FilterOptions &f) const
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
CFGTerminator getTerminator() const
const Stmt * getLabel() const
void setEntry(CFGBlock *B)
Set the entry block of the CFG.
iterator beginLifetimeEndsInsert(iterator I, size_t Cnt, BumpVectorContext &C)
void addSyntheticDeclStmt(const DeclStmt *Synthetic, const DeclStmt *Source)
Records a synthetic DeclStmt and the DeclStmt it was constructed from.
::clang::CFG::const_iterator nodes_iterator
Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...
static nodes_iterator nodes_end(::clang::CFG *F)
static ChildIteratorType child_begin(NodeRef N)
Represents beginning of a scope implicitly generated by the compiler on encountering a CompoundStmt...
Represents the point where a loop ends.