zcov: / lib/Checker/SVals.cpp


Files: 1 Branches Taken: 39.1% 36 / 92
Generated: 2010-02-10 01:31 Branches Executed: 47.8% 44 / 92
Line Coverage: 48.4% 76 / 157


Programs: 1 Runs 2897


       1                 : //= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- C++ -*-==//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : //  This file defines SVal, Loc, and NonLoc, classes that represent
      11                 : //  abstract r-values for use with path-sensitive value tracking.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "clang/Checker/PathSensitive/GRState.h"
      16                 : #include "clang/Basic/IdentifierTable.h"
      17                 : 
      18                 : using namespace clang;
      19                 : using llvm::dyn_cast;
      20                 : using llvm::cast;
      21                 : using llvm::APSInt;
      22                 : 
      23                 : //===----------------------------------------------------------------------===//
      24                 : // Symbol iteration within an SVal.
      25                 : //===----------------------------------------------------------------------===//
      26                 : 
      27                 : 
      28                 : //===----------------------------------------------------------------------===//
      29                 : // Utility methods.
      30                 : //===----------------------------------------------------------------------===//
      31                 : 
      32                0: bool SVal::hasConjuredSymbol() const {
                        0: branch 1 not taken
                        0: branch 2 not taken
      33                0:   if (const nonloc::SymbolVal* SV = dyn_cast<nonloc::SymbolVal>(this)) {
      34                0:     SymbolRef sym = SV->getSymbol();
                        0: branch 1 not taken
                        0: branch 2 not taken
      35                0:     if (isa<SymbolConjured>(sym))
      36                0:       return true;
      37                 :   }
      38                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
      39                0:   if (const loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(this)) {
      40                0:     const MemRegion *R = RV->getRegion();
                        0: branch 1 not taken
                        0: branch 2 not taken
      41                0:     if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
      42                0:       SymbolRef sym = SR->getSymbol();
                        0: branch 1 not taken
                        0: branch 2 not taken
      43                0:       if (isa<SymbolConjured>(sym))
      44                0:         return true;
      45                 :     }
      46                 :   }
      47                 : 
      48                0:   return false;
      49                 : }
      50                 : 
      51            11578: const FunctionDecl *SVal::getAsFunctionDecl() const {
                    11444: branch 1 taken
                      134: branch 2 taken
      52            11578:   if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
      53            11444:     const MemRegion* R = X->getRegion();
                    11092: branch 1 taken
                      352: branch 2 taken
      54            11444:     if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
      55            11092:       return CTR->getDecl();
      56                 :   }
      57                 : 
      58              486:   return NULL;
      59                 : }
      60                 : 
      61                 : /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
      62                 : ///  wraps a symbol, return that SymbolRef.  Otherwise return 0.
      63                 : // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
      64            39871: SymbolRef SVal::getAsLocSymbol() const {
                    17692: branch 1 taken
                    22179: branch 2 taken
      65            39871:   if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
      66            17692:     const MemRegion *R = X->StripCasts();
                    15257: branch 1 taken
                     2435: branch 2 taken
      67            17692:     if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
      68            15257:       return SymR->getSymbol();
      69                 :   }
      70            24614:   return NULL;
      71                 : }
      72                 : 
      73                 : /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
      74                 : ///  Otherwise return 0.
      75                 : // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
      76            41214: SymbolRef SVal::getAsSymbol() const {
                     7921: branch 1 taken
                    33293: branch 2 taken
      77            41214:   if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
      78             7921:     return X->getSymbol();
      79                 : 
                      461: branch 1 taken
                    32832: branch 2 taken
      80            33293:   if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
                        0: branch 2 not taken
                      461: branch 3 taken
      81              461:     if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
      82                0:       return Y;
      83                 : 
      84            33293:   return getAsLocSymbol();
      85                 : }
      86                 : 
      87                 : /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
      88                 : ///  return that expression.  Otherwise return NULL.
      89            34454: const SymExpr *SVal::getAsSymbolicExpression() const {
                      220: branch 1 taken
                    34234: branch 2 taken
      90            34454:   if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
      91              220:     return X->getSymbolicExpression();
      92                 : 
      93            34234:   return getAsSymbol();
      94                 : }
      95                 : 
      96            33059: const MemRegion *SVal::getAsRegion() const {
                    25947: branch 1 taken
                     7112: branch 2 taken
      97            33059:   if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this))
      98            25947:     return X->getRegion();
      99                 : 
                       17: branch 1 taken
                     7095: branch 2 taken
     100             7112:   if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this)) {
     101               17:     return X->getLoc().getAsRegion();
     102                 :   }
     103                 : 
     104             7095:   return 0;
     105                 : }
     106                 : 
     107            17934: const MemRegion *loc::MemRegionVal::StripCasts() const {
     108            17934:   const MemRegion *R = getRegion();
                    17934: branch 0 taken
                        0: branch 1 not taken
     109            17934:   return R ?  R->StripCasts() : NULL;
     110                 : }
     111                 : 
     112                0: bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
     113                0:   return itr == X.itr;
     114                 : }
     115                 : 
     116            45483: bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
     117            45483:   return itr != X.itr;
     118                 : }
     119                 : 
     120            15244: SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
     121            15244:   itr.push_back(SE);
                      198: branch 3 taken
                    15244: branch 4 taken
                        0: branch 8 not taken
                        0: branch 9 not taken
     122            15244:   while (!isa<SymbolData>(itr.back())) expand();
     123            15244: }
     124                 : 
     125            15244: SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
                    15244: branch 1 taken
                        0: branch 2 not taken
     126            15244:   assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
                        0: branch 2 not taken
                    15244: branch 3 taken
     127            15244:   assert(isa<SymbolData>(itr.back()));
     128            15244:   itr.pop_back();
                        0: branch 1 not taken
                    15244: branch 2 taken
     129            15244:   if (!itr.empty())
                        0: branch 3 not taken
                        0: branch 4 not taken
     130                0:     while (!isa<SymbolData>(itr.back())) expand();
     131            15244:   return *this;
     132                 : }
     133                 : 
     134            15244: SymbolRef SVal::symbol_iterator::operator*() {
                    15244: branch 1 taken
                        0: branch 2 not taken
     135            15244:   assert(!itr.empty() && "attempting to dereference an 'end' iterator");
     136            15244:   return cast<SymbolData>(itr.back());
     137                 : }
     138                 : 
     139              198: void SVal::symbol_iterator::expand() {
     140              198:   const SymExpr *SE = itr.back();
     141              198:   itr.pop_back();
     142                 : 
                      198: branch 1 taken
                        0: branch 2 not taken
     143              198:   if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
     144              198:     itr.push_back(SIE->getLHS());
     145              198:     return;
     146                 :   }
                        0: branch 1 not taken
                        0: branch 2 not taken
     147                0:   else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
     148                0:     itr.push_back(SSE->getLHS());
     149                0:     itr.push_back(SSE->getRHS());
     150                0:     return;
     151                 :   }
     152                 : 
     153                0:   assert(false && "unhandled expansion case");
     154                 : }
     155                 : 
     156               10: const void *nonloc::LazyCompoundVal::getStore() const {
     157               10:   return static_cast<const LazyCompoundValData*>(Data)->getStore();
     158                 : }
     159                 : 
     160               10: const TypedRegion *nonloc::LazyCompoundVal::getRegion() const {
     161               10:   return static_cast<const LazyCompoundValData*>(Data)->getRegion();
     162                 : }
     163                 : 
     164                 : //===----------------------------------------------------------------------===//
     165                 : // Other Iterators.
     166                 : //===----------------------------------------------------------------------===//
     167                 : 
     168              181: nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
     169              181:   return getValue()->begin();
     170                 : }
     171                 : 
     172              181: nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
     173              181:   return getValue()->end();
     174                 : }
     175                 : 
     176                 : //===----------------------------------------------------------------------===//
     177                 : // Useful predicates.
     178                 : //===----------------------------------------------------------------------===//
     179                 : 
     180              457: bool SVal::isConstant() const {
                      427: branch 1 taken
                       30: branch 2 taken
                       55: branch 4 taken
                      372: branch 5 taken
     181              457:   return isa<nonloc::ConcreteInt>(this) || isa<loc::ConcreteInt>(this);
     182                 : }
     183                 : 
     184              425: bool SVal::isZeroConstant() const {
                       55: branch 1 taken
                      370: branch 2 taken
     185              425:   if (isa<loc::ConcreteInt>(*this))
     186               55:     return cast<loc::ConcreteInt>(*this).getValue() == 0;
                      363: branch 1 taken
                        7: branch 2 taken
     187              370:   else if (isa<nonloc::ConcreteInt>(*this))
     188              363:     return cast<nonloc::ConcreteInt>(*this).getValue() == 0;
     189                 :   else
     190                7:     return false;
     191                 : }
     192                 : 
     193                 : 
     194                 : //===----------------------------------------------------------------------===//
     195                 : // Transfer function dispatch for Non-Locs.
     196                 : //===----------------------------------------------------------------------===//
     197                 : 
     198                 : SVal nonloc::ConcreteInt::evalBinOp(ValueManager &ValMgr,
     199                 :                                     BinaryOperator::Opcode Op,
     200             1359:                                     const nonloc::ConcreteInt& R) const {
     201                 :   const llvm::APSInt* X =
     202             1359:     ValMgr.getBasicValueFactory().EvaluateAPSInt(Op, getValue(), R.getValue());
     203                 : 
                     1359: branch 0 taken
                        0: branch 1 not taken
     204             1359:   if (X)
     205             1359:     return nonloc::ConcreteInt(*X);
     206                 :   else
     207                0:     return UndefinedVal();
     208                 : }
     209                 : 
     210                 : nonloc::ConcreteInt
     211               20: nonloc::ConcreteInt::evalComplement(ValueManager &ValMgr) const {
     212               20:   return ValMgr.makeIntVal(~getValue());
     213                 : }
     214                 : 
     215               18: nonloc::ConcreteInt nonloc::ConcreteInt::evalMinus(ValueManager &ValMgr) const {
     216               18:   return ValMgr.makeIntVal(-getValue());
     217                 : }
     218                 : 
     219                 : //===----------------------------------------------------------------------===//
     220                 : // Transfer function dispatch for Locs.
     221                 : //===----------------------------------------------------------------------===//
     222                 : 
     223                 : SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
     224                 :                                  BinaryOperator::Opcode Op,
     225                0:                                  const loc::ConcreteInt& R) const {
     226                 : 
     227                 :   assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
     228                0:           (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
     229                 : 
     230                0:   const llvm::APSInt* X = BasicVals.EvaluateAPSInt(Op, getValue(), R.getValue());
     231                 : 
                        0: branch 0 not taken
                        0: branch 1 not taken
     232                0:   if (X)
     233                0:     return loc::ConcreteInt(*X);
     234                 :   else
     235                0:     return UndefinedVal();
     236                 : }
     237                 : 
     238                 : //===----------------------------------------------------------------------===//
     239                 : // Pretty-Printing.
     240                 : //===----------------------------------------------------------------------===//
     241                 : 
     242                0: void SVal::dump() const { dumpToStream(llvm::errs()); }
     243                 : 
     244                0: void SVal::dumpToStream(llvm::raw_ostream& os) const {
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     245                0:   switch (getBaseKind()) {
     246                 :     case UnknownKind:
     247                0:       os << "Invalid";
     248                0:       break;
     249                 :     case NonLocKind:
     250                0:       cast<NonLoc>(this)->dumpToStream(os);
     251                0:       break;
     252                 :     case LocKind:
     253                0:       cast<Loc>(this)->dumpToStream(os);
     254                0:       break;
     255                 :     case UndefinedKind:
     256                0:       os << "Undefined";
     257                0:       break;
     258                 :     default:
     259                0:       assert (false && "Invalid SVal.");
     260                 :   }
     261                0: }
     262                 : 
     263                0: void NonLoc::dumpToStream(llvm::raw_ostream& os) const {
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
     264                0:   switch (getSubKind()) {
     265                 :     case nonloc::ConcreteIntKind:
     266                0:       os << cast<nonloc::ConcreteInt>(this)->getValue().getZExtValue();
                        0: branch 3 not taken
                        0: branch 4 not taken
     267                0:       if (cast<nonloc::ConcreteInt>(this)->getValue().isUnsigned())
     268                0:         os << 'U';
     269                0:       break;
     270                 :     case nonloc::SymbolValKind:
     271                0:       os << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
     272                0:       break;
     273                 :     case nonloc::SymExprValKind: {
     274                0:       const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
     275                0:       const SymExpr *SE = C.getSymbolicExpression();
     276                0:       os << SE;
     277                0:       break;
     278                 :     }
     279                 :     case nonloc::LocAsIntegerKind: {
     280                0:       const nonloc::LocAsInteger& C = *cast<nonloc::LocAsInteger>(this);
     281                0:       os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
     282                0:       break;
     283                 :     }
     284                 :     case nonloc::CompoundValKind: {
     285                0:       const nonloc::CompoundVal& C = *cast<nonloc::CompoundVal>(this);
     286                0:       os << "compoundVal{";
     287                0:       bool first = true;
                        0: branch 4 not taken
                        0: branch 5 not taken
     288                0:       for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
                        0: branch 0 not taken
                        0: branch 1 not taken
     289                0:         if (first) {
     290                0:           os << ' '; first = false;
     291                 :         }
     292                 :         else
     293                0:           os << ", ";
     294                 : 
     295                0:         (*I).dumpToStream(os);
     296                 :       }
     297                0:       os << "}";
     298                0:       break;
     299                 :     }
     300                 :     case nonloc::LazyCompoundValKind: {
     301                0:       const nonloc::LazyCompoundVal &C = *cast<nonloc::LazyCompoundVal>(this);
     302                 :       os << "lazyCompoundVal{" << (void*) C.getStore() << ',' << C.getRegion()
     303                0:          << '}';
     304                0:       break;
     305                 :     }
     306                 :     default:
     307                0:       assert (false && "Pretty-printed not implemented for this NonLoc.");
     308                 :       break;
     309                 :   }
     310                0: }
     311                 : 
     312                0: void Loc::dumpToStream(llvm::raw_ostream& os) const {
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     313                0:   switch (getSubKind()) {
     314                 :     case loc::ConcreteIntKind:
     315                0:       os << cast<loc::ConcreteInt>(this)->getValue().getZExtValue() << " (Loc)";
     316                0:       break;
     317                 :     case loc::GotoLabelKind:
     318                0:       os << "&&" << cast<loc::GotoLabel>(this)->getLabel()->getID()->getName();
     319                0:       break;
     320                 :     case loc::MemRegionKind:
     321                0:       os << '&' << cast<loc::MemRegionVal>(this)->getRegion()->getString();
     322                0:       break;
     323                 :     default:
     324                0:       assert(false && "Pretty-printing not implemented for this Loc.");
     325                 :       break;
     326                 :   }
     327                0: }

Generated: 2010-02-10 01:31 by zcov