1226586Sdim//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*- 2226586Sdim// 3226586Sdim// The LLVM Compiler Infrastructure 4226586Sdim// 5226586Sdim// This file is distributed under the University of Illinois Open Source 6226586Sdim// License. See LICENSE.TXT for details. 7226586Sdim// 8226586Sdim//===----------------------------------------------------------------------===// 9226586Sdim// 10226586Sdim// This file defines partial implementations of template specializations of 11226586Sdim// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState 12235633Sdim// to implement set/get methods for manipulating a ProgramState's 13235633Sdim// generic data map. 14226586Sdim// 15226586Sdim//===----------------------------------------------------------------------===// 16226586Sdim 17226586Sdim 18226586Sdim#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 19226586Sdim#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 20226586Sdim 21252723Sdim#include "llvm/Support/DataTypes.h" 22252723Sdim 23226586Sdimnamespace llvm { 24226586Sdim class BumpPtrAllocator; 25226586Sdim template <typename K, typename D, typename I> class ImmutableMap; 26226586Sdim template <typename K, typename I> class ImmutableSet; 27226586Sdim template <typename T> class ImmutableList; 28226586Sdim template <typename T> class ImmutableListImpl; 29226586Sdim} 30226586Sdim 31226586Sdimnamespace clang { 32226586Sdim 33226586Sdimnamespace ento { 34226586Sdim template <typename T> struct ProgramStatePartialTrait; 35226586Sdim 36245431Sdim /// Declares a program state trait for type \p Type called \p Name, and 37245431Sdim /// introduce a typedef named \c NameTy. 38245431Sdim /// The macro should not be used inside namespaces, or for traits that must 39245431Sdim /// be accessible from more than one translation unit. 40245431Sdim #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ 41245431Sdim namespace { \ 42245431Sdim class Name {}; \ 43245431Sdim typedef Type Name ## Ty; \ 44245431Sdim } \ 45245431Sdim namespace clang { \ 46245431Sdim namespace ento { \ 47245431Sdim template <> \ 48245431Sdim struct ProgramStateTrait<Name> \ 49245431Sdim : public ProgramStatePartialTrait<Name ## Ty> { \ 50245431Sdim static void *GDMIndex() { static int Index; return &Index; } \ 51245431Sdim }; \ 52245431Sdim } \ 53245431Sdim } 54245431Sdim 55245431Sdim 56226586Sdim // Partial-specialization for ImmutableMap. 57226586Sdim 58226586Sdim template <typename Key, typename Data, typename Info> 59226586Sdim struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > { 60226586Sdim typedef llvm::ImmutableMap<Key,Data,Info> data_type; 61226586Sdim typedef typename data_type::Factory& context_type; 62226586Sdim typedef Key key_type; 63226586Sdim typedef Data value_type; 64226586Sdim typedef const value_type* lookup_type; 65226586Sdim 66226586Sdim static inline data_type MakeData(void *const* p) { 67226586Sdim return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 68226586Sdim } 69226586Sdim static inline void *MakeVoidPtr(data_type B) { 70226586Sdim return B.getRoot(); 71226586Sdim } 72226586Sdim static lookup_type Lookup(data_type B, key_type K) { 73226586Sdim return B.lookup(K); 74226586Sdim } 75226586Sdim static data_type Set(data_type B, key_type K, value_type E,context_type F){ 76226586Sdim return F.add(B, K, E); 77226586Sdim } 78226586Sdim 79226586Sdim static data_type Remove(data_type B, key_type K, context_type F) { 80226586Sdim return F.remove(B, K); 81226586Sdim } 82226586Sdim 83226586Sdim static inline context_type MakeContext(void *p) { 84226586Sdim return *((typename data_type::Factory*) p); 85226586Sdim } 86226586Sdim 87226586Sdim static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 88226586Sdim return new typename data_type::Factory(Alloc); 89226586Sdim } 90226586Sdim 91226586Sdim static void DeleteContext(void *Ctx) { 92226586Sdim delete (typename data_type::Factory*) Ctx; 93226586Sdim } 94226586Sdim }; 95226586Sdim 96245431Sdim /// Helper for registering a map trait. 97245431Sdim /// 98245431Sdim /// If the map type were written directly in the invocation of 99245431Sdim /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments 100245431Sdim /// would be treated as a macro argument separator, which is wrong. 101245431Sdim /// This allows the user to specify a map type in a way that the preprocessor 102245431Sdim /// can deal with. 103245431Sdim #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> 104226586Sdim 105245431Sdim 106226586Sdim // Partial-specialization for ImmutableSet. 107226586Sdim 108226586Sdim template <typename Key, typename Info> 109226586Sdim struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > { 110226586Sdim typedef llvm::ImmutableSet<Key,Info> data_type; 111226586Sdim typedef typename data_type::Factory& context_type; 112226586Sdim typedef Key key_type; 113226586Sdim 114226586Sdim static inline data_type MakeData(void *const* p) { 115226586Sdim return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 116226586Sdim } 117226586Sdim 118226586Sdim static inline void *MakeVoidPtr(data_type B) { 119226586Sdim return B.getRoot(); 120226586Sdim } 121226586Sdim 122226586Sdim static data_type Add(data_type B, key_type K, context_type F) { 123226586Sdim return F.add(B, K); 124226586Sdim } 125226586Sdim 126226586Sdim static data_type Remove(data_type B, key_type K, context_type F) { 127226586Sdim return F.remove(B, K); 128226586Sdim } 129226586Sdim 130226586Sdim static bool Contains(data_type B, key_type K) { 131226586Sdim return B.contains(K); 132226586Sdim } 133226586Sdim 134226586Sdim static inline context_type MakeContext(void *p) { 135226586Sdim return *((typename data_type::Factory*) p); 136226586Sdim } 137226586Sdim 138226586Sdim static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 139226586Sdim return new typename data_type::Factory(Alloc); 140226586Sdim } 141226586Sdim 142226586Sdim static void DeleteContext(void *Ctx) { 143226586Sdim delete (typename data_type::Factory*) Ctx; 144226586Sdim } 145226586Sdim }; 146226586Sdim 147245431Sdim 148226586Sdim // Partial-specialization for ImmutableList. 149226586Sdim 150226586Sdim template <typename T> 151226586Sdim struct ProgramStatePartialTrait< llvm::ImmutableList<T> > { 152226586Sdim typedef llvm::ImmutableList<T> data_type; 153226586Sdim typedef T key_type; 154226586Sdim typedef typename data_type::Factory& context_type; 155226586Sdim 156226586Sdim static data_type Add(data_type L, key_type K, context_type F) { 157226586Sdim return F.add(K, L); 158226586Sdim } 159226586Sdim 160226586Sdim static bool Contains(data_type L, key_type K) { 161226586Sdim return L.contains(K); 162226586Sdim } 163226586Sdim 164226586Sdim static inline data_type MakeData(void *const* p) { 165226586Sdim return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) 166226586Sdim : data_type(0); 167226586Sdim } 168226586Sdim 169226586Sdim static inline void *MakeVoidPtr(data_type D) { 170252723Sdim return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer()); 171226586Sdim } 172226586Sdim 173226586Sdim static inline context_type MakeContext(void *p) { 174226586Sdim return *((typename data_type::Factory*) p); 175226586Sdim } 176226586Sdim 177226586Sdim static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 178226586Sdim return new typename data_type::Factory(Alloc); 179226586Sdim } 180226586Sdim 181226586Sdim static void DeleteContext(void *Ctx) { 182226586Sdim delete (typename data_type::Factory*) Ctx; 183226586Sdim } 184226586Sdim }; 185245431Sdim 186226586Sdim 187226586Sdim // Partial specialization for bool. 188226586Sdim template <> struct ProgramStatePartialTrait<bool> { 189226586Sdim typedef bool data_type; 190226586Sdim 191226586Sdim static inline data_type MakeData(void *const* p) { 192226586Sdim return p ? (data_type) (uintptr_t) *p 193226586Sdim : data_type(); 194226586Sdim } 195226586Sdim static inline void *MakeVoidPtr(data_type d) { 196226586Sdim return (void*) (uintptr_t) d; 197226586Sdim } 198226586Sdim }; 199226586Sdim 200226586Sdim // Partial specialization for unsigned. 201226586Sdim template <> struct ProgramStatePartialTrait<unsigned> { 202226586Sdim typedef unsigned data_type; 203226586Sdim 204226586Sdim static inline data_type MakeData(void *const* p) { 205226586Sdim return p ? (data_type) (uintptr_t) *p 206226586Sdim : data_type(); 207226586Sdim } 208226586Sdim static inline void *MakeVoidPtr(data_type d) { 209226586Sdim return (void*) (uintptr_t) d; 210226586Sdim } 211226586Sdim }; 212235633Sdim 213235633Sdim // Partial specialization for void*. 214235633Sdim template <> struct ProgramStatePartialTrait<void*> { 215235633Sdim typedef void *data_type; 216235633Sdim 217235633Sdim static inline data_type MakeData(void *const* p) { 218235633Sdim return p ? *p 219235633Sdim : data_type(); 220235633Sdim } 221235633Sdim static inline void *MakeVoidPtr(data_type d) { 222235633Sdim return d; 223235633Sdim } 224235633Sdim }; 225235633Sdim 226252723Sdim // Partial specialization for const void *. 227252723Sdim template <> struct ProgramStatePartialTrait<const void *> { 228252723Sdim typedef const void *data_type; 229226586Sdim 230252723Sdim static inline data_type MakeData(void * const *p) { 231252723Sdim return p ? *p : data_type(); 232252723Sdim } 233252723Sdim 234252723Sdim static inline void *MakeVoidPtr(data_type d) { 235252723Sdim return const_cast<void *>(d); 236252723Sdim } 237252723Sdim }; 238252723Sdim 239252723Sdim} // end ento namespace 240252723Sdim 241226586Sdim} // end clang namespace 242226586Sdim 243226586Sdim#endif 244