SVals.cpp 13 KB

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