File indexing completed on 2026-05-10 08:36:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
0014 #define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
0015
0016 #include "clang/Analysis/AnalysisDeclContext.h"
0017 #include "clang/Analysis/CFG.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "llvm/ADT/BitVector.h"
0020 #include "llvm/ADT/DenseMap.h"
0021 #include "llvm/ADT/PostOrderIterator.h"
0022 #include <utility>
0023 #include <vector>
0024
0025 namespace clang {
0026
0027 class PostOrderCFGView : public ManagedAnalysis {
0028 virtual void anchor();
0029
0030 public:
0031
0032
0033
0034
0035
0036
0037 class CFGBlockSet {
0038 llvm::BitVector VisitedBlockIDs;
0039
0040 public:
0041
0042
0043 struct iterator { using value_type = const CFGBlock *; };
0044
0045 CFGBlockSet() = default;
0046 CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
0047
0048
0049
0050 std::pair<std::nullopt_t, bool> insert(const CFGBlock *Block) {
0051
0052
0053
0054
0055 if (!Block)
0056 return std::make_pair(std::nullopt,
0057 false);
0058 if (VisitedBlockIDs.test(Block->getBlockID()))
0059 return std::make_pair(std::nullopt, false);
0060 VisitedBlockIDs.set(Block->getBlockID());
0061 return std::make_pair(std::nullopt, true);
0062 }
0063
0064
0065
0066
0067 bool alreadySet(const CFGBlock *Block) {
0068 return VisitedBlockIDs.test(Block->getBlockID());
0069 }
0070 };
0071
0072 private:
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 struct CFGLoopBodyFirstTraits {
0084 using NodeRef = const ::clang::CFGBlock *;
0085 using ChildIteratorType = ::clang::CFGBlock::const_succ_reverse_iterator;
0086
0087 static ChildIteratorType child_begin(NodeRef N) { return N->succ_rbegin(); }
0088 static ChildIteratorType child_end(NodeRef N) { return N->succ_rend(); }
0089
0090 using nodes_iterator = ::clang::CFG::const_iterator;
0091
0092 static NodeRef getEntryNode(const ::clang::CFG *F) {
0093 return &F->getEntry();
0094 }
0095
0096 static nodes_iterator nodes_begin(const ::clang::CFG *F) {
0097 return F->nodes_begin();
0098 }
0099
0100 static nodes_iterator nodes_end(const ::clang::CFG *F) {
0101 return F->nodes_end();
0102 }
0103
0104 static unsigned size(const ::clang::CFG *F) { return F->size(); }
0105 };
0106 using po_iterator =
0107 llvm::po_iterator<const CFG *, CFGBlockSet, true, CFGLoopBodyFirstTraits>;
0108 std::vector<const CFGBlock *> Blocks;
0109
0110 using BlockOrderTy = llvm::DenseMap<const CFGBlock *, unsigned>;
0111 BlockOrderTy BlockOrder;
0112
0113 public:
0114 friend struct BlockOrderCompare;
0115
0116 using iterator = std::vector<const CFGBlock *>::reverse_iterator;
0117 using const_iterator = std::vector<const CFGBlock *>::const_reverse_iterator;
0118
0119 PostOrderCFGView(const CFG *cfg);
0120
0121 iterator begin() { return Blocks.rbegin(); }
0122 iterator end() { return Blocks.rend(); }
0123
0124 const_iterator begin() const { return Blocks.rbegin(); }
0125 const_iterator end() const { return Blocks.rend(); }
0126
0127 bool empty() const { return begin() == end(); }
0128
0129 struct BlockOrderCompare {
0130 const PostOrderCFGView &POV;
0131
0132 public:
0133 BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {}
0134
0135 bool operator()(const CFGBlock *b1, const CFGBlock *b2) const;
0136 };
0137
0138 BlockOrderCompare getComparator() const {
0139 return BlockOrderCompare(*this);
0140 }
0141
0142
0143 static const void *getTag();
0144
0145 static std::unique_ptr<PostOrderCFGView>
0146 create(AnalysisDeclContext &analysisContext);
0147 };
0148
0149 }
0150
0151 #endif