SVals.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. //===-- SVals.cpp - Abstract RValues for Path-Sens. Value Tracking --------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines SVal, Loc, and NonLoc, classes that represent
  10. // abstract r-values for use with path-sensitive value tracking.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  14. #include "clang/AST/Decl.h"
  15. #include "clang/AST/DeclCXX.h"
  16. #include "clang/AST/Expr.h"
  17. #include "clang/AST/Type.h"
  18. #include "clang/Basic/JsonSupport.h"
  19. #include "clang/Basic/LLVM.h"
  20. #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
  24. #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
  25. #include "llvm/ADT/Optional.h"
  26. #include "llvm/Support/Casting.h"
  27. #include "llvm/Support/Compiler.h"
  28. #include "llvm/Support/ErrorHandling.h"
  29. #include "llvm/Support/raw_ostream.h"
  30. #include <cassert>
  31. using namespace clang;
  32. using namespace ento;
  33. //===----------------------------------------------------------------------===//
  34. // Symbol iteration within an SVal.
  35. //===----------------------------------------------------------------------===//
  36. //===----------------------------------------------------------------------===//
  37. // Utility methods.
  38. //===----------------------------------------------------------------------===//
  39. bool SVal::hasConjuredSymbol() const {
  40. if (Optional<nonloc::SymbolVal> SV = getAs<nonloc::SymbolVal>()) {
  41. SymbolRef sym = SV->getSymbol();
  42. if (isa<SymbolConjured>(sym))
  43. return true;
  44. }
  45. if (Optional<loc::MemRegionVal> RV = getAs<loc::MemRegionVal>()) {
  46. const MemRegion *R = RV->getRegion();
  47. if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
  48. SymbolRef sym = SR->getSymbol();
  49. if (isa<SymbolConjured>(sym))
  50. return true;
  51. }
  52. }
  53. return false;
  54. }
  55. const FunctionDecl *SVal::getAsFunctionDecl() const {
  56. if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
  57. const MemRegion* R = X->getRegion();
  58. if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
  59. if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
  60. return FD;
  61. }
  62. if (auto X = getAs<nonloc::PointerToMember>()) {
  63. if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
  64. return MD;
  65. }
  66. return nullptr;
  67. }
  68. /// If this SVal is a location (subclasses Loc) and wraps a symbol,
  69. /// return that SymbolRef. Otherwise return 0.
  70. ///
  71. /// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element
  72. /// region. If that is the case, gets the underlining region.
  73. /// When IncludeBaseRegions is set to true and the SubRegion is non-symbolic,
  74. /// the first symbolic parent region is returned.
  75. SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
  76. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
  77. if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
  78. return X->getLoc().getAsLocSymbol(IncludeBaseRegions);
  79. if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
  80. const MemRegion *R = X->getRegion();
  81. if (const SymbolicRegion *SymR = IncludeBaseRegions ?
  82. R->getSymbolicBase() :
  83. dyn_cast<SymbolicRegion>(R->StripCasts()))
  84. return SymR->getSymbol();
  85. }
  86. return nullptr;
  87. }
  88. /// Get the symbol in the SVal or its base region.
  89. SymbolRef SVal::getLocSymbolInBase() const {
  90. Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
  91. if (!X)
  92. return nullptr;
  93. const MemRegion *R = X->getRegion();
  94. while (const auto *SR = dyn_cast<SubRegion>(R)) {
  95. if (const auto *SymR = dyn_cast<SymbolicRegion>(SR))
  96. return SymR->getSymbol();
  97. else
  98. R = SR->getSuperRegion();
  99. }
  100. return nullptr;
  101. }
  102. // TODO: The next 3 functions have to be simplified.
  103. /// If this SVal wraps a symbol return that SymbolRef.
  104. /// Otherwise, return 0.
  105. ///
  106. /// Casts are ignored during lookup.
  107. /// \param IncludeBaseRegions The boolean that controls whether the search
  108. /// should continue to the base regions if the region is not symbolic.
  109. SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
  110. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
  111. if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
  112. return X->getSymbol();
  113. return getAsLocSymbol(IncludeBaseRegions);
  114. }
  115. /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
  116. /// return that expression. Otherwise return NULL.
  117. const SymExpr *SVal::getAsSymbolicExpression() const {
  118. if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
  119. return X->getSymbol();
  120. return getAsSymbol();
  121. }
  122. const SymExpr* SVal::getAsSymExpr() const {
  123. const SymExpr* Sym = getAsSymbol();
  124. if (!Sym)
  125. Sym = getAsSymbolicExpression();
  126. return Sym;
  127. }
  128. const MemRegion *SVal::getAsRegion() const {
  129. if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
  130. return X->getRegion();
  131. if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
  132. return X->getLoc().getAsRegion();
  133. return nullptr;
  134. }
  135. const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
  136. const MemRegion *R = getRegion();
  137. return R ? R->StripCasts(StripBaseCasts) : nullptr;
  138. }
  139. const void *nonloc::LazyCompoundVal::getStore() const {
  140. return static_cast<const LazyCompoundValData*>(Data)->getStore();
  141. }
  142. const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
  143. return static_cast<const LazyCompoundValData*>(Data)->getRegion();
  144. }
  145. bool nonloc::PointerToMember::isNullMemberPointer() const {
  146. return getPTMData().isNull();
  147. }
  148. const DeclaratorDecl *nonloc::PointerToMember::getDecl() const {
  149. const auto PTMD = this->getPTMData();
  150. if (PTMD.isNull())
  151. return nullptr;
  152. const DeclaratorDecl *DD = nullptr;
  153. if (PTMD.is<const DeclaratorDecl *>())
  154. DD = PTMD.get<const DeclaratorDecl *>();
  155. else
  156. DD = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl();
  157. return DD;
  158. }
  159. //===----------------------------------------------------------------------===//
  160. // Other Iterators.
  161. //===----------------------------------------------------------------------===//
  162. nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
  163. return getValue()->begin();
  164. }
  165. nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
  166. return getValue()->end();
  167. }
  168. nonloc::PointerToMember::iterator nonloc::PointerToMember::begin() const {
  169. const PTMDataType PTMD = getPTMData();
  170. if (PTMD.is<const DeclaratorDecl *>())
  171. return {};
  172. return PTMD.get<const PointerToMemberData *>()->begin();
  173. }
  174. nonloc::PointerToMember::iterator nonloc::PointerToMember::end() const {
  175. const PTMDataType PTMD = getPTMData();
  176. if (PTMD.is<const DeclaratorDecl *>())
  177. return {};
  178. return PTMD.get<const PointerToMemberData *>()->end();
  179. }
  180. //===----------------------------------------------------------------------===//
  181. // Useful predicates.
  182. //===----------------------------------------------------------------------===//
  183. bool SVal::isConstant() const {
  184. return getAs<nonloc::ConcreteInt>() || getAs<loc::ConcreteInt>();
  185. }
  186. bool SVal::isConstant(int I) const {
  187. if (Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
  188. return LV->getValue() == I;
  189. if (Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
  190. return NV->getValue() == I;
  191. return false;
  192. }
  193. bool SVal::isZeroConstant() const {
  194. return isConstant(0);
  195. }
  196. //===----------------------------------------------------------------------===//
  197. // Transfer function dispatch for Non-Locs.
  198. //===----------------------------------------------------------------------===//
  199. SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder,
  200. BinaryOperator::Opcode Op,
  201. const nonloc::ConcreteInt& R) const {
  202. const llvm::APSInt* X =
  203. svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
  204. if (X)
  205. return nonloc::ConcreteInt(*X);
  206. else
  207. return UndefinedVal();
  208. }
  209. nonloc::ConcreteInt
  210. nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const {
  211. return svalBuilder.makeIntVal(~getValue());
  212. }
  213. nonloc::ConcreteInt
  214. nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
  215. return svalBuilder.makeIntVal(-getValue());
  216. }
  217. //===----------------------------------------------------------------------===//
  218. // Transfer function dispatch for Locs.
  219. //===----------------------------------------------------------------------===//
  220. SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
  221. BinaryOperator::Opcode Op,
  222. const loc::ConcreteInt& R) const {
  223. assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub);
  224. const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
  225. if (X)
  226. return nonloc::ConcreteInt(*X);
  227. else
  228. return UndefinedVal();
  229. }
  230. //===----------------------------------------------------------------------===//
  231. // Pretty-Printing.
  232. //===----------------------------------------------------------------------===//
  233. LLVM_DUMP_METHOD void SVal::dump() const { dumpToStream(llvm::errs()); }
  234. void SVal::printJson(raw_ostream &Out, bool AddQuotes) const {
  235. std::string Buf;
  236. llvm::raw_string_ostream TempOut(Buf);
  237. dumpToStream(TempOut);
  238. Out << JsonFormat(TempOut.str(), AddQuotes);
  239. }
  240. void SVal::dumpToStream(raw_ostream &os) const {
  241. switch (getBaseKind()) {
  242. case UnknownValKind:
  243. os << "Unknown";
  244. break;
  245. case NonLocKind:
  246. castAs<NonLoc>().dumpToStream(os);
  247. break;
  248. case LocKind:
  249. castAs<Loc>().dumpToStream(os);
  250. break;
  251. case UndefinedValKind:
  252. os << "Undefined";
  253. break;
  254. }
  255. }
  256. void NonLoc::dumpToStream(raw_ostream &os) const {
  257. switch (getSubKind()) {
  258. case nonloc::ConcreteIntKind: {
  259. const auto &Value = castAs<nonloc::ConcreteInt>().getValue();
  260. os << Value << ' ' << (Value.isSigned() ? 'S' : 'U')
  261. << Value.getBitWidth() << 'b';
  262. break;
  263. }
  264. case nonloc::SymbolValKind:
  265. os << castAs<nonloc::SymbolVal>().getSymbol();
  266. break;
  267. case nonloc::LocAsIntegerKind: {
  268. const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
  269. os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
  270. break;
  271. }
  272. case nonloc::CompoundValKind: {
  273. const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
  274. os << "compoundVal{";
  275. bool first = true;
  276. for (const auto &I : C) {
  277. if (first) {
  278. os << ' '; first = false;
  279. }
  280. else
  281. os << ", ";
  282. I.dumpToStream(os);
  283. }
  284. os << "}";
  285. break;
  286. }
  287. case nonloc::LazyCompoundValKind: {
  288. const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
  289. os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
  290. << ',' << C.getRegion()
  291. << '}';
  292. break;
  293. }
  294. case nonloc::PointerToMemberKind: {
  295. os << "pointerToMember{";
  296. const nonloc::PointerToMember &CastRes =
  297. castAs<nonloc::PointerToMember>();
  298. if (CastRes.getDecl())
  299. os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|";
  300. bool first = true;
  301. for (const auto &I : CastRes) {
  302. if (first) {
  303. os << ' '; first = false;
  304. }
  305. else
  306. os << ", ";
  307. os << (*I).getType().getAsString();
  308. }
  309. os << '}';
  310. break;
  311. }
  312. default:
  313. assert(false && "Pretty-printed not implemented for this NonLoc.");
  314. break;
  315. }
  316. }
  317. void Loc::dumpToStream(raw_ostream &os) const {
  318. switch (getSubKind()) {
  319. case loc::ConcreteIntKind:
  320. os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
  321. break;
  322. case loc::GotoLabelKind:
  323. os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
  324. break;
  325. case loc::MemRegionValKind:
  326. os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
  327. break;
  328. default:
  329. llvm_unreachable("Pretty-printing not implemented for this Loc.");
  330. }
  331. }