File indexing completed on 2026-05-10 08:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_FORMULA_H
0010 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_FORMULA_H
0011
0012 #include "clang/Basic/LLVM.h"
0013 #include "llvm/ADT/ArrayRef.h"
0014 #include "llvm/ADT/DenseMap.h"
0015 #include "llvm/ADT/DenseMapInfo.h"
0016 #include "llvm/Support/Allocator.h"
0017 #include "llvm/Support/raw_ostream.h"
0018 #include <cassert>
0019 #include <string>
0020
0021 namespace clang::dataflow {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 enum class Atom : unsigned {};
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 class Formula;
0049 class alignas(const Formula *) Formula {
0050 public:
0051 enum Kind : unsigned {
0052
0053
0054 AtomRef,
0055
0056 Literal,
0057
0058 Not,
0059
0060
0061 And,
0062 Or,
0063 Implies,
0064 Equal,
0065 };
0066 Kind kind() const { return FormulaKind; }
0067
0068 Atom getAtom() const {
0069 assert(kind() == AtomRef);
0070 return static_cast<Atom>(Value);
0071 }
0072
0073 bool literal() const {
0074 assert(kind() == Literal);
0075 return static_cast<bool>(Value);
0076 }
0077
0078 bool isLiteral(bool b) const {
0079 return kind() == Literal && static_cast<bool>(Value) == b;
0080 }
0081
0082 ArrayRef<const Formula *> operands() const {
0083 return ArrayRef(reinterpret_cast<Formula *const *>(this + 1),
0084 numOperands(kind()));
0085 }
0086
0087 using AtomNames = llvm::DenseMap<Atom, std::string>;
0088
0089
0090
0091 void print(llvm::raw_ostream &OS, const AtomNames * = nullptr) const;
0092
0093
0094 static const Formula &create(llvm::BumpPtrAllocator &Alloc, Kind K,
0095 ArrayRef<const Formula *> Operands,
0096 unsigned Value = 0);
0097
0098 private:
0099 Formula() = default;
0100 Formula(const Formula &) = delete;
0101 Formula &operator=(const Formula &) = delete;
0102
0103 static unsigned numOperands(Kind K) {
0104 switch (K) {
0105 case AtomRef:
0106 case Literal:
0107 return 0;
0108 case Not:
0109 return 1;
0110 case And:
0111 case Or:
0112 case Implies:
0113 case Equal:
0114 return 2;
0115 }
0116 llvm_unreachable("Unhandled Formula::Kind enum");
0117 }
0118
0119 Kind FormulaKind;
0120
0121 unsigned Value;
0122 };
0123
0124
0125 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Atom A) {
0126 return OS << 'V' << static_cast<unsigned>(A);
0127 }
0128 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Formula &F) {
0129 F.print(OS);
0130 return OS;
0131 }
0132
0133 }
0134 namespace llvm {
0135 template <> struct DenseMapInfo<clang::dataflow::Atom> {
0136 using Atom = clang::dataflow::Atom;
0137 using Underlying = std::underlying_type_t<Atom>;
0138
0139 static inline Atom getEmptyKey() { return Atom(Underlying(-1)); }
0140 static inline Atom getTombstoneKey() { return Atom(Underlying(-2)); }
0141 static unsigned getHashValue(const Atom &Val) {
0142 return DenseMapInfo<Underlying>::getHashValue(Underlying(Val));
0143 }
0144 static bool isEqual(const Atom &LHS, const Atom &RHS) { return LHS == RHS; }
0145 };
0146 }
0147 #endif