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