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