clang API Documentation
00001 //ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*- 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines partial implementations of template specializations of 00011 // the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState 00012 // to implement set/get methods for manipulating a ProgramState's 00013 // generic data map. 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 00018 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H 00019 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H 00020 00021 #include "llvm/Support/Allocator.h" 00022 #include "llvm/Support/DataTypes.h" 00023 00024 namespace llvm { 00025 template <typename K, typename D, typename I> class ImmutableMap; 00026 template <typename K, typename I> class ImmutableSet; 00027 template <typename T> class ImmutableList; 00028 template <typename T> class ImmutableListImpl; 00029 } 00030 00031 namespace clang { 00032 00033 namespace ento { 00034 template <typename T> struct ProgramStatePartialTrait; 00035 00036 /// Declares a program state trait for type \p Type called \p Name, and 00037 /// introduce a typedef named \c NameTy. 00038 /// The macro should not be used inside namespaces, or for traits that must 00039 /// be accessible from more than one translation unit. 00040 #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ 00041 namespace { \ 00042 class Name {}; \ 00043 typedef Type Name ## Ty; \ 00044 } \ 00045 namespace clang { \ 00046 namespace ento { \ 00047 template <> \ 00048 struct ProgramStateTrait<Name> \ 00049 : public ProgramStatePartialTrait<Name ## Ty> { \ 00050 static void *GDMIndex() { static int Index; return &Index; } \ 00051 }; \ 00052 } \ 00053 } 00054 00055 00056 // Partial-specialization for ImmutableMap. 00057 00058 template <typename Key, typename Data, typename Info> 00059 struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > { 00060 typedef llvm::ImmutableMap<Key,Data,Info> data_type; 00061 typedef typename data_type::Factory& context_type; 00062 typedef Key key_type; 00063 typedef Data value_type; 00064 typedef const value_type* lookup_type; 00065 00066 static inline data_type MakeData(void *const* p) { 00067 return p ? data_type((typename data_type::TreeTy*) *p) 00068 : data_type(nullptr); 00069 } 00070 static inline void *MakeVoidPtr(data_type B) { 00071 return B.getRoot(); 00072 } 00073 static lookup_type Lookup(data_type B, key_type K) { 00074 return B.lookup(K); 00075 } 00076 static data_type Set(data_type B, key_type K, value_type E,context_type F){ 00077 return F.add(B, K, E); 00078 } 00079 00080 static data_type Remove(data_type B, key_type K, context_type F) { 00081 return F.remove(B, K); 00082 } 00083 00084 static inline context_type MakeContext(void *p) { 00085 return *((typename data_type::Factory*) p); 00086 } 00087 00088 static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 00089 return new typename data_type::Factory(Alloc); 00090 } 00091 00092 static void DeleteContext(void *Ctx) { 00093 delete (typename data_type::Factory*) Ctx; 00094 } 00095 }; 00096 00097 /// Helper for registering a map trait. 00098 /// 00099 /// If the map type were written directly in the invocation of 00100 /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments 00101 /// would be treated as a macro argument separator, which is wrong. 00102 /// This allows the user to specify a map type in a way that the preprocessor 00103 /// can deal with. 00104 #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> 00105 00106 00107 // Partial-specialization for ImmutableSet. 00108 00109 template <typename Key, typename Info> 00110 struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > { 00111 typedef llvm::ImmutableSet<Key,Info> data_type; 00112 typedef typename data_type::Factory& context_type; 00113 typedef Key key_type; 00114 00115 static inline data_type MakeData(void *const* p) { 00116 return p ? data_type((typename data_type::TreeTy*) *p) 00117 : data_type(nullptr); 00118 } 00119 00120 static inline void *MakeVoidPtr(data_type B) { 00121 return B.getRoot(); 00122 } 00123 00124 static data_type Add(data_type B, key_type K, context_type F) { 00125 return F.add(B, K); 00126 } 00127 00128 static data_type Remove(data_type B, key_type K, context_type F) { 00129 return F.remove(B, K); 00130 } 00131 00132 static bool Contains(data_type B, key_type K) { 00133 return B.contains(K); 00134 } 00135 00136 static inline context_type MakeContext(void *p) { 00137 return *((typename data_type::Factory*) p); 00138 } 00139 00140 static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 00141 return new typename data_type::Factory(Alloc); 00142 } 00143 00144 static void DeleteContext(void *Ctx) { 00145 delete (typename data_type::Factory*) Ctx; 00146 } 00147 }; 00148 00149 00150 // Partial-specialization for ImmutableList. 00151 00152 template <typename T> 00153 struct ProgramStatePartialTrait< llvm::ImmutableList<T> > { 00154 typedef llvm::ImmutableList<T> data_type; 00155 typedef T key_type; 00156 typedef typename data_type::Factory& context_type; 00157 00158 static data_type Add(data_type L, key_type K, context_type F) { 00159 return F.add(K, L); 00160 } 00161 00162 static bool Contains(data_type L, key_type K) { 00163 return L.contains(K); 00164 } 00165 00166 static inline data_type MakeData(void *const* p) { 00167 return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) 00168 : data_type(nullptr); 00169 } 00170 00171 static inline void *MakeVoidPtr(data_type D) { 00172 return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer()); 00173 } 00174 00175 static inline context_type MakeContext(void *p) { 00176 return *((typename data_type::Factory*) p); 00177 } 00178 00179 static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 00180 return new typename data_type::Factory(Alloc); 00181 } 00182 00183 static void DeleteContext(void *Ctx) { 00184 delete (typename data_type::Factory*) Ctx; 00185 } 00186 }; 00187 00188 00189 // Partial specialization for bool. 00190 template <> struct ProgramStatePartialTrait<bool> { 00191 typedef bool data_type; 00192 00193 static inline data_type MakeData(void *const* p) { 00194 return p ? (data_type) (uintptr_t) *p 00195 : data_type(); 00196 } 00197 static inline void *MakeVoidPtr(data_type d) { 00198 return (void*) (uintptr_t) d; 00199 } 00200 }; 00201 00202 // Partial specialization for unsigned. 00203 template <> struct ProgramStatePartialTrait<unsigned> { 00204 typedef unsigned data_type; 00205 00206 static inline data_type MakeData(void *const* p) { 00207 return p ? (data_type) (uintptr_t) *p 00208 : data_type(); 00209 } 00210 static inline void *MakeVoidPtr(data_type d) { 00211 return (void*) (uintptr_t) d; 00212 } 00213 }; 00214 00215 // Partial specialization for void*. 00216 template <> struct ProgramStatePartialTrait<void*> { 00217 typedef void *data_type; 00218 00219 static inline data_type MakeData(void *const* p) { 00220 return p ? *p 00221 : data_type(); 00222 } 00223 static inline void *MakeVoidPtr(data_type d) { 00224 return d; 00225 } 00226 }; 00227 00228 // Partial specialization for const void *. 00229 template <> struct ProgramStatePartialTrait<const void *> { 00230 typedef const void *data_type; 00231 00232 static inline data_type MakeData(void * const *p) { 00233 return p ? *p : data_type(); 00234 } 00235 00236 static inline void *MakeVoidPtr(data_type d) { 00237 return const_cast<void *>(d); 00238 } 00239 }; 00240 00241 } // end ento namespace 00242 00243 } // end clang namespace 00244 00245 #endif