clang API Documentation

ProgramStateTrait.h
Go to the documentation of this file.
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