ProgramStateTrait.h revision 40d8551890bc8454c4e0a28c9072c9c1d1dd588a
1ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*- 2ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// 3ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// The LLVM Compiler Infrastructure 4ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// 5ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// This file is distributed under the University of Illinois Open Source 6ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// License. See LICENSE.TXT for details. 7ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// 8ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek//===----------------------------------------------------------------------===// 9ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// 10ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// This file defines partial implementations of template specializations of 11ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState 12af5f550de34525b27f0ff31dafce792caf8158b6Anna Zaks// to implement set/get methods for manipulating a ProgramState's 13af5f550de34525b27f0ff31dafce792caf8158b6Anna Zaks// generic data map. 14ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek// 15ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek//===----------------------------------------------------------------------===// 16ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 17ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 18ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 19ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 20ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 21ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremeneknamespace llvm { 22ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek class BumpPtrAllocator; 23ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename K, typename D, typename I> class ImmutableMap; 24ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename K, typename I> class ImmutableSet; 25ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename T> class ImmutableList; 26ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename T> class ImmutableListImpl; 27ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek} 28ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 29ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremeneknamespace clang { 30ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 31ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremeneknamespace ento { 32ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename T> struct ProgramStatePartialTrait; 33ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 34166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose /// Declares a program state trait for type \p Type called \p Name, and 35166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose /// introduce a typedef named \c NameTy. 36166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose /// The macro should not be used inside namespaces, or for traits that must 37166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose /// be accessible from more than one translation unit. 38166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ 39166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose namespace { \ 40166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose class Name {}; \ 41166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose typedef Type Name ## Ty; \ 42166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose } \ 43166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose namespace clang { \ 44166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose namespace ento { \ 45166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose template <> \ 46166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose struct ProgramStateTrait<Name> \ 47166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose : public ProgramStatePartialTrait<Name ## Ty> { \ 48166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose static void *GDMIndex() { static int Index; return &Index; } \ 49166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose }; \ 50166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose } \ 51166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose } 52166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose 53166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose 54ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek // Partial-specialization for ImmutableMap. 55ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 56ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename Key, typename Data, typename Info> 57ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > { 58ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef llvm::ImmutableMap<Key,Data,Info> data_type; 59ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef typename data_type::Factory& context_type; 60ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef Key key_type; 61ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef Data value_type; 62ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef const value_type* lookup_type; 63ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 64ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline data_type MakeData(void *const* p) { 65ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 66ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 67ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline void *MakeVoidPtr(data_type B) { 68ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return B.getRoot(); 69ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 70ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static lookup_type Lookup(data_type B, key_type K) { 71ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return B.lookup(K); 72ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 73ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static data_type Set(data_type B, key_type K, value_type E,context_type F){ 74ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return F.add(B, K, E); 75ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 76ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 77ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static data_type Remove(data_type B, key_type K, context_type F) { 78ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return F.remove(B, K); 79ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 80ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 81ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline context_type MakeContext(void *p) { 82ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return *((typename data_type::Factory*) p); 83ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 84ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 85ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 86ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return new typename data_type::Factory(Alloc); 87ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 88ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 89ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static void DeleteContext(void *Ctx) { 90ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek delete (typename data_type::Factory*) Ctx; 91ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 92ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek }; 93ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 9440d8551890bc8454c4e0a28c9072c9c1d1dd588aJordan Rose /// Helper for registering a map trait. 9540d8551890bc8454c4e0a28c9072c9c1d1dd588aJordan Rose /// 9640d8551890bc8454c4e0a28c9072c9c1d1dd588aJordan Rose /// If the map type were written directly in the invocation of 9740d8551890bc8454c4e0a28c9072c9c1d1dd588aJordan Rose /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments 9840d8551890bc8454c4e0a28c9072c9c1d1dd588aJordan Rose /// would be treated as a macro argument separator, which is wrong. 9940d8551890bc8454c4e0a28c9072c9c1d1dd588aJordan Rose /// This allows the user to specify a map type in a way that the preprocessor 10040d8551890bc8454c4e0a28c9072c9c1d1dd588aJordan Rose /// can deal with. 101166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> 102166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose 103ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 104ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek // Partial-specialization for ImmutableSet. 105ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 106ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename Key, typename Info> 107ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > { 108ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef llvm::ImmutableSet<Key,Info> data_type; 109ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef typename data_type::Factory& context_type; 110ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef Key key_type; 111ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 112ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline data_type MakeData(void *const* p) { 113ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 114ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 115ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 116ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline void *MakeVoidPtr(data_type B) { 117ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return B.getRoot(); 118ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 119ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 120ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static data_type Add(data_type B, key_type K, context_type F) { 121ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return F.add(B, K); 122ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 123ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 124ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static data_type Remove(data_type B, key_type K, context_type F) { 125ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return F.remove(B, K); 126ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 127ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 128ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static bool Contains(data_type B, key_type K) { 129ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return B.contains(K); 130ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 131ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 132ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline context_type MakeContext(void *p) { 133ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return *((typename data_type::Factory*) p); 134ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 135ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 136ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 137ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return new typename data_type::Factory(Alloc); 138ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 139ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 140ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static void DeleteContext(void *Ctx) { 141ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek delete (typename data_type::Factory*) Ctx; 142ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 143ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek }; 144ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 145166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose 146ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek // Partial-specialization for ImmutableList. 147ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 148ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <typename T> 149ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek struct ProgramStatePartialTrait< llvm::ImmutableList<T> > { 150ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef llvm::ImmutableList<T> data_type; 151ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef T key_type; 152ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef typename data_type::Factory& context_type; 153ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 154ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static data_type Add(data_type L, key_type K, context_type F) { 155ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return F.add(K, L); 156ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 157ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 158ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static bool Contains(data_type L, key_type K) { 159ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return L.contains(K); 160ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 161ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 162ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline data_type MakeData(void *const* p) { 163ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) 164ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek : data_type(0); 165ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 166ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 167ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline void *MakeVoidPtr(data_type D) { 168ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return (void*) D.getInternalPointer(); 169ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 170ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 171ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline context_type MakeContext(void *p) { 172ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return *((typename data_type::Factory*) p); 173ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 174ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 175ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 176ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return new typename data_type::Factory(Alloc); 177ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 178ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 179ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static void DeleteContext(void *Ctx) { 180ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek delete (typename data_type::Factory*) Ctx; 181ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 182ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek }; 183166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose 184166d502d5367ceacd1313a33cac43b1048b8524dJordan Rose 185ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek // Partial specialization for bool. 186ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <> struct ProgramStatePartialTrait<bool> { 187ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef bool data_type; 188ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 189ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline data_type MakeData(void *const* p) { 190ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return p ? (data_type) (uintptr_t) *p 191ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek : data_type(); 192ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 193ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline void *MakeVoidPtr(data_type d) { 194ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return (void*) (uintptr_t) d; 195ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 196ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek }; 197ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 198ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek // Partial specialization for unsigned. 199ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek template <> struct ProgramStatePartialTrait<unsigned> { 200ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek typedef unsigned data_type; 201ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 202ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline data_type MakeData(void *const* p) { 203ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return p ? (data_type) (uintptr_t) *p 204ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek : data_type(); 205ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 206ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek static inline void *MakeVoidPtr(data_type d) { 207ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek return (void*) (uintptr_t) d; 208ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek } 209ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek }; 2105903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks 2115903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks // Partial specialization for void*. 2125903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks template <> struct ProgramStatePartialTrait<void*> { 2135903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks typedef void *data_type; 2145903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks 2155903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks static inline data_type MakeData(void *const* p) { 2165903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks return p ? *p 2175903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks : data_type(); 2185903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks } 2195903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks static inline void *MakeVoidPtr(data_type d) { 2205903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks return d; 2215903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks } 2225903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks }; 2235903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks 224ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek} // end GR namespace 225ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 226ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek} // end clang namespace 227ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek 228ae160f880d183ab938fd7ce3b891694ae2f569c0Ted Kremenek#endif 229