clang API Documentation

BasicValueFactory.cpp
Go to the documentation of this file.
00001 //=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- 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 BasicValueFactory, a class that manages the lifetime
00011 //  of APSInt objects and symbolic constraints used by ExprEngine
00012 //  and related classes.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
00017 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
00018 
00019 using namespace clang;
00020 using namespace ento;
00021 
00022 void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
00023                               llvm::ImmutableList<SVal> L) {
00024   T.Profile(ID);
00025   ID.AddPointer(L.getInternalPointer());
00026 }
00027 
00028 void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
00029                                   const StoreRef &store,
00030                                   const TypedValueRegion *region) {
00031   ID.AddPointer(store.getStore());
00032   ID.AddPointer(region);
00033 }
00034 
00035 typedef std::pair<SVal, uintptr_t> SValData;
00036 typedef std::pair<SVal, SVal> SValPair;
00037 
00038 namespace llvm {
00039 template<> struct FoldingSetTrait<SValData> {
00040   static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
00041     X.first.Profile(ID);
00042     ID.AddPointer( (void*) X.second);
00043   }
00044 };
00045 
00046 template<> struct FoldingSetTrait<SValPair> {
00047   static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
00048     X.first.Profile(ID);
00049     X.second.Profile(ID);
00050   }
00051 };
00052 }
00053 
00054 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData> >
00055   PersistentSValsTy;
00056 
00057 typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair> >
00058   PersistentSValPairsTy;
00059 
00060 BasicValueFactory::~BasicValueFactory() {
00061   // Note that the dstor for the contents of APSIntSet will never be called,
00062   // so we iterate over the set and invoke the dstor for each APSInt.  This
00063   // frees an aux. memory allocated to represent very large constants.
00064   for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
00065     I->getValue().~APSInt();
00066 
00067   delete (PersistentSValsTy*) PersistentSVals;
00068   delete (PersistentSValPairsTy*) PersistentSValPairs;
00069 }
00070 
00071 const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
00072   llvm::FoldingSetNodeID ID;
00073   void *InsertPos;
00074   typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
00075 
00076   X.Profile(ID);
00077   FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
00078 
00079   if (!P) {
00080     P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
00081     new (P) FoldNodeTy(X);
00082     APSIntSet.InsertNode(P, InsertPos);
00083   }
00084 
00085   return *P;
00086 }
00087 
00088 const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
00089                                                 bool isUnsigned) {
00090   llvm::APSInt V(X, isUnsigned);
00091   return getValue(V);
00092 }
00093 
00094 const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
00095                                            bool isUnsigned) {
00096   llvm::APSInt V(BitWidth, isUnsigned);
00097   V = X;
00098   return getValue(V);
00099 }
00100 
00101 const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
00102 
00103   unsigned bits = Ctx.getTypeSize(T);
00104   llvm::APSInt V(bits, 
00105                  T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T));
00106   V = X;
00107   return getValue(V);
00108 }
00109 
00110 const CompoundValData*
00111 BasicValueFactory::getCompoundValData(QualType T,
00112                                       llvm::ImmutableList<SVal> Vals) {
00113 
00114   llvm::FoldingSetNodeID ID;
00115   CompoundValData::Profile(ID, T, Vals);
00116   void *InsertPos;
00117 
00118   CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
00119 
00120   if (!D) {
00121     D = (CompoundValData*) BPAlloc.Allocate<CompoundValData>();
00122     new (D) CompoundValData(T, Vals);
00123     CompoundValDataSet.InsertNode(D, InsertPos);
00124   }
00125 
00126   return D;
00127 }
00128 
00129 const LazyCompoundValData*
00130 BasicValueFactory::getLazyCompoundValData(const StoreRef &store,
00131                                           const TypedValueRegion *region) {
00132   llvm::FoldingSetNodeID ID;
00133   LazyCompoundValData::Profile(ID, store, region);
00134   void *InsertPos;
00135 
00136   LazyCompoundValData *D =
00137     LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
00138 
00139   if (!D) {
00140     D = (LazyCompoundValData*) BPAlloc.Allocate<LazyCompoundValData>();
00141     new (D) LazyCompoundValData(store, region);
00142     LazyCompoundValDataSet.InsertNode(D, InsertPos);
00143   }
00144 
00145   return D;
00146 }
00147 
00148 const llvm::APSInt*
00149 BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
00150                              const llvm::APSInt& V1, const llvm::APSInt& V2) {
00151 
00152   switch (Op) {
00153     default:
00154       assert (false && "Invalid Opcode.");
00155 
00156     case BO_Mul:
00157       return &getValue( V1 * V2 );
00158 
00159     case BO_Div:
00160       return &getValue( V1 / V2 );
00161 
00162     case BO_Rem:
00163       return &getValue( V1 % V2 );
00164 
00165     case BO_Add:
00166       return &getValue( V1 + V2 );
00167 
00168     case BO_Sub:
00169       return &getValue( V1 - V2 );
00170 
00171     case BO_Shl: {
00172 
00173       // FIXME: This logic should probably go higher up, where we can
00174       // test these conditions symbolically.
00175 
00176       // FIXME: Expand these checks to include all undefined behavior.
00177 
00178       if (V2.isSigned() && V2.isNegative())
00179         return NULL;
00180 
00181       uint64_t Amt = V2.getZExtValue();
00182 
00183       if (Amt > V1.getBitWidth())
00184         return NULL;
00185 
00186       return &getValue( V1.operator<<( (unsigned) Amt ));
00187     }
00188 
00189     case BO_Shr: {
00190 
00191       // FIXME: This logic should probably go higher up, where we can
00192       // test these conditions symbolically.
00193 
00194       // FIXME: Expand these checks to include all undefined behavior.
00195 
00196       if (V2.isSigned() && V2.isNegative())
00197         return NULL;
00198 
00199       uint64_t Amt = V2.getZExtValue();
00200 
00201       if (Amt > V1.getBitWidth())
00202         return NULL;
00203 
00204       return &getValue( V1.operator>>( (unsigned) Amt ));
00205     }
00206 
00207     case BO_LT:
00208       return &getTruthValue( V1 < V2 );
00209 
00210     case BO_GT:
00211       return &getTruthValue( V1 > V2 );
00212 
00213     case BO_LE:
00214       return &getTruthValue( V1 <= V2 );
00215 
00216     case BO_GE:
00217       return &getTruthValue( V1 >= V2 );
00218 
00219     case BO_EQ:
00220       return &getTruthValue( V1 == V2 );
00221 
00222     case BO_NE:
00223       return &getTruthValue( V1 != V2 );
00224 
00225       // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
00226 
00227     case BO_And:
00228       return &getValue( V1 & V2 );
00229 
00230     case BO_Or:
00231       return &getValue( V1 | V2 );
00232 
00233     case BO_Xor:
00234       return &getValue( V1 ^ V2 );
00235   }
00236 }
00237 
00238 
00239 const std::pair<SVal, uintptr_t>&
00240 BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
00241 
00242   // Lazily create the folding set.
00243   if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
00244 
00245   llvm::FoldingSetNodeID ID;
00246   void *InsertPos;
00247   V.Profile(ID);
00248   ID.AddPointer((void*) Data);
00249 
00250   PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
00251 
00252   typedef llvm::FoldingSetNodeWrapper<SValData> FoldNodeTy;
00253   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
00254 
00255   if (!P) {
00256     P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
00257     new (P) FoldNodeTy(std::make_pair(V, Data));
00258     Map.InsertNode(P, InsertPos);
00259   }
00260 
00261   return P->getValue();
00262 }
00263 
00264 const std::pair<SVal, SVal>&
00265 BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
00266 
00267   // Lazily create the folding set.
00268   if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
00269 
00270   llvm::FoldingSetNodeID ID;
00271   void *InsertPos;
00272   V1.Profile(ID);
00273   V2.Profile(ID);
00274 
00275   PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
00276 
00277   typedef llvm::FoldingSetNodeWrapper<SValPair> FoldNodeTy;
00278   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
00279 
00280   if (!P) {
00281     P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
00282     new (P) FoldNodeTy(std::make_pair(V1, V2));
00283     Map.InsertNode(P, InsertPos);
00284   }
00285 
00286   return P->getValue();
00287 }
00288 
00289 const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
00290   return &getPersistentSValWithData(X, 0).first;
00291 }