clang API Documentation

SVals.cpp
Go to the documentation of this file.
00001 //= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- 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 SVal, Loc, and NonLoc, classes that represent
00011 //  abstract r-values for use with path-sensitive value tracking.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
00016 #include "clang/AST/ExprObjC.h"
00017 #include "clang/Basic/IdentifierTable.h"
00018 #include "llvm/Support/raw_ostream.h"
00019 using namespace clang;
00020 using namespace ento;
00021 using llvm::APSInt;
00022 
00023 //===----------------------------------------------------------------------===//
00024 // Symbol iteration within an SVal.
00025 //===----------------------------------------------------------------------===//
00026 
00027 
00028 //===----------------------------------------------------------------------===//
00029 // Utility methods.
00030 //===----------------------------------------------------------------------===//
00031 
00032 bool SVal::hasConjuredSymbol() const {
00033   if (Optional<nonloc::SymbolVal> SV = getAs<nonloc::SymbolVal>()) {
00034     SymbolRef sym = SV->getSymbol();
00035     if (isa<SymbolConjured>(sym))
00036       return true;
00037   }
00038 
00039   if (Optional<loc::MemRegionVal> RV = getAs<loc::MemRegionVal>()) {
00040     const MemRegion *R = RV->getRegion();
00041     if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
00042       SymbolRef sym = SR->getSymbol();
00043       if (isa<SymbolConjured>(sym))
00044         return true;
00045     }
00046   }
00047 
00048   return false;
00049 }
00050 
00051 const FunctionDecl *SVal::getAsFunctionDecl() const {
00052   if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
00053     const MemRegion* R = X->getRegion();
00054     if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
00055       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
00056         return FD;
00057   }
00058 
00059   return nullptr;
00060 }
00061 
00062 /// \brief If this SVal is a location (subclasses Loc) and wraps a symbol,
00063 /// return that SymbolRef.  Otherwise return 0.
00064 ///
00065 /// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element
00066 /// region. If that is the case, gets the underlining region.
00067 /// When IncludeBaseRegions is set to true and the SubRegion is non-symbolic,
00068 /// the first symbolic parent region is returned.
00069 SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
00070   // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
00071   if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
00072     return X->getLoc().getAsLocSymbol();
00073 
00074   if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
00075     const MemRegion *R = X->getRegion();
00076     if (const SymbolicRegion *SymR = IncludeBaseRegions ?
00077                                       R->getSymbolicBase() :
00078                                       dyn_cast<SymbolicRegion>(R->StripCasts()))
00079       return SymR->getSymbol();
00080   }
00081   return nullptr;
00082 }
00083 
00084 /// Get the symbol in the SVal or its base region.
00085 SymbolRef SVal::getLocSymbolInBase() const {
00086   Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
00087 
00088   if (!X)
00089     return nullptr;
00090 
00091   const MemRegion *R = X->getRegion();
00092 
00093   while (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
00094     if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SR))
00095       return SymR->getSymbol();
00096     else
00097       R = SR->getSuperRegion();
00098   }
00099 
00100   return nullptr;
00101 }
00102 
00103 // TODO: The next 3 functions have to be simplified.
00104 
00105 /// \brief If this SVal wraps a symbol return that SymbolRef.
00106 /// Otherwise, return 0.
00107 ///
00108 /// Casts are ignored during lookup.
00109 /// \param IncludeBaseRegions The boolean that controls whether the search
00110 /// should continue to the base regions if the region is not symbolic.
00111 SymbolRef SVal::getAsSymbol(bool IncludeBaseRegion) const {
00112   // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
00113   if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
00114     return X->getSymbol();
00115 
00116   return getAsLocSymbol(IncludeBaseRegion);
00117 }
00118 
00119 /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
00120 ///  return that expression.  Otherwise return NULL.
00121 const SymExpr *SVal::getAsSymbolicExpression() const {
00122   if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
00123     return X->getSymbol();
00124 
00125   return getAsSymbol();
00126 }
00127 
00128 const SymExpr* SVal::getAsSymExpr() const {
00129   const SymExpr* Sym = getAsSymbol();
00130   if (!Sym)
00131     Sym = getAsSymbolicExpression();
00132   return Sym;
00133 }
00134 
00135 const MemRegion *SVal::getAsRegion() const {
00136   if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
00137     return X->getRegion();
00138 
00139   if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
00140     return X->getLoc().getAsRegion();
00141 
00142   return nullptr;
00143 }
00144 
00145 const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
00146   const MemRegion *R = getRegion();
00147   return R ?  R->StripCasts(StripBaseCasts) : nullptr;
00148 }
00149 
00150 const void *nonloc::LazyCompoundVal::getStore() const {
00151   return static_cast<const LazyCompoundValData*>(Data)->getStore();
00152 }
00153 
00154 const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
00155   return static_cast<const LazyCompoundValData*>(Data)->getRegion();
00156 }
00157 
00158 //===----------------------------------------------------------------------===//
00159 // Other Iterators.
00160 //===----------------------------------------------------------------------===//
00161 
00162 nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
00163   return getValue()->begin();
00164 }
00165 
00166 nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
00167   return getValue()->end();
00168 }
00169 
00170 //===----------------------------------------------------------------------===//
00171 // Useful predicates.
00172 //===----------------------------------------------------------------------===//
00173 
00174 bool SVal::isConstant() const {
00175   return getAs<nonloc::ConcreteInt>() || getAs<loc::ConcreteInt>();
00176 }
00177 
00178 bool SVal::isConstant(int I) const {
00179   if (Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
00180     return LV->getValue() == I;
00181   if (Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
00182     return NV->getValue() == I;
00183   return false;
00184 }
00185 
00186 bool SVal::isZeroConstant() const {
00187   return isConstant(0);
00188 }
00189 
00190 
00191 //===----------------------------------------------------------------------===//
00192 // Transfer function dispatch for Non-Locs.
00193 //===----------------------------------------------------------------------===//
00194 
00195 SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder,
00196                                     BinaryOperator::Opcode Op,
00197                                     const nonloc::ConcreteInt& R) const {
00198   const llvm::APSInt* X =
00199     svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
00200 
00201   if (X)
00202     return nonloc::ConcreteInt(*X);
00203   else
00204     return UndefinedVal();
00205 }
00206 
00207 nonloc::ConcreteInt
00208 nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const {
00209   return svalBuilder.makeIntVal(~getValue());
00210 }
00211 
00212 nonloc::ConcreteInt
00213 nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
00214   return svalBuilder.makeIntVal(-getValue());
00215 }
00216 
00217 //===----------------------------------------------------------------------===//
00218 // Transfer function dispatch for Locs.
00219 //===----------------------------------------------------------------------===//
00220 
00221 SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
00222                                  BinaryOperator::Opcode Op,
00223                                  const loc::ConcreteInt& R) const {
00224 
00225   assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub);
00226 
00227   const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
00228 
00229   if (X)
00230     return nonloc::ConcreteInt(*X);
00231   else
00232     return UndefinedVal();
00233 }
00234 
00235 //===----------------------------------------------------------------------===//
00236 // Pretty-Printing.
00237 //===----------------------------------------------------------------------===//
00238 
00239 void SVal::dump() const { dumpToStream(llvm::errs()); }
00240 
00241 void SVal::dumpToStream(raw_ostream &os) const {
00242   switch (getBaseKind()) {
00243     case UnknownKind:
00244       os << "Unknown";
00245       break;
00246     case NonLocKind:
00247       castAs<NonLoc>().dumpToStream(os);
00248       break;
00249     case LocKind:
00250       castAs<Loc>().dumpToStream(os);
00251       break;
00252     case UndefinedKind:
00253       os << "Undefined";
00254       break;
00255   }
00256 }
00257 
00258 void NonLoc::dumpToStream(raw_ostream &os) const {
00259   switch (getSubKind()) {
00260     case nonloc::ConcreteIntKind: {
00261       const nonloc::ConcreteInt& C = castAs<nonloc::ConcreteInt>();
00262       if (C.getValue().isUnsigned())
00263         os << C.getValue().getZExtValue();
00264       else
00265         os << C.getValue().getSExtValue();
00266       os << ' ' << (C.getValue().isUnsigned() ? 'U' : 'S')
00267          << C.getValue().getBitWidth() << 'b';
00268       break;
00269     }
00270     case nonloc::SymbolValKind: {
00271       os << castAs<nonloc::SymbolVal>().getSymbol();
00272       break;
00273     }
00274     case nonloc::LocAsIntegerKind: {
00275       const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
00276       os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
00277       break;
00278     }
00279     case nonloc::CompoundValKind: {
00280       const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
00281       os << "compoundVal{";
00282       bool first = true;
00283       for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
00284         if (first) {
00285           os << ' '; first = false;
00286         }
00287         else
00288           os << ", ";
00289 
00290         (*I).dumpToStream(os);
00291       }
00292       os << "}";
00293       break;
00294     }
00295     case nonloc::LazyCompoundValKind: {
00296       const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
00297       os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
00298          << ',' << C.getRegion()
00299          << '}';
00300       break;
00301     }
00302     default:
00303       assert (false && "Pretty-printed not implemented for this NonLoc.");
00304       break;
00305   }
00306 }
00307 
00308 void Loc::dumpToStream(raw_ostream &os) const {
00309   switch (getSubKind()) {
00310     case loc::ConcreteIntKind:
00311       os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
00312       break;
00313     case loc::GotoLabelKind:
00314       os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
00315       break;
00316     case loc::MemRegionKind:
00317       os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
00318       break;
00319     default:
00320       llvm_unreachable("Pretty-printing not implemented for this Loc.");
00321   }
00322 }