File indexing completed on 2026-05-10 08:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
0015 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_VALUE_H
0016
0017 #include "clang/AST/Decl.h"
0018 #include "clang/Analysis/FlowSensitive/Formula.h"
0019 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
0020 #include "llvm/ADT/DenseMap.h"
0021 #include "llvm/ADT/StringMap.h"
0022 #include "llvm/ADT/StringRef.h"
0023 #include <cassert>
0024 #include <utility>
0025
0026 namespace clang {
0027 namespace dataflow {
0028
0029
0030
0031
0032
0033 class Value {
0034 public:
0035 enum class Kind {
0036 Integer,
0037 Pointer,
0038
0039
0040 TopBool,
0041 AtomicBool,
0042 FormulaBool,
0043 };
0044
0045 explicit Value(Kind ValKind) : ValKind(ValKind) {}
0046
0047
0048
0049
0050 Value(const Value &) = delete;
0051 Value &operator=(const Value &) = delete;
0052
0053 virtual ~Value() = default;
0054
0055 Kind getKind() const { return ValKind; }
0056
0057
0058
0059 Value *getProperty(llvm::StringRef Name) const {
0060 return Properties.lookup(Name);
0061 }
0062
0063
0064
0065
0066
0067
0068 void setProperty(llvm::StringRef Name, Value &Val) {
0069 Properties.insert_or_assign(Name, &Val);
0070 }
0071
0072 llvm::iterator_range<llvm::StringMap<Value *>::const_iterator>
0073 properties() const {
0074 return {Properties.begin(), Properties.end()};
0075 }
0076
0077 private:
0078 Kind ValKind;
0079 llvm::StringMap<Value *> Properties;
0080 };
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 bool areEquivalentValues(const Value &Val1, const Value &Val2);
0092
0093
0094 class BoolValue : public Value {
0095 const Formula *F;
0096
0097 public:
0098 explicit BoolValue(Kind ValueKind, const Formula &F)
0099 : Value(ValueKind), F(&F) {}
0100
0101 static bool classof(const Value *Val) {
0102 return Val->getKind() == Kind::TopBool ||
0103 Val->getKind() == Kind::AtomicBool ||
0104 Val->getKind() == Kind::FormulaBool;
0105 }
0106
0107 const Formula &formula() const { return *F; }
0108 };
0109
0110
0111
0112
0113
0114
0115
0116 class TopBoolValue final : public BoolValue {
0117 public:
0118 TopBoolValue(const Formula &F) : BoolValue(Kind::TopBool, F) {
0119 assert(F.kind() == Formula::AtomRef);
0120 }
0121
0122 static bool classof(const Value *Val) {
0123 return Val->getKind() == Kind::TopBool;
0124 }
0125
0126 Atom getAtom() const { return formula().getAtom(); }
0127 };
0128
0129
0130
0131
0132
0133 class AtomicBoolValue final : public BoolValue {
0134 public:
0135 explicit AtomicBoolValue(const Formula &F) : BoolValue(Kind::AtomicBool, F) {
0136 assert(F.kind() == Formula::AtomRef);
0137 }
0138
0139 static bool classof(const Value *Val) {
0140 return Val->getKind() == Kind::AtomicBool;
0141 }
0142
0143 Atom getAtom() const { return formula().getAtom(); }
0144 };
0145
0146
0147 class FormulaBoolValue final : public BoolValue {
0148 public:
0149 explicit FormulaBoolValue(const Formula &F)
0150 : BoolValue(Kind::FormulaBool, F) {
0151 assert(F.kind() != Formula::AtomRef && "For now, use AtomicBoolValue");
0152 }
0153
0154 static bool classof(const Value *Val) {
0155 return Val->getKind() == Kind::FormulaBool;
0156 }
0157 };
0158
0159
0160 class IntegerValue : public Value {
0161 public:
0162 explicit IntegerValue() : Value(Kind::Integer) {}
0163
0164 static bool classof(const Value *Val) {
0165 return Val->getKind() == Kind::Integer;
0166 }
0167 };
0168
0169
0170 class PointerValue final : public Value {
0171 public:
0172 explicit PointerValue(StorageLocation &PointeeLoc)
0173 : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
0174
0175 static bool classof(const Value *Val) {
0176 return Val->getKind() == Kind::Pointer;
0177 }
0178
0179 StorageLocation &getPointeeLoc() const { return PointeeLoc; }
0180
0181 private:
0182 StorageLocation &PointeeLoc;
0183 };
0184
0185 raw_ostream &operator<<(raw_ostream &OS, const Value &Val);
0186
0187 }
0188 }
0189
0190 #endif