SVals.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  15. #include "clang/AST/ExprObjC.h"
  16. #include "clang/Basic/IdentifierTable.h"
  17. #include "llvm/Support/raw_ostream.h"
  18. using namespace clang;
  19. using namespace ento;
  20. using llvm::APSInt;
  21. //===----------------------------------------------------------------------===//
  22. // Symbol iteration within an SVal.
  23. //===----------------------------------------------------------------------===//
  24. //===----------------------------------------------------------------------===//
  25. // Utility methods.
  26. //===----------------------------------------------------------------------===//
  27. bool SVal::hasConjuredSymbol() const {
  28. if (Optional<nonloc::SymbolVal> SV = getAs<nonloc::SymbolVal>()) {
  29. SymbolRef sym = SV->getSymbol();
  30. if (isa<SymbolConjured>(sym))
  31. return true;
  32. }
  33. if (Optional<loc::MemRegionVal> RV = getAs<loc::MemRegionVal>()) {
  34. const MemRegion *R = RV->getRegion();
  35. if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
  36. SymbolRef sym = SR->getSymbol();
  37. if (isa<SymbolConjured>(sym))
  38. return true;
  39. }
  40. }
  41. return false;
  42. }
  43. const FunctionDecl *SVal::getAsFunctionDecl() const {
  44. if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
  45. const MemRegion* R = X->getRegion();
  46. if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
  47. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
  48. return FD;
  49. }
  50. return nullptr;
  51. }
  52. /// \brief If this SVal is a location (subclasses Loc) and wraps a symbol,
  53. /// return that SymbolRef. Otherwise return 0.
  54. ///
  55. /// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element
  56. /// region. If that is the case, gets the underlining region.
  57. /// When IncludeBaseRegions is set to true and the SubRegion is non-symbolic,
  58. /// the first symbolic parent region is returned.
  59. SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
  60. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
  61. if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
  62. return X->getLoc().getAsLocSymbol();
  63. if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
  64. const MemRegion *R = X->getRegion();
  65. if (const SymbolicRegion *SymR = IncludeBaseRegions ?
  66. R->getSymbolicBase() :
  67. dyn_cast<SymbolicRegion>(R->StripCasts()))
  68. return SymR->getSymbol();
  69. }
  70. return nullptr;
  71. }
  72. /// Get the symbol in the SVal or its base region.
  73. SymbolRef SVal::getLocSymbolInBase() const {
  74. Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
  75. if (!X)
  76. return nullptr;
  77. const MemRegion *R = X->getRegion();
  78. while (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
  79. if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SR))
  80. return SymR->getSymbol();
  81. else
  82. R = SR->getSuperRegion();
  83. }
  84. return nullptr;
  85. }
  86. // TODO: The next 3 functions have to be simplified.
  87. /// \brief If this SVal wraps a symbol return that SymbolRef.
  88. /// Otherwise, return 0.
  89. ///
  90. /// Casts are ignored during lookup.
  91. /// \param IncludeBaseRegions The boolean that controls whether the search
  92. /// should continue to the base regions if the region is not symbolic.
  93. SymbolRef SVal::getAsSymbol(bool IncludeBaseRegion) const {
  94. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
  95. if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
  96. return X->getSymbol();
  97. return getAsLocSymbol(IncludeBaseRegion);
  98. }
  99. /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
  100. /// return that expression. Otherwise return NULL.
  101. const SymExpr *SVal::getAsSymbolicExpression() const {
  102. if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
  103. return X->getSymbol();
  104. return getAsSymbol();
  105. }
  106. const SymExpr* SVal::getAsSymExpr() const {
  107. const SymExpr* Sym = getAsSymbol();
  108. if (!Sym)
  109. Sym = getAsSymbolicExpression();
  110. return Sym;
  111. }
  112. const MemRegion *SVal::getAsRegion() const {
  113. if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
  114. return X->getRegion();
  115. if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
  116. return X->getLoc().getAsRegion();
  117. return nullptr;
  118. }
  119. const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
  120. const MemRegion *R = getRegion();
  121. return R ? R->StripCasts(StripBaseCasts) : nullptr;
  122. }
  123. const void *nonloc::LazyCompoundVal::getStore() const {
  124. return static_cast<const LazyCompoundValData*>(Data)->getStore();
  125. }
  126. const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
  127. return static_cast<const LazyCompoundValData*>(Data)->getRegion();
  128. }
  129. //===----------------------------------------------------------------------===//
  130. // Other Iterators.
  131. //===----------------------------------------------------------------------===//
  132. nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
  133. return getValue()->begin();
  134. }
  135. nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
  136. return getValue()->end();
  137. }
  138. //===----------------------------------------------------------------------===//
  139. // Useful predicates.
  140. //===----------------------------------------------------------------------===//
  141. bool SVal::isConstant() const {
  142. return getAs<nonloc::ConcreteInt>() || getAs<loc::ConcreteInt>();
  143. }
  144. bool SVal::isConstant(int I) const {
  145. if (Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
  146. return LV->getValue() == I;
  147. if (Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
  148. return NV->getValue() == I;
  149. return false;
  150. }
  151. bool SVal::isZeroConstant() const {
  152. return isConstant(0);
  153. }
  154. //===----------------------------------------------------------------------===//
  155. // Transfer function dispatch for Non-Locs.
  156. //===----------------------------------------------------------------------===//
  157. SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder,
  158. BinaryOperator::Opcode Op,
  159. const nonloc::ConcreteInt& R) const {
  160. const llvm::APSInt* X =
  161. svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
  162. if (X)
  163. return nonloc::ConcreteInt(*X);
  164. else
  165. return UndefinedVal();
  166. }
  167. nonloc::ConcreteInt
  168. nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const {
  169. return svalBuilder.makeIntVal(~getValue());
  170. }
  171. nonloc::ConcreteInt
  172. nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
  173. return svalBuilder.makeIntVal(-getValue());
  174. }
  175. //===----------------------------------------------------------------------===//
  176. // Transfer function dispatch for Locs.
  177. //===----------------------------------------------------------------------===//
  178. SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
  179. BinaryOperator::Opcode Op,
  180. const loc::ConcreteInt& R) const {
  181. assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub);
  182. const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
  183. if (X)
  184. return nonloc::ConcreteInt(*X);
  185. else
  186. return UndefinedVal();
  187. }
  188. //===----------------------------------------------------------------------===//
  189. // Pretty-Printing.
  190. //===----------------------------------------------------------------------===//
  191. void SVal::dump() const { dumpToStream(llvm::errs()); }
  192. void SVal::dumpToStream(raw_ostream &os) const {
  193. switch (getBaseKind()) {
  194. case UnknownKind:
  195. os << "Unknown";
  196. break;
  197. case NonLocKind:
  198. castAs<NonLoc>().dumpToStream(os);
  199. break;
  200. case LocKind:
  201. castAs<Loc>().dumpToStream(os);
  202. break;
  203. case UndefinedKind:
  204. os << "Undefined";
  205. break;
  206. }
  207. }
  208. void NonLoc::dumpToStream(raw_ostream &os) const {
  209. switch (getSubKind()) {
  210. case nonloc::ConcreteIntKind: {
  211. const nonloc::ConcreteInt& C = castAs<nonloc::ConcreteInt>();
  212. if (C.getValue().isUnsigned())
  213. os << C.getValue().getZExtValue();
  214. else
  215. os << C.getValue().getSExtValue();
  216. os << ' ' << (C.getValue().isUnsigned() ? 'U' : 'S')
  217. << C.getValue().getBitWidth() << 'b';
  218. break;
  219. }
  220. case nonloc::SymbolValKind: {
  221. os << castAs<nonloc::SymbolVal>().getSymbol();
  222. break;
  223. }
  224. case nonloc::LocAsIntegerKind: {
  225. const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
  226. os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
  227. break;
  228. }
  229. case nonloc::CompoundValKind: {
  230. const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
  231. os << "compoundVal{";
  232. bool first = true;
  233. for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
  234. if (first) {
  235. os << ' '; first = false;
  236. }
  237. else
  238. os << ", ";
  239. (*I).dumpToStream(os);
  240. }
  241. os << "}";
  242. break;
  243. }
  244. case nonloc::LazyCompoundValKind: {
  245. const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
  246. os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
  247. << ',' << C.getRegion()
  248. << '}';
  249. break;
  250. }
  251. default:
  252. assert (false && "Pretty-printed not implemented for this NonLoc.");
  253. break;
  254. }
  255. }
  256. void Loc::dumpToStream(raw_ostream &os) const {
  257. switch (getSubKind()) {
  258. case loc::ConcreteIntKind:
  259. os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
  260. break;
  261. case loc::GotoLabelKind:
  262. os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
  263. break;
  264. case loc::MemRegionKind:
  265. os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
  266. break;
  267. default:
  268. llvm_unreachable("Pretty-printing not implemented for this Loc.");
  269. }
  270. }