SVals.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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/ASTContext.h"
  15. #include "clang/AST/Decl.h"
  16. #include "clang/AST/DeclCXX.h"
  17. #include "clang/AST/Expr.h"
  18. #include "clang/AST/Type.h"
  19. #include "clang/Basic/JsonSupport.h"
  20. #include "clang/Basic/LLVM.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
  24. #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
  25. #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
  26. #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
  27. #include "llvm/Support/Casting.h"
  28. #include "llvm/Support/Compiler.h"
  29. #include "llvm/Support/ErrorHandling.h"
  30. #include "llvm/Support/raw_ostream.h"
  31. #include <cassert>
  32. #include <optional>
  33. using namespace clang;
  34. using namespace ento;
  35. //===----------------------------------------------------------------------===//
  36. // Symbol iteration within an SVal.
  37. //===----------------------------------------------------------------------===//
  38. //===----------------------------------------------------------------------===//
  39. // Utility methods.
  40. //===----------------------------------------------------------------------===//
  41. const FunctionDecl *SVal::getAsFunctionDecl() const {
  42. if (std::optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
  43. const MemRegion* R = X->getRegion();
  44. if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
  45. if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
  46. return FD;
  47. }
  48. if (auto X = getAs<nonloc::PointerToMember>()) {
  49. if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
  50. return MD;
  51. }
  52. return nullptr;
  53. }
  54. /// If this SVal is a location (subclasses Loc) and wraps a symbol,
  55. /// return that SymbolRef. Otherwise return 0.
  56. ///
  57. /// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element
  58. /// region. If that is the case, gets the underlining region.
  59. /// When IncludeBaseRegions is set to true and the SubRegion is non-symbolic,
  60. /// the first symbolic parent region is returned.
  61. SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
  62. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
  63. if (const MemRegion *R = getAsRegion())
  64. if (const SymbolicRegion *SymR =
  65. IncludeBaseRegions ? R->getSymbolicBase()
  66. : dyn_cast<SymbolicRegion>(R->StripCasts()))
  67. return SymR->getSymbol();
  68. return nullptr;
  69. }
  70. /// Get the symbol in the SVal or its base region.
  71. SymbolRef SVal::getLocSymbolInBase() const {
  72. std::optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
  73. if (!X)
  74. return nullptr;
  75. const MemRegion *R = X->getRegion();
  76. while (const auto *SR = dyn_cast<SubRegion>(R)) {
  77. if (const auto *SymR = dyn_cast<SymbolicRegion>(SR))
  78. return SymR->getSymbol();
  79. else
  80. R = SR->getSuperRegion();
  81. }
  82. return nullptr;
  83. }
  84. /// If this SVal wraps a symbol return that SymbolRef.
  85. /// Otherwise, return 0.
  86. ///
  87. /// Casts are ignored during lookup.
  88. /// \param IncludeBaseRegions The boolean that controls whether the search
  89. /// should continue to the base regions if the region is not symbolic.
  90. SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
  91. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
  92. if (std::optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
  93. return X->getSymbol();
  94. return getAsLocSymbol(IncludeBaseRegions);
  95. }
  96. const llvm::APSInt *SVal::getAsInteger() const {
  97. if (auto CI = getAs<nonloc::ConcreteInt>())
  98. return &CI->getValue();
  99. if (auto CI = getAs<loc::ConcreteInt>())
  100. return &CI->getValue();
  101. return nullptr;
  102. }
  103. const MemRegion *SVal::getAsRegion() const {
  104. if (std::optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
  105. return X->getRegion();
  106. if (std::optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
  107. return X->getLoc().getAsRegion();
  108. return nullptr;
  109. }
  110. namespace {
  111. class TypeRetrievingVisitor
  112. : public FullSValVisitor<TypeRetrievingVisitor, QualType> {
  113. private:
  114. const ASTContext &Context;
  115. public:
  116. TypeRetrievingVisitor(const ASTContext &Context) : Context(Context) {}
  117. QualType VisitLocMemRegionVal(loc::MemRegionVal MRV) {
  118. return Visit(MRV.getRegion());
  119. }
  120. QualType VisitLocGotoLabel(loc::GotoLabel GL) {
  121. return QualType{Context.VoidPtrTy};
  122. }
  123. template <class ConcreteInt> QualType VisitConcreteInt(ConcreteInt CI) {
  124. const llvm::APSInt &Value = CI.getValue();
  125. if (1 == Value.getBitWidth())
  126. return Context.BoolTy;
  127. return Context.getIntTypeForBitwidth(Value.getBitWidth(), Value.isSigned());
  128. }
  129. QualType VisitLocConcreteInt(loc::ConcreteInt CI) {
  130. return VisitConcreteInt(CI);
  131. }
  132. QualType VisitNonLocConcreteInt(nonloc::ConcreteInt CI) {
  133. return VisitConcreteInt(CI);
  134. }
  135. QualType VisitNonLocLocAsInteger(nonloc::LocAsInteger LI) {
  136. QualType NestedType = Visit(LI.getLoc());
  137. if (NestedType.isNull())
  138. return NestedType;
  139. return Context.getIntTypeForBitwidth(LI.getNumBits(),
  140. NestedType->isSignedIntegerType());
  141. }
  142. QualType VisitNonLocCompoundVal(nonloc::CompoundVal CV) {
  143. return CV.getValue()->getType();
  144. }
  145. QualType VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal LCV) {
  146. return LCV.getRegion()->getValueType();
  147. }
  148. QualType VisitNonLocSymbolVal(nonloc::SymbolVal SV) {
  149. return Visit(SV.getSymbol());
  150. }
  151. QualType VisitSymbolicRegion(const SymbolicRegion *SR) {
  152. return Visit(SR->getSymbol());
  153. }
  154. QualType VisitTypedRegion(const TypedRegion *TR) {
  155. return TR->getLocationType();
  156. }
  157. QualType VisitSymExpr(const SymExpr *SE) { return SE->getType(); }
  158. };
  159. } // end anonymous namespace
  160. QualType SVal::getType(const ASTContext &Context) const {
  161. TypeRetrievingVisitor TRV{Context};
  162. return TRV.Visit(*this);
  163. }
  164. const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
  165. return getRegion()->StripCasts(StripBaseCasts);
  166. }
  167. const void *nonloc::LazyCompoundVal::getStore() const {
  168. return static_cast<const LazyCompoundValData*>(Data)->getStore();
  169. }
  170. const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
  171. return static_cast<const LazyCompoundValData*>(Data)->getRegion();
  172. }
  173. bool nonloc::PointerToMember::isNullMemberPointer() const {
  174. return getPTMData().isNull();
  175. }
  176. const NamedDecl *nonloc::PointerToMember::getDecl() const {
  177. const auto PTMD = this->getPTMData();
  178. if (PTMD.isNull())
  179. return nullptr;
  180. const NamedDecl *ND = nullptr;
  181. if (PTMD.is<const NamedDecl *>())
  182. ND = PTMD.get<const NamedDecl *>();
  183. else
  184. ND = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl();
  185. return ND;
  186. }
  187. //===----------------------------------------------------------------------===//
  188. // Other Iterators.
  189. //===----------------------------------------------------------------------===//
  190. nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
  191. return getValue()->begin();
  192. }
  193. nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
  194. return getValue()->end();
  195. }
  196. nonloc::PointerToMember::iterator nonloc::PointerToMember::begin() const {
  197. const PTMDataType PTMD = getPTMData();
  198. if (PTMD.is<const NamedDecl *>())
  199. return {};
  200. return PTMD.get<const PointerToMemberData *>()->begin();
  201. }
  202. nonloc::PointerToMember::iterator nonloc::PointerToMember::end() const {
  203. const PTMDataType PTMD = getPTMData();
  204. if (PTMD.is<const NamedDecl *>())
  205. return {};
  206. return PTMD.get<const PointerToMemberData *>()->end();
  207. }
  208. //===----------------------------------------------------------------------===//
  209. // Useful predicates.
  210. //===----------------------------------------------------------------------===//
  211. bool SVal::isConstant() const {
  212. return getAs<nonloc::ConcreteInt>() || getAs<loc::ConcreteInt>();
  213. }
  214. bool SVal::isConstant(int I) const {
  215. if (std::optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
  216. return LV->getValue() == I;
  217. if (std::optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
  218. return NV->getValue() == I;
  219. return false;
  220. }
  221. bool SVal::isZeroConstant() const {
  222. return isConstant(0);
  223. }
  224. //===----------------------------------------------------------------------===//
  225. // Pretty-Printing.
  226. //===----------------------------------------------------------------------===//
  227. LLVM_DUMP_METHOD void SVal::dump() const { dumpToStream(llvm::errs()); }
  228. void SVal::printJson(raw_ostream &Out, bool AddQuotes) const {
  229. std::string Buf;
  230. llvm::raw_string_ostream TempOut(Buf);
  231. dumpToStream(TempOut);
  232. Out << JsonFormat(TempOut.str(), AddQuotes);
  233. }
  234. void SVal::dumpToStream(raw_ostream &os) const {
  235. switch (getBaseKind()) {
  236. case UnknownValKind:
  237. os << "Unknown";
  238. break;
  239. case NonLocKind:
  240. castAs<NonLoc>().dumpToStream(os);
  241. break;
  242. case LocKind:
  243. castAs<Loc>().dumpToStream(os);
  244. break;
  245. case UndefinedValKind:
  246. os << "Undefined";
  247. break;
  248. }
  249. }
  250. void NonLoc::dumpToStream(raw_ostream &os) const {
  251. switch (getSubKind()) {
  252. case nonloc::ConcreteIntKind: {
  253. const auto &Value = castAs<nonloc::ConcreteInt>().getValue();
  254. os << Value << ' ' << (Value.isSigned() ? 'S' : 'U')
  255. << Value.getBitWidth() << 'b';
  256. break;
  257. }
  258. case nonloc::SymbolValKind:
  259. os << castAs<nonloc::SymbolVal>().getSymbol();
  260. break;
  261. case nonloc::LocAsIntegerKind: {
  262. const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
  263. os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
  264. break;
  265. }
  266. case nonloc::CompoundValKind: {
  267. const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
  268. os << "compoundVal{";
  269. bool first = true;
  270. for (const auto &I : C) {
  271. if (first) {
  272. os << ' '; first = false;
  273. }
  274. else
  275. os << ", ";
  276. I.dumpToStream(os);
  277. }
  278. os << "}";
  279. break;
  280. }
  281. case nonloc::LazyCompoundValKind: {
  282. const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
  283. os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
  284. << ',' << C.getRegion()
  285. << '}';
  286. break;
  287. }
  288. case nonloc::PointerToMemberKind: {
  289. os << "pointerToMember{";
  290. const nonloc::PointerToMember &CastRes =
  291. castAs<nonloc::PointerToMember>();
  292. if (CastRes.getDecl())
  293. os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|";
  294. bool first = true;
  295. for (const auto &I : CastRes) {
  296. if (first) {
  297. os << ' '; first = false;
  298. }
  299. else
  300. os << ", ";
  301. os << I->getType();
  302. }
  303. os << '}';
  304. break;
  305. }
  306. default:
  307. assert(false && "Pretty-printed not implemented for this NonLoc.");
  308. break;
  309. }
  310. }
  311. void Loc::dumpToStream(raw_ostream &os) const {
  312. switch (getSubKind()) {
  313. case loc::ConcreteIntKind:
  314. os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
  315. break;
  316. case loc::GotoLabelKind:
  317. os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
  318. break;
  319. case loc::MemRegionValKind:
  320. os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
  321. break;
  322. default:
  323. llvm_unreachable("Pretty-printing not implemented for this Loc.");
  324. }
  325. }