summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/include/clang/Analysis/CFG.h')
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFG.h167
1 files changed, 136 insertions, 31 deletions
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
index 14b7ab8..891fb90 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
@@ -21,13 +21,14 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
#include <bitset>
#include <cassert>
#include <iterator>
+#include <memory>
namespace clang {
class CXXDestructorDecl;
@@ -45,6 +46,8 @@ namespace clang {
class ASTContext;
class CXXRecordDecl;
class CXXDeleteExpr;
+ class CXXNewExpr;
+ class BinaryOperator;
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
@@ -53,6 +56,7 @@ public:
// main kind
Statement,
Initializer,
+ NewAllocator,
// dtor kind
AutomaticObjectDtor,
DeleteDtor,
@@ -68,9 +72,11 @@ protected:
llvm::PointerIntPair<void *, 2> Data1;
llvm::PointerIntPair<void *, 2> Data2;
- CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0)
+ CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr)
: Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
- Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {}
+ Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {
+ assert(getKind() == kind);
+ }
CFGElement() {}
public:
@@ -141,12 +147,31 @@ private:
}
};
+/// CFGNewAllocator - Represents C++ allocator call.
+class CFGNewAllocator : public CFGElement {
+public:
+ explicit CFGNewAllocator(const CXXNewExpr *S)
+ : CFGElement(NewAllocator, S) {}
+
+ // Get the new expression.
+ const CXXNewExpr *getAllocatorExpr() const {
+ return static_cast<CXXNewExpr *>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGNewAllocator() {}
+ static bool isKind(const CFGElement &elem) {
+ return elem.getKind() == NewAllocator;
+ }
+};
+
/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
protected:
CFGImplicitDtor() {}
- CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0)
+ CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr)
: CFGElement(kind, data1, data2) {
assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
}
@@ -237,7 +262,7 @@ private:
class CFGMemberDtor : public CFGImplicitDtor {
public:
CFGMemberDtor(const FieldDecl *field)
- : CFGImplicitDtor(MemberDtor, field, 0) {}
+ : CFGImplicitDtor(MemberDtor, field, nullptr) {}
const FieldDecl *getFieldDecl() const {
return static_cast<const FieldDecl*>(Data1.getPointer());
@@ -256,7 +281,7 @@ private:
class CFGTemporaryDtor : public CFGImplicitDtor {
public:
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
- : CFGImplicitDtor(TemporaryDtor, expr, 0) {}
+ : CFGImplicitDtor(TemporaryDtor, expr, nullptr) {}
const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer());
@@ -388,9 +413,64 @@ class CFGBlock {
/// of the CFG.
unsigned BlockID;
+public:
+ /// This class represents a potential adjacent block in the CFG. It encodes
+ /// whether or not the block is actually reachable, or can be proved to be
+ /// trivially unreachable. For some cases it allows one to encode scenarios
+ /// where a block was substituted because the original (now alternate) block
+ /// is unreachable.
+ class AdjacentBlock {
+ enum Kind {
+ AB_Normal,
+ AB_Unreachable,
+ AB_Alternate
+ };
+
+ CFGBlock *ReachableBlock;
+ llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock;
+
+ public:
+ /// Construct an AdjacentBlock with a possibly unreachable block.
+ AdjacentBlock(CFGBlock *B, bool IsReachable);
+
+ /// Construct an AdjacentBlock with a reachable block and an alternate
+ /// unreachable block.
+ AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);
+
+ /// Get the reachable block, if one exists.
+ CFGBlock *getReachableBlock() const {
+ return ReachableBlock;
+ }
+
+ /// Get the potentially unreachable block.
+ CFGBlock *getPossiblyUnreachableBlock() const {
+ return UnreachableBlock.getPointer();
+ }
+
+ /// Provide an implicit conversion to CFGBlock* so that
+ /// AdjacentBlock can be substituted for CFGBlock*.
+ operator CFGBlock*() const {
+ return getReachableBlock();
+ }
+
+ CFGBlock& operator *() const {
+ return *getReachableBlock();
+ }
+
+ CFGBlock* operator ->() const {
+ return getReachableBlock();
+ }
+
+ bool isReachable() const {
+ Kind K = (Kind) UnreachableBlock.getInt();
+ return K == AB_Normal || K == AB_Alternate;
+ }
+ };
+
+private:
/// Predecessors/Successors - Keep track of the predecessor / successor
/// CFG blocks.
- typedef BumpVector<CFGBlock*> AdjacentBlocks;
+ typedef BumpVector<AdjacentBlock> AdjacentBlocks;
AdjacentBlocks Preds;
AdjacentBlocks Succs;
@@ -410,7 +490,7 @@ class CFGBlock {
public:
explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
- : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
+ : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr),
BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false),
Parent(parent) {}
~CFGBlock() {}
@@ -480,9 +560,11 @@ public:
class FilterOptions {
public:
FilterOptions() {
+ IgnoreNullPredecessors = 1;
IgnoreDefaultsWithCoveredEnums = 0;
}
+ unsigned IgnoreNullPredecessors : 1;
unsigned IgnoreDefaultsWithCoveredEnums : 1;
};
@@ -495,11 +577,14 @@ public:
IMPL I, E;
const FilterOptions F;
const CFGBlock *From;
- public:
+ public:
explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
- const CFGBlock *from,
- const FilterOptions &f)
- : I(i), E(e), F(f), From(from) {}
+ const CFGBlock *from,
+ const FilterOptions &f)
+ : I(i), E(e), F(f), From(from) {
+ while (hasMore() && Filter(*I))
+ ++I;
+ }
bool hasMore() const { return I != E; }
@@ -531,7 +616,7 @@ public:
// Manipulation of block contents
- void setTerminator(Stmt *Statement) { Terminator = Statement; }
+ void setTerminator(CFGTerminator Term) { Terminator = Term; }
void setLabel(Stmt *Statement) { Label = Statement; }
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
void setHasNoReturnElement() { HasNoReturnElement = true; }
@@ -539,10 +624,10 @@ public:
CFGTerminator getTerminator() { return Terminator; }
const CFGTerminator getTerminator() const { return Terminator; }
- Stmt *getTerminatorCondition();
+ Stmt *getTerminatorCondition(bool StripParens = true);
- const Stmt *getTerminatorCondition() const {
- return const_cast<CFGBlock*>(this)->getTerminatorCondition();
+ const Stmt *getTerminatorCondition(bool StripParens = true) const {
+ return const_cast<CFGBlock*>(this)->getTerminatorCondition(StripParens);
}
const Stmt *getLoopTarget() const { return LoopTarget; }
@@ -556,17 +641,19 @@ public:
CFG *getParent() const { return Parent; }
+ void dump() const;
+
void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
bool ShowColors) const;
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
-
- void addSuccessor(CFGBlock *Block, BumpVectorContext &C) {
- if (Block)
- Block->Preds.push_back(this, C);
- Succs.push_back(Block, C);
+ void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
+ OS << "BB#" << getBlockID();
}
+ /// Adds a (potentially unreachable) successor block to the current block.
+ void addSuccessor(AdjacentBlock Succ, BumpVectorContext &C);
+
void appendStmt(Stmt *statement, BumpVectorContext &C) {
Elements.push_back(CFGStmt(statement), C);
}
@@ -576,6 +663,11 @@ public:
Elements.push_back(CFGInitializer(initializer), C);
}
+ void appendNewAllocator(CXXNewExpr *NE,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGNewAllocator(NE), C);
+ }
+
void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
Elements.push_back(CFGBaseDtor(BS), C);
}
@@ -601,7 +693,8 @@ public:
// the elements beginning at the last position in prepared space.
iterator beginAutomaticObjDtorsInsert(iterator I, size_t Cnt,
BumpVectorContext &C) {
- return iterator(Elements.insert(I.base(), Cnt, CFGAutomaticObjDtor(0, 0), C));
+ return iterator(Elements.insert(I.base(), Cnt,
+ CFGAutomaticObjDtor(nullptr, 0), C));
}
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) {
*I = CFGAutomaticObjDtor(VD, S);
@@ -609,6 +702,17 @@ public:
}
};
+/// \brief CFGCallback defines methods that should be called when a logical
+/// operator error is found when building the CFG.
+class CFGCallback {
+public:
+ CFGCallback() {}
+ virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
+ virtual void compareBitwiseEquality(const BinaryOperator *B,
+ bool isAlwaysTrue) {}
+ virtual ~CFGCallback() {}
+};
+
/// CFG - Represents a source-level, intra-procedural CFG that represents the
/// control-flow of a Stmt. The Stmt can represent an entire function body,
/// or a single expression. A CFG will always contain one empty block that
@@ -627,13 +731,14 @@ public:
public:
typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs;
ForcedBlkExprs **forcedBlkExprs;
-
+ CFGCallback *Observer;
bool PruneTriviallyFalseEdges;
bool AddEHEdges;
bool AddInitializers;
bool AddImplicitDtors;
bool AddTemporaryDtors;
bool AddStaticInitBranches;
+ bool AddCXXNewAllocator;
bool alwaysAdd(const Stmt *stmt) const {
return alwaysAddMask[stmt->getStmtClass()];
@@ -650,12 +755,11 @@ public:
}
BuildOptions()
- : forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
- ,AddEHEdges(false)
- ,AddInitializers(false)
- ,AddImplicitDtors(false)
- ,AddTemporaryDtors(false)
- ,AddStaticInitBranches(false) {}
+ : forcedBlkExprs(nullptr), Observer(nullptr),
+ PruneTriviallyFalseEdges(true), AddEHEdges(false),
+ AddInitializers(false), AddImplicitDtors(false),
+ AddTemporaryDtors(false), AddStaticInitBranches(false),
+ AddCXXNewAllocator(false) {}
};
/// \brief Provides a custom implementation of the iterator class to have the
@@ -845,8 +949,9 @@ public:
// Internal: constructors and data.
//===--------------------------------------------------------------------===//
- CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
- Blocks(BlkBVC, 10) {}
+ CFG()
+ : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0),
+ Blocks(BlkBVC, 10) {}
llvm::BumpPtrAllocator& getAllocator() {
return BlkBVC.getAllocator();
OpenPOWER on IntegriCloud