167754Smsmith//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*- 267754Smsmith// 377424Smsmith// The LLVM Compiler Infrastructure 467754Smsmith// 567754Smsmith// This file is distributed under the University of Illinois Open Source 667754Smsmith// License. See LICENSE.TXT for details. 7217365Sjkim// 8245582Sjkim//===----------------------------------------------------------------------===// 970243Smsmith// 1067754Smsmith// This file defines partial implementations of template specializations of 11217365Sjkim// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState 12217365Sjkim// to implement set/get methods for manipulating a ProgramState's 13217365Sjkim// generic data map. 14217365Sjkim// 15217365Sjkim//===----------------------------------------------------------------------===// 16217365Sjkim 17217365Sjkim 18217365Sjkim#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 19217365Sjkim#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 20217365Sjkim 21217365Sjkim#include "llvm/Support/DataTypes.h" 22217365Sjkim 23217365Sjkimnamespace llvm { 24217365Sjkim class BumpPtrAllocator; 2567754Smsmith template <typename K, typename D, typename I> class ImmutableMap; 26217365Sjkim template <typename K, typename I> class ImmutableSet; 27217365Sjkim template <typename T> class ImmutableList; 28217365Sjkim template <typename T> class ImmutableListImpl; 2967754Smsmith} 30217365Sjkim 31217365Sjkimnamespace clang { 32217365Sjkim 33217365Sjkimnamespace ento { 34217365Sjkim template <typename T> struct ProgramStatePartialTrait; 35217365Sjkim 36217365Sjkim /// Declares a program state trait for type \p Type called \p Name, and 37217365Sjkim /// introduce a typedef named \c NameTy. 38217365Sjkim /// The macro should not be used inside namespaces, or for traits that must 39217365Sjkim /// be accessible from more than one translation unit. 40217365Sjkim #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ 41217365Sjkim namespace { \ 42217365Sjkim class Name {}; \ 4367754Smsmith typedef Type Name ## Ty; \ 4477424Smsmith } \ 4577424Smsmith namespace clang { \ 4667754Smsmith namespace ento { \ 4767754Smsmith template <> \ 48167802Sjkim struct ProgramStateTrait<Name> \ 49228110Sjkim : public ProgramStatePartialTrait<Name ## Ty> { \ 50167802Sjkim static void *GDMIndex() { static int Index; return &Index; } \ 51167802Sjkim }; \ 52167802Sjkim } \ 53167802Sjkim } 54167802Sjkim 55167802Sjkim 56167802Sjkim // Partial-specialization for ImmutableMap. 57167802Sjkim 58167802Sjkim template <typename Key, typename Data, typename Info> 59167802Sjkim struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > { 60167802Sjkim typedef llvm::ImmutableMap<Key,Data,Info> data_type; 61167802Sjkim typedef typename data_type::Factory& context_type; 62167802Sjkim typedef Key key_type; 63167802Sjkim typedef Data value_type; 64167802Sjkim typedef const value_type* lookup_type; 65167802Sjkim 66167802Sjkim static inline data_type MakeData(void *const* p) { 67167802Sjkim return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 68167802Sjkim } 69167802Sjkim static inline void *MakeVoidPtr(data_type B) { 70167802Sjkim return B.getRoot(); 71167802Sjkim } 72167802Sjkim static lookup_type Lookup(data_type B, key_type K) { 73228110Sjkim return B.lookup(K); 74228110Sjkim } 75228110Sjkim static data_type Set(data_type B, key_type K, value_type E,context_type F){ 76228110Sjkim return F.add(B, K, E); 77228110Sjkim } 78228110Sjkim 79228110Sjkim static data_type Remove(data_type B, key_type K, context_type F) { 80228110Sjkim return F.remove(B, K); 81228110Sjkim } 82228110Sjkim 83228110Sjkim static inline context_type MakeContext(void *p) { 84228110Sjkim return *((typename data_type::Factory*) p); 85228110Sjkim } 86228110Sjkim 87228110Sjkim static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 88228110Sjkim return new typename data_type::Factory(Alloc); 89167802Sjkim } 90167802Sjkim 91250838Sjkim static void DeleteContext(void *Ctx) { 92250838Sjkim delete (typename data_type::Factory*) Ctx; 93250838Sjkim } 94250838Sjkim }; 95250838Sjkim 96250838Sjkim /// Helper for registering a map trait. 97250838Sjkim /// 98250838Sjkim /// If the map type were written directly in the invocation of 99250838Sjkim /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments 100250838Sjkim /// would be treated as a macro argument separator, which is wrong. 101250838Sjkim /// This allows the user to specify a map type in a way that the preprocessor 102250838Sjkim /// can deal with. 103250838Sjkim #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> 104250838Sjkim 105250838Sjkim 106250838Sjkim // Partial-specialization for ImmutableSet. 107250838Sjkim 108250838Sjkim template <typename Key, typename Info> 109250838Sjkim struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > { 110250838Sjkim typedef llvm::ImmutableSet<Key,Info> data_type; 111250838Sjkim typedef typename data_type::Factory& context_type; 112250838Sjkim typedef Key key_type; 113250838Sjkim 114250838Sjkim static inline data_type MakeData(void *const* p) { 115250838Sjkim return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 116250838Sjkim } 117250838Sjkim 118250838Sjkim static inline void *MakeVoidPtr(data_type B) { 119250838Sjkim return B.getRoot(); 120250838Sjkim } 121250838Sjkim 122250838Sjkim static data_type Add(data_type B, key_type K, context_type F) { 123250838Sjkim return F.add(B, K); 124250838Sjkim } 125250838Sjkim 126250838Sjkim static data_type Remove(data_type B, key_type K, context_type F) { 127250838Sjkim return F.remove(B, K); 128250838Sjkim } 129250838Sjkim 130250838Sjkim static bool Contains(data_type B, key_type K) { 131250838Sjkim return B.contains(K); 132250838Sjkim } 133250838Sjkim 134167802Sjkim static inline context_type MakeContext(void *p) { 135167802Sjkim return *((typename data_type::Factory*) p); 136167802Sjkim } 137167802Sjkim 138167802Sjkim static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 139167802Sjkim return new typename data_type::Factory(Alloc); 140167802Sjkim } 14173561Smsmith 142167802Sjkim static void DeleteContext(void *Ctx) { 143167802Sjkim delete (typename data_type::Factory*) Ctx; 144167802Sjkim } 145167802Sjkim }; 146167802Sjkim 147245582Sjkim 148167802Sjkim // Partial-specialization for ImmutableList. 149167802Sjkim 15073561Smsmith template <typename T> 15173561Smsmith struct ProgramStatePartialTrait< llvm::ImmutableList<T> > { 15273561Smsmith typedef llvm::ImmutableList<T> data_type; 15373561Smsmith typedef T key_type; 15473561Smsmith typedef typename data_type::Factory& context_type; 15573561Smsmith 15673561Smsmith static data_type Add(data_type L, key_type K, context_type F) { 15773561Smsmith return F.add(K, L); 15873561Smsmith } 15991116Smsmith 16073561Smsmith static bool Contains(data_type L, key_type K) { 16173561Smsmith return L.contains(K); 162114237Snjl } 16373561Smsmith 16473561Smsmith static inline data_type MakeData(void *const* p) { 165249112Sjkim return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) 166249112Sjkim : data_type(0); 16767754Smsmith } 16867754Smsmith 16967754Smsmith static inline void *MakeVoidPtr(data_type D) { 17077424Smsmith return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer()); 17167754Smsmith } 17267754Smsmith 17367754Smsmith static inline context_type MakeContext(void *p) { 17467754Smsmith return *((typename data_type::Factory*) p); 17567754Smsmith } 17667754Smsmith 17767754Smsmith static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 178151937Sjkim return new typename data_type::Factory(Alloc); 17967754Smsmith } 180193267Sjkim 181151937Sjkim static void DeleteContext(void *Ctx) { 18267754Smsmith delete (typename data_type::Factory*) Ctx; 18367754Smsmith } 184102550Siwasaki }; 18569746Smsmith 186114237Snjl 18777424Smsmith // Partial specialization for bool. 18867754Smsmith template <> struct ProgramStatePartialTrait<bool> { 18967754Smsmith typedef bool data_type; 190193267Sjkim 191193267Sjkim static inline data_type MakeData(void *const* p) { 192193267Sjkim return p ? (data_type) (uintptr_t) *p 193193267Sjkim : data_type(); 194100966Siwasaki } 195100966Siwasaki static inline void *MakeVoidPtr(data_type d) { 196114237Snjl return (void*) (uintptr_t) d; 19777424Smsmith } 19891116Smsmith }; 19967754Smsmith 200114237Snjl // Partial specialization for unsigned. 201123315Snjl template <> struct ProgramStatePartialTrait<unsigned> { 202123315Snjl typedef unsigned data_type; 203123315Snjl 204123315Snjl static inline data_type MakeData(void *const* p) { 205123315Snjl return p ? (data_type) (uintptr_t) *p 206123315Snjl : data_type(); 207123315Snjl } 208193267Sjkim static inline void *MakeVoidPtr(data_type d) { 209193267Sjkim return (void*) (uintptr_t) d; 210193267Sjkim } 211193267Sjkim }; 212123315Snjl 21399679Siwasaki // Partial specialization for void*. 21499679Siwasaki template <> struct ProgramStatePartialTrait<void*> { 21599679Siwasaki typedef void *data_type; 216114237Snjl 21777424Smsmith static inline data_type MakeData(void *const* p) { 21869746Smsmith return p ? *p 21969746Smsmith : data_type(); 220114237Snjl } 22191116Smsmith static inline void *MakeVoidPtr(data_type d) { 22291116Smsmith return d; 22369746Smsmith } 22499679Siwasaki }; 22582367Smsmith 226202771Sjkim // Partial specialization for const void *. 22782367Smsmith template <> struct ProgramStatePartialTrait<const void *> { 22882367Smsmith typedef const void *data_type; 22967754Smsmith 23077424Smsmith static inline data_type MakeData(void * const *p) { 23191116Smsmith return p ? *p : data_type(); 23267754Smsmith } 23367754Smsmith 234151937Sjkim static inline void *MakeVoidPtr(data_type d) { 235151937Sjkim return const_cast<void *>(d); 236151937Sjkim } 237151937Sjkim }; 238151937Sjkim 239151937Sjkim} // end ento namespace 24067754Smsmith 241151937Sjkim} // end clang namespace 242151937Sjkim 243151937Sjkim#endif 244151937Sjkim