Ref.h

Go to the documentation of this file.
00001 //===-- Ref.h ---------------------------------------------------*- C++ -*-===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #ifndef KLEE_REF_H
00011 #define KLEE_REF_H
00012 
00013 #include "llvm/Support/Casting.h"
00014 #include "llvm/Support/Streams.h"
00015 using llvm::isa;
00016 using llvm::cast;
00017 using llvm::cast_or_null;
00018 using llvm::dyn_cast;
00019 using llvm::dyn_cast_or_null;
00020 
00021 #include <assert.h>
00022 
00023 namespace klee {
00024 
00025 template<class T>
00026 class ref {
00027   T *ptr;
00028 
00029 public:
00030   // default constructor: create a NULL reference
00031   ref() : ptr(0) { }
00032   ~ref () { dec (); }
00033 
00034 private:
00035   void inc() {
00036     if (ptr)
00037       ++ptr->refCount;
00038   }
00039   
00040   void dec() {
00041     if (ptr && --ptr->refCount == 0)
00042       delete ptr;
00043   }  
00044 
00045 public:
00046   template<class U> friend class ref;
00047 
00048   // constructor from pointer
00049   ref(T *p) : ptr(p) {
00050     inc();
00051   }
00052   
00053   // normal copy constructor
00054   ref(const ref<T> &r) : ptr(r.ptr) {
00055     inc();
00056   }
00057   
00058   // conversion constructor
00059   template<class U>
00060   ref (const ref<U> &r) {
00061     ptr = r.ptr;
00062     inc();
00063   }
00064   
00065   // pointer operations
00066   T *get () const {
00067     return ptr;
00068   }
00069 
00070   /* The copy assignment operator must also explicitly be defined,
00071    * despite a redundant template. */
00072   ref<T> &operator= (const ref<T> &r) {
00073     dec();
00074     ptr = r.ptr;
00075     inc();
00076     
00077     return *this;
00078   }
00079   
00080   template<class U> ref<T> &operator= (const ref<U> &r) {
00081     dec();
00082     ptr = r.ptr;
00083     inc();
00084     
00085     return *this;
00086   }
00087 
00088   T& operator*() const {
00089     return *ptr;
00090   }
00091 
00092   T* operator->() const {
00093     return ptr;
00094   }
00095 
00096   bool isNull() const { return ptr == 0; }
00097 
00098   // assumes non-null arguments
00099   int compare(const ref &rhs) const {
00100     assert(!isNull() && !rhs.isNull() && "Invalid call to compare()");
00101     return get()->compare(*rhs.get());
00102   }
00103 
00104   // assumes non-null arguments
00105   bool operator<(const ref &rhs) const { return compare(rhs)<0; }
00106   bool operator==(const ref &rhs) const { return compare(rhs)==0; }
00107   bool operator!=(const ref &rhs) const { return compare(rhs)!=0; }
00108 };
00109 
00110 template<class T>
00111 inline std::ostream &operator<<(std::ostream &os, const ref<T> &e) {
00112   os << *e;
00113   return os;
00114 }
00115 
00116 } // end namespace klee
00117 
00118 namespace llvm {
00119   // simplify_type implementation for ref<>, which allows dyn_cast from on a
00120   // ref<> to apply to the wrapper type. Conceptually the result of such a
00121   // dyn_cast should probably be a ref of the casted type, but that breaks the
00122   // idiom of initializing a variable to the result of a dyn_cast inside an if
00123   // condition, or we would have to implement operator(bool) for ref<> with
00124   // isNull semantics, which doesn't seem like a good idea.
00125 template<typename T>
00126 struct simplify_type<const ::klee::ref<T> > {
00127   typedef T* SimpleType;
00128   static SimpleType getSimplifiedValue(const ::klee::ref<T> &Ref) {
00129     return Ref.get();
00130   }
00131 };
00132 
00133 template<typename T> 
00134 struct simplify_type< ::klee::ref<T> >
00135   : public simplify_type<const ::klee::ref<T> > {};
00136 }
00137 
00138 #endif /* KLEE_REF_H */

Generated on Fri Jun 5 03:31:31 2009 for klee by  doxygen 1.5.8