aboutsummaryrefslogtreecommitdiffstats
path: root/include/clang/Analysis/CFG.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Analysis/CFG.h')
-rw-r--r--include/clang/Analysis/CFG.h195
1 files changed, 193 insertions, 2 deletions
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 277b2292e5ea..a8301a0e0063 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -121,6 +121,12 @@ public:
x |= Data1.getInt();
return (Kind) x;
}
+
+ void dumpToStream(llvm::raw_ostream &OS) const;
+
+ void dump() const {
+ dumpToStream(llvm::errs());
+ }
};
class CFGStmt : public CFGElement {
@@ -610,6 +616,153 @@ class CFGBlock {
bool empty() const { return Impl.empty(); }
};
+ /// A convenience class for comparing CFGElements, since methods of CFGBlock
+ /// like operator[] return CFGElements by value. This is practically a wrapper
+ /// around a (CFGBlock, Index) pair.
+ template <bool IsConst> class ElementRefImpl {
+
+ template <bool IsOtherConst> friend class ElementRefImpl;
+
+ using CFGBlockPtr =
+ typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
+
+ using CFGElementPtr = typename std::conditional<IsConst, const CFGElement *,
+ CFGElement *>::type;
+
+ protected:
+ CFGBlockPtr Parent;
+ size_t Index;
+
+ public:
+ ElementRefImpl(CFGBlockPtr Parent, size_t Index)
+ : Parent(Parent), Index(Index) {}
+
+ template <bool IsOtherConst>
+ ElementRefImpl(ElementRefImpl<IsOtherConst> Other)
+ : ElementRefImpl(Other.Parent, Other.Index) {}
+
+ size_t getIndexInBlock() const { return Index; }
+
+ CFGBlockPtr getParent() { return Parent; }
+ CFGBlockPtr getParent() const { return Parent; }
+
+ bool operator<(ElementRefImpl Other) const {
+ return std::make_pair(Parent, Index) <
+ std::make_pair(Other.Parent, Other.Index);
+ }
+
+ bool operator==(ElementRefImpl Other) const {
+ return Parent == Other.Parent && Index == Other.Index;
+ }
+
+ bool operator!=(ElementRefImpl Other) const { return !(*this == Other); }
+ CFGElement operator*() const { return (*Parent)[Index]; }
+ CFGElementPtr operator->() const { return &*(Parent->begin() + Index); }
+
+ void dumpToStream(llvm::raw_ostream &OS) const {
+ OS << getIndexInBlock() + 1 << ": ";
+ (*this)->dumpToStream(OS);
+ }
+
+ void dump() const {
+ dumpToStream(llvm::errs());
+ }
+ };
+
+ template <bool IsReverse, bool IsConst> class ElementRefIterator {
+
+ template <bool IsOtherReverse, bool IsOtherConst>
+ friend class ElementRefIterator;
+
+ using CFGBlockRef =
+ typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
+
+ using UnderlayingIteratorTy = typename std::conditional<
+ IsConst,
+ typename std::conditional<IsReverse,
+ ElementList::const_reverse_iterator,
+ ElementList::const_iterator>::type,
+ typename std::conditional<IsReverse, ElementList::reverse_iterator,
+ ElementList::iterator>::type>::type;
+
+ using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>;
+ using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>;
+
+ public:
+ using difference_type = typename IteratorTraits::difference_type;
+ using value_type = ElementRef;
+ using pointer = ElementRef *;
+ using iterator_category = typename IteratorTraits::iterator_category;
+
+ private:
+ CFGBlockRef Parent;
+ UnderlayingIteratorTy Pos;
+
+ public:
+ ElementRefIterator(CFGBlockRef Parent, UnderlayingIteratorTy Pos)
+ : Parent(Parent), Pos(Pos) {}
+
+ template <bool IsOtherConst>
+ ElementRefIterator(ElementRefIterator<false, IsOtherConst> E)
+ : ElementRefIterator(E.Parent, E.Pos.base()) {}
+
+ template <bool IsOtherConst>
+ ElementRefIterator(ElementRefIterator<true, IsOtherConst> E)
+ : ElementRefIterator(E.Parent, llvm::make_reverse_iterator(E.Pos)) {}
+
+ bool operator<(ElementRefIterator Other) const {
+ assert(Parent == Other.Parent);
+ return Pos < Other.Pos;
+ }
+
+ bool operator==(ElementRefIterator Other) const {
+ return Parent == Other.Parent && Pos == Other.Pos;
+ }
+
+ bool operator!=(ElementRefIterator Other) const {
+ return !(*this == Other);
+ }
+
+ private:
+ template <bool IsOtherConst>
+ static size_t
+ getIndexInBlock(CFGBlock::ElementRefIterator<true, IsOtherConst> E) {
+ return E.Parent->size() - (E.Pos - E.Parent->rbegin()) - 1;
+ }
+
+ template <bool IsOtherConst>
+ static size_t
+ getIndexInBlock(CFGBlock::ElementRefIterator<false, IsOtherConst> E) {
+ return E.Pos - E.Parent->begin();
+ }
+
+ public:
+ value_type operator*() { return {Parent, getIndexInBlock(*this)}; }
+
+ difference_type operator-(ElementRefIterator Other) const {
+ return Pos - Other.Pos;
+ }
+
+ ElementRefIterator operator++() {
+ ++this->Pos;
+ return *this;
+ }
+ ElementRefIterator operator++(int) {
+ ElementRefIterator Ret = *this;
+ ++*this;
+ return Ret;
+ }
+ ElementRefIterator operator+(size_t count) {
+ this->Pos += count;
+ return *this;
+ }
+ ElementRefIterator operator-(size_t count) {
+ this->Pos -= count;
+ return *this;
+ }
+ };
+
+public:
/// The set of statements in the basic block.
ElementList Elements;
@@ -715,6 +868,8 @@ public:
using reverse_iterator = ElementList::reverse_iterator;
using const_reverse_iterator = ElementList::const_reverse_iterator;
+ size_t getIndexInCFG() const;
+
CFGElement front() const { return Elements.front(); }
CFGElement back() const { return Elements.back(); }
@@ -728,6 +883,38 @@ public:
const_reverse_iterator rbegin() const { return Elements.rbegin(); }
const_reverse_iterator rend() const { return Elements.rend(); }
+ using CFGElementRef = ElementRefImpl<false>;
+ using ConstCFGElementRef = ElementRefImpl<true>;
+
+ using ref_iterator = ElementRefIterator<false, false>;
+ using ref_iterator_range = llvm::iterator_range<ref_iterator>;
+ using const_ref_iterator = ElementRefIterator<false, true>;
+ using const_ref_iterator_range = llvm::iterator_range<const_ref_iterator>;
+
+ using reverse_ref_iterator = ElementRefIterator<true, false>;
+ using reverse_ref_iterator_range = llvm::iterator_range<reverse_ref_iterator>;
+
+ using const_reverse_ref_iterator = ElementRefIterator<true, true>;
+ using const_reverse_ref_iterator_range =
+ llvm::iterator_range<const_reverse_ref_iterator>;
+
+ ref_iterator ref_begin() { return {this, begin()}; }
+ ref_iterator ref_end() { return {this, end()}; }
+ const_ref_iterator ref_begin() const { return {this, begin()}; }
+ const_ref_iterator ref_end() const { return {this, end()}; }
+
+ reverse_ref_iterator rref_begin() { return {this, rbegin()}; }
+ reverse_ref_iterator rref_end() { return {this, rend()}; }
+ const_reverse_ref_iterator rref_begin() const { return {this, rbegin()}; }
+ const_reverse_ref_iterator rref_end() const { return {this, rend()}; }
+
+ ref_iterator_range refs() { return {ref_begin(), ref_end()}; }
+ const_ref_iterator_range refs() const { return {ref_begin(), ref_end()}; }
+ reverse_ref_iterator_range rrefs() { return {rref_begin(), rref_end()}; }
+ const_reverse_ref_iterator_range rrefs() const {
+ return {rref_begin(), rref_end()};
+ }
+
unsigned size() const { return Elements.size(); }
bool empty() const { return Elements.empty(); }
@@ -855,6 +1042,10 @@ public:
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
void setHasNoReturnElement() { HasNoReturnElement = true; }
+ /// Returns true if the block would eventually end with a sink (a noreturn
+ /// node).
+ bool isInevitablySinking() const;
+
CFGTerminator getTerminator() const { return Terminator; }
Stmt *getTerminatorStmt() { return Terminator.getStmt(); }
@@ -894,7 +1085,7 @@ public:
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
bool AddQuotes) const;
-
+
void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
OS << "BB#" << getBlockID();
}
@@ -1010,7 +1201,6 @@ public:
*I = CFGScopeEnd(VD, S);
return ++I;
}
-
};
/// CFGCallback defines methods that should be called when a logical
@@ -1023,6 +1213,7 @@ public:
virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
virtual void compareBitwiseEquality(const BinaryOperator *B,
bool isAlwaysTrue) {}
+ virtual void compareBitwiseOr(const BinaryOperator *B) {}
};
/// Represents a source-level, intra-procedural CFG that represents the