File indexing completed on 2026-05-10 08:37:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
0017 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
0018
0019 #include "llvm/ADT/ImmutableList.h"
0020 #include "llvm/ADT/ImmutableMap.h"
0021 #include "llvm/ADT/ImmutableSet.h"
0022 #include "llvm/Support/Allocator.h"
0023 #include <cstdint>
0024 #include <type_traits>
0025
0026 namespace clang {
0027 namespace ento {
0028
0029 template <typename T, typename Enable = void> struct ProgramStatePartialTrait;
0030
0031
0032
0033
0034 #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
0035 namespace { \
0036 class Name {}; \
0037 using Name##Ty = Type; \
0038 } \
0039 namespace clang { \
0040 namespace ento { \
0041 template <> \
0042 struct ProgramStateTrait<Name> : public ProgramStatePartialTrait<Name##Ty> { \
0043 static void *GDMIndex() { \
0044 static int Index; \
0045 return &Index; \
0046 } \
0047 }; \
0048 } \
0049 }
0050
0051
0052
0053
0054
0055 #define REGISTER_FACTORY_WITH_PROGRAMSTATE(Type) \
0056 namespace clang { \
0057 namespace ento { \
0058 template <> \
0059 struct ProgramStateTrait<Type> \
0060 : public ProgramStatePartialTrait<Type> { \
0061 static void *GDMIndex() { static int Index; return &Index; } \
0062 }; \
0063 } \
0064 }
0065
0066
0067
0068
0069
0070
0071
0072
0073 #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \
0088 REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \
0089 CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value))
0090
0091
0092
0093
0094
0095 #define REGISTER_MAP_FACTORY_WITH_PROGRAMSTATE(Name, Key, Value) \
0096 using Name = llvm::ImmutableMap<Key, Value>; \
0097 REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \
0113 REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>)
0114
0115
0116
0117
0118
0119 #define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \
0120 using Name = llvm::ImmutableSet<Elem>; \
0121 REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135 #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \
0136 REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>)
0137
0138
0139
0140
0141
0142 #define REGISTER_LIST_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \
0143 using Name = llvm::ImmutableList<Elem>; \
0144 REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
0145
0146
0147
0148 template <typename Key, typename Data, typename Info>
0149 struct ProgramStatePartialTrait<llvm::ImmutableMap<Key, Data, Info>> {
0150 using data_type = llvm::ImmutableMap<Key, Data, Info>;
0151 using context_type = typename data_type::Factory &;
0152 using key_type = Key;
0153 using value_type = Data;
0154 using lookup_type = const value_type *;
0155
0156 static data_type MakeData(void *const *p) {
0157 return p ? data_type((typename data_type::TreeTy *) *p)
0158 : data_type(nullptr);
0159 }
0160
0161 static void *MakeVoidPtr(data_type B) {
0162 return B.getRoot();
0163 }
0164
0165 static lookup_type Lookup(data_type B, key_type K) {
0166 return B.lookup(K);
0167 }
0168
0169 static data_type Set(data_type B, key_type K, value_type E,
0170 context_type F) {
0171 return F.add(B, K, E);
0172 }
0173
0174 static data_type Remove(data_type B, key_type K, context_type F) {
0175 return F.remove(B, K);
0176 }
0177
0178 static bool Contains(data_type B, key_type K) {
0179 return B.contains(K);
0180 }
0181
0182 static context_type MakeContext(void *p) {
0183 return *((typename data_type::Factory *) p);
0184 }
0185
0186 static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
0187 return new typename data_type::Factory(Alloc);
0188 }
0189
0190 static void DeleteContext(void *Ctx) {
0191 delete (typename data_type::Factory *) Ctx;
0192 }
0193 };
0194
0195
0196 template <typename Key, typename Info>
0197 struct ProgramStatePartialTrait<llvm::ImmutableSet<Key, Info>> {
0198 using data_type = llvm::ImmutableSet<Key, Info>;
0199 using context_type = typename data_type::Factory &;
0200 using key_type = Key;
0201
0202 static data_type MakeData(void *const *p) {
0203 return p ? data_type((typename data_type::TreeTy *) *p)
0204 : data_type(nullptr);
0205 }
0206
0207 static void *MakeVoidPtr(data_type B) {
0208 return B.getRoot();
0209 }
0210
0211 static data_type Add(data_type B, key_type K, context_type F) {
0212 return F.add(B, K);
0213 }
0214
0215 static data_type Remove(data_type B, key_type K, context_type F) {
0216 return F.remove(B, K);
0217 }
0218
0219 static bool Contains(data_type B, key_type K) {
0220 return B.contains(K);
0221 }
0222
0223 static context_type MakeContext(void *p) {
0224 return *((typename data_type::Factory *) p);
0225 }
0226
0227 static void *CreateContext(llvm::BumpPtrAllocator &Alloc) {
0228 return new typename data_type::Factory(Alloc);
0229 }
0230
0231 static void DeleteContext(void *Ctx) {
0232 delete (typename data_type::Factory *) Ctx;
0233 }
0234 };
0235
0236
0237 template <typename T>
0238 struct ProgramStatePartialTrait<llvm::ImmutableList<T>> {
0239 using data_type = llvm::ImmutableList<T>;
0240 using key_type = T;
0241 using context_type = typename data_type::Factory &;
0242
0243 static data_type Add(data_type L, key_type K, context_type F) {
0244 return F.add(K, L);
0245 }
0246
0247 static bool Contains(data_type L, key_type K) {
0248 return L.contains(K);
0249 }
0250
0251 static data_type MakeData(void *const *p) {
0252 return p ? data_type((const llvm::ImmutableListImpl<T> *) *p)
0253 : data_type(nullptr);
0254 }
0255
0256 static void *MakeVoidPtr(data_type D) {
0257 return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
0258 }
0259
0260 static context_type MakeContext(void *p) {
0261 return *((typename data_type::Factory *) p);
0262 }
0263
0264 static void *CreateContext(llvm::BumpPtrAllocator &Alloc) {
0265 return new typename data_type::Factory(Alloc);
0266 }
0267
0268 static void DeleteContext(void *Ctx) {
0269 delete (typename data_type::Factory *) Ctx;
0270 }
0271 };
0272
0273 template <typename T> struct DefaultProgramStatePartialTraitImpl {
0274 using data_type = T;
0275 static T MakeData(void *const *P) { return P ? (T)(uintptr_t)*P : T{}; }
0276 static void *MakeVoidPtr(T D) { return (void *)(uintptr_t)D; }
0277 };
0278
0279
0280 template <typename T>
0281 struct ProgramStatePartialTrait<T,
0282 std::enable_if_t<std::is_integral<T>::value>>
0283 : DefaultProgramStatePartialTraitImpl<T> {};
0284
0285
0286 template <typename T>
0287 struct ProgramStatePartialTrait<T, std::enable_if_t<std::is_enum<T>::value>>
0288 : DefaultProgramStatePartialTraitImpl<T> {};
0289
0290
0291 template <typename T>
0292 struct ProgramStatePartialTrait<T *, void>
0293 : DefaultProgramStatePartialTraitImpl<T *> {};
0294
0295 }
0296 }
0297
0298 #endif