SymbolManager.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. //===- SymbolManager.h - Management of Symbolic Values --------------------===//
  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 SymbolManager, a class that manages symbolic values
  10. // created for use by ExprEngine and related classes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
  14. #include "clang/AST/ASTContext.h"
  15. #include "clang/AST/Expr.h"
  16. #include "clang/AST/StmtObjC.h"
  17. #include "clang/Analysis/Analyses/LiveVariables.h"
  18. #include "clang/Analysis/AnalysisDeclContext.h"
  19. #include "clang/Basic/LLVM.h"
  20. #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
  24. #include "llvm/ADT/FoldingSet.h"
  25. #include "llvm/ADT/STLExtras.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. void SymExpr::anchor() {}
  34. StringRef SymbolConjured::getKindStr() const { return "conj_$"; }
  35. StringRef SymbolDerived::getKindStr() const { return "derived_$"; }
  36. StringRef SymbolExtent::getKindStr() const { return "extent_$"; }
  37. StringRef SymbolMetadata::getKindStr() const { return "meta_$"; }
  38. StringRef SymbolRegionValue::getKindStr() const { return "reg_$"; }
  39. LLVM_DUMP_METHOD void SymExpr::dump() const { dumpToStream(llvm::errs()); }
  40. void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS, const SymExpr *Sym) {
  41. OS << '(';
  42. Sym->dumpToStream(OS);
  43. OS << ')';
  44. }
  45. void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
  46. const llvm::APSInt &Value) {
  47. if (Value.isUnsigned())
  48. OS << Value.getZExtValue();
  49. else
  50. OS << Value.getSExtValue();
  51. if (Value.isUnsigned())
  52. OS << 'U';
  53. }
  54. void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
  55. BinaryOperator::Opcode Op) {
  56. OS << ' ' << BinaryOperator::getOpcodeStr(Op) << ' ';
  57. }
  58. void SymbolCast::dumpToStream(raw_ostream &os) const {
  59. os << '(' << ToTy << ") (";
  60. Operand->dumpToStream(os);
  61. os << ')';
  62. }
  63. void UnarySymExpr::dumpToStream(raw_ostream &os) const {
  64. os << UnaryOperator::getOpcodeStr(Op);
  65. bool Binary = isa<BinarySymExpr>(Operand);
  66. if (Binary)
  67. os << '(';
  68. Operand->dumpToStream(os);
  69. if (Binary)
  70. os << ')';
  71. }
  72. void SymbolConjured::dumpToStream(raw_ostream &os) const {
  73. os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID();
  74. if (S)
  75. os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
  76. else
  77. os << ", no stmt";
  78. os << ", #" << Count << '}';
  79. }
  80. void SymbolDerived::dumpToStream(raw_ostream &os) const {
  81. os << getKindStr() << getSymbolID() << '{' << getParentSymbol() << ','
  82. << getRegion() << '}';
  83. }
  84. void SymbolExtent::dumpToStream(raw_ostream &os) const {
  85. os << getKindStr() << getSymbolID() << '{' << getRegion() << '}';
  86. }
  87. void SymbolMetadata::dumpToStream(raw_ostream &os) const {
  88. os << getKindStr() << getSymbolID() << '{' << getRegion() << ',' << T << '}';
  89. }
  90. void SymbolData::anchor() {}
  91. void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
  92. os << getKindStr() << getSymbolID() << '<' << getType() << ' ' << R << '>';
  93. }
  94. bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
  95. return itr == X.itr;
  96. }
  97. bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
  98. return itr != X.itr;
  99. }
  100. SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
  101. itr.push_back(SE);
  102. }
  103. SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
  104. assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
  105. expand();
  106. return *this;
  107. }
  108. SymbolRef SymExpr::symbol_iterator::operator*() {
  109. assert(!itr.empty() && "attempting to dereference an 'end' iterator");
  110. return itr.back();
  111. }
  112. void SymExpr::symbol_iterator::expand() {
  113. const SymExpr *SE = itr.pop_back_val();
  114. switch (SE->getKind()) {
  115. case SymExpr::SymbolRegionValueKind:
  116. case SymExpr::SymbolConjuredKind:
  117. case SymExpr::SymbolDerivedKind:
  118. case SymExpr::SymbolExtentKind:
  119. case SymExpr::SymbolMetadataKind:
  120. return;
  121. case SymExpr::SymbolCastKind:
  122. itr.push_back(cast<SymbolCast>(SE)->getOperand());
  123. return;
  124. case SymExpr::UnarySymExprKind:
  125. itr.push_back(cast<UnarySymExpr>(SE)->getOperand());
  126. return;
  127. case SymExpr::SymIntExprKind:
  128. itr.push_back(cast<SymIntExpr>(SE)->getLHS());
  129. return;
  130. case SymExpr::IntSymExprKind:
  131. itr.push_back(cast<IntSymExpr>(SE)->getRHS());
  132. return;
  133. case SymExpr::SymSymExprKind: {
  134. const auto *x = cast<SymSymExpr>(SE);
  135. itr.push_back(x->getLHS());
  136. itr.push_back(x->getRHS());
  137. return;
  138. }
  139. }
  140. llvm_unreachable("unhandled expansion case");
  141. }
  142. const SymbolRegionValue*
  143. SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
  144. llvm::FoldingSetNodeID profile;
  145. SymbolRegionValue::Profile(profile, R);
  146. void *InsertPos;
  147. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  148. if (!SD) {
  149. SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
  150. new (SD) SymbolRegionValue(SymbolCounter, R);
  151. DataSet.InsertNode(SD, InsertPos);
  152. ++SymbolCounter;
  153. }
  154. return cast<SymbolRegionValue>(SD);
  155. }
  156. const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
  157. const LocationContext *LCtx,
  158. QualType T,
  159. unsigned Count,
  160. const void *SymbolTag) {
  161. llvm::FoldingSetNodeID profile;
  162. SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
  163. void *InsertPos;
  164. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  165. if (!SD) {
  166. SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
  167. new (SD) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
  168. DataSet.InsertNode(SD, InsertPos);
  169. ++SymbolCounter;
  170. }
  171. return cast<SymbolConjured>(SD);
  172. }
  173. const SymbolDerived*
  174. SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
  175. const TypedValueRegion *R) {
  176. llvm::FoldingSetNodeID profile;
  177. SymbolDerived::Profile(profile, parentSymbol, R);
  178. void *InsertPos;
  179. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  180. if (!SD) {
  181. SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
  182. new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
  183. DataSet.InsertNode(SD, InsertPos);
  184. ++SymbolCounter;
  185. }
  186. return cast<SymbolDerived>(SD);
  187. }
  188. const SymbolExtent*
  189. SymbolManager::getExtentSymbol(const SubRegion *R) {
  190. llvm::FoldingSetNodeID profile;
  191. SymbolExtent::Profile(profile, R);
  192. void *InsertPos;
  193. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  194. if (!SD) {
  195. SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
  196. new (SD) SymbolExtent(SymbolCounter, R);
  197. DataSet.InsertNode(SD, InsertPos);
  198. ++SymbolCounter;
  199. }
  200. return cast<SymbolExtent>(SD);
  201. }
  202. const SymbolMetadata *
  203. SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
  204. const LocationContext *LCtx,
  205. unsigned Count, const void *SymbolTag) {
  206. llvm::FoldingSetNodeID profile;
  207. SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag);
  208. void *InsertPos;
  209. SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
  210. if (!SD) {
  211. SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
  212. new (SD) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag);
  213. DataSet.InsertNode(SD, InsertPos);
  214. ++SymbolCounter;
  215. }
  216. return cast<SymbolMetadata>(SD);
  217. }
  218. const SymbolCast*
  219. SymbolManager::getCastSymbol(const SymExpr *Op,
  220. QualType From, QualType To) {
  221. llvm::FoldingSetNodeID ID;
  222. SymbolCast::Profile(ID, Op, From, To);
  223. void *InsertPos;
  224. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  225. if (!data) {
  226. data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
  227. new (data) SymbolCast(Op, From, To);
  228. DataSet.InsertNode(data, InsertPos);
  229. }
  230. return cast<SymbolCast>(data);
  231. }
  232. const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
  233. BinaryOperator::Opcode op,
  234. const llvm::APSInt& v,
  235. QualType t) {
  236. llvm::FoldingSetNodeID ID;
  237. SymIntExpr::Profile(ID, lhs, op, v, t);
  238. void *InsertPos;
  239. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  240. if (!data) {
  241. data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
  242. new (data) SymIntExpr(lhs, op, v, t);
  243. DataSet.InsertNode(data, InsertPos);
  244. }
  245. return cast<SymIntExpr>(data);
  246. }
  247. const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
  248. BinaryOperator::Opcode op,
  249. const SymExpr *rhs,
  250. QualType t) {
  251. llvm::FoldingSetNodeID ID;
  252. IntSymExpr::Profile(ID, lhs, op, rhs, t);
  253. void *InsertPos;
  254. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  255. if (!data) {
  256. data = (IntSymExpr*) BPAlloc.Allocate<IntSymExpr>();
  257. new (data) IntSymExpr(lhs, op, rhs, t);
  258. DataSet.InsertNode(data, InsertPos);
  259. }
  260. return cast<IntSymExpr>(data);
  261. }
  262. const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
  263. BinaryOperator::Opcode op,
  264. const SymExpr *rhs,
  265. QualType t) {
  266. llvm::FoldingSetNodeID ID;
  267. SymSymExpr::Profile(ID, lhs, op, rhs, t);
  268. void *InsertPos;
  269. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  270. if (!data) {
  271. data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
  272. new (data) SymSymExpr(lhs, op, rhs, t);
  273. DataSet.InsertNode(data, InsertPos);
  274. }
  275. return cast<SymSymExpr>(data);
  276. }
  277. const UnarySymExpr *SymbolManager::getUnarySymExpr(const SymExpr *Operand,
  278. UnaryOperator::Opcode Opc,
  279. QualType T) {
  280. llvm::FoldingSetNodeID ID;
  281. UnarySymExpr::Profile(ID, Operand, Opc, T);
  282. void *InsertPos;
  283. SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
  284. if (!data) {
  285. data = (UnarySymExpr *)BPAlloc.Allocate<UnarySymExpr>();
  286. new (data) UnarySymExpr(Operand, Opc, T);
  287. DataSet.InsertNode(data, InsertPos);
  288. }
  289. return cast<UnarySymExpr>(data);
  290. }
  291. QualType SymbolConjured::getType() const {
  292. return T;
  293. }
  294. QualType SymbolDerived::getType() const {
  295. return R->getValueType();
  296. }
  297. QualType SymbolExtent::getType() const {
  298. ASTContext &Ctx = R->getMemRegionManager().getContext();
  299. return Ctx.getSizeType();
  300. }
  301. QualType SymbolMetadata::getType() const {
  302. return T;
  303. }
  304. QualType SymbolRegionValue::getType() const {
  305. return R->getValueType();
  306. }
  307. bool SymbolManager::canSymbolicate(QualType T) {
  308. T = T.getCanonicalType();
  309. if (Loc::isLocType(T))
  310. return true;
  311. if (T->isIntegralOrEnumerationType())
  312. return true;
  313. if (T->isRecordType() && !T->isUnionType())
  314. return true;
  315. return false;
  316. }
  317. void SymbolManager::addSymbolDependency(const SymbolRef Primary,
  318. const SymbolRef Dependent) {
  319. auto &dependencies = SymbolDependencies[Primary];
  320. if (!dependencies) {
  321. dependencies = std::make_unique<SymbolRefSmallVectorTy>();
  322. }
  323. dependencies->push_back(Dependent);
  324. }
  325. const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
  326. const SymbolRef Primary) {
  327. SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
  328. if (I == SymbolDependencies.end())
  329. return nullptr;
  330. return I->second.get();
  331. }
  332. void SymbolReaper::markDependentsLive(SymbolRef sym) {
  333. // Do not mark dependents more then once.
  334. SymbolMapTy::iterator LI = TheLiving.find(sym);
  335. assert(LI != TheLiving.end() && "The primary symbol is not live.");
  336. if (LI->second == HaveMarkedDependents)
  337. return;
  338. LI->second = HaveMarkedDependents;
  339. if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
  340. for (const auto I : *Deps) {
  341. if (TheLiving.find(I) != TheLiving.end())
  342. continue;
  343. markLive(I);
  344. }
  345. }
  346. }
  347. void SymbolReaper::markLive(SymbolRef sym) {
  348. TheLiving[sym] = NotProcessed;
  349. markDependentsLive(sym);
  350. }
  351. void SymbolReaper::markLive(const MemRegion *region) {
  352. LiveRegionRoots.insert(region->getBaseRegion());
  353. markElementIndicesLive(region);
  354. }
  355. void SymbolReaper::markLazilyCopied(const clang::ento::MemRegion *region) {
  356. LazilyCopiedRegionRoots.insert(region->getBaseRegion());
  357. }
  358. void SymbolReaper::markElementIndicesLive(const MemRegion *region) {
  359. for (auto SR = dyn_cast<SubRegion>(region); SR;
  360. SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
  361. if (const auto ER = dyn_cast<ElementRegion>(SR)) {
  362. SVal Idx = ER->getIndex();
  363. for (auto SI = Idx.symbol_begin(), SE = Idx.symbol_end(); SI != SE; ++SI)
  364. markLive(*SI);
  365. }
  366. }
  367. }
  368. void SymbolReaper::markInUse(SymbolRef sym) {
  369. if (isa<SymbolMetadata>(sym))
  370. MetadataInUse.insert(sym);
  371. }
  372. bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
  373. // TODO: For now, liveness of a memory region is equivalent to liveness of its
  374. // base region. In fact we can do a bit better: say, if a particular FieldDecl
  375. // is not used later in the path, we can diagnose a leak of a value within
  376. // that field earlier than, say, the variable that contains the field dies.
  377. MR = MR->getBaseRegion();
  378. if (LiveRegionRoots.count(MR))
  379. return true;
  380. if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
  381. return isLive(SR->getSymbol());
  382. if (const auto *VR = dyn_cast<VarRegion>(MR))
  383. return isLive(VR, true);
  384. // FIXME: This is a gross over-approximation. What we really need is a way to
  385. // tell if anything still refers to this region. Unlike SymbolicRegions,
  386. // AllocaRegions don't have associated symbols, though, so we don't actually
  387. // have a way to track their liveness.
  388. return isa<AllocaRegion, CXXThisRegion, MemSpaceRegion, CodeTextRegion>(MR);
  389. }
  390. bool SymbolReaper::isLazilyCopiedRegion(const MemRegion *MR) const {
  391. // TODO: See comment in isLiveRegion.
  392. return LazilyCopiedRegionRoots.count(MR->getBaseRegion());
  393. }
  394. bool SymbolReaper::isReadableRegion(const MemRegion *MR) {
  395. return isLiveRegion(MR) || isLazilyCopiedRegion(MR);
  396. }
  397. bool SymbolReaper::isLive(SymbolRef sym) {
  398. if (TheLiving.count(sym)) {
  399. markDependentsLive(sym);
  400. return true;
  401. }
  402. bool KnownLive;
  403. switch (sym->getKind()) {
  404. case SymExpr::SymbolRegionValueKind:
  405. KnownLive = isReadableRegion(cast<SymbolRegionValue>(sym)->getRegion());
  406. break;
  407. case SymExpr::SymbolConjuredKind:
  408. KnownLive = false;
  409. break;
  410. case SymExpr::SymbolDerivedKind:
  411. KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
  412. break;
  413. case SymExpr::SymbolExtentKind:
  414. KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
  415. break;
  416. case SymExpr::SymbolMetadataKind:
  417. KnownLive = MetadataInUse.count(sym) &&
  418. isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
  419. if (KnownLive)
  420. MetadataInUse.erase(sym);
  421. break;
  422. case SymExpr::SymIntExprKind:
  423. KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
  424. break;
  425. case SymExpr::IntSymExprKind:
  426. KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
  427. break;
  428. case SymExpr::SymSymExprKind:
  429. KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
  430. isLive(cast<SymSymExpr>(sym)->getRHS());
  431. break;
  432. case SymExpr::SymbolCastKind:
  433. KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
  434. break;
  435. case SymExpr::UnarySymExprKind:
  436. KnownLive = isLive(cast<UnarySymExpr>(sym)->getOperand());
  437. break;
  438. }
  439. if (KnownLive)
  440. markLive(sym);
  441. return KnownLive;
  442. }
  443. bool
  444. SymbolReaper::isLive(const Expr *ExprVal, const LocationContext *ELCtx) const {
  445. if (LCtx == nullptr)
  446. return false;
  447. if (LCtx != ELCtx) {
  448. // If the reaper's location context is a parent of the expression's
  449. // location context, then the expression value is now "out of scope".
  450. if (LCtx->isParentOf(ELCtx))
  451. return false;
  452. return true;
  453. }
  454. // If no statement is provided, everything in this and parent contexts is
  455. // live.
  456. if (!Loc)
  457. return true;
  458. return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
  459. }
  460. bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
  461. const StackFrameContext *VarContext = VR->getStackFrame();
  462. if (!VarContext)
  463. return true;
  464. if (!LCtx)
  465. return false;
  466. const StackFrameContext *CurrentContext = LCtx->getStackFrame();
  467. if (VarContext == CurrentContext) {
  468. // If no statement is provided, everything is live.
  469. if (!Loc)
  470. return true;
  471. // Anonymous parameters of an inheriting constructor are live for the entire
  472. // duration of the constructor.
  473. if (isa<CXXInheritedCtorInitExpr>(Loc))
  474. return true;
  475. if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
  476. return true;
  477. if (!includeStoreBindings)
  478. return false;
  479. unsigned &cachedQuery =
  480. const_cast<SymbolReaper *>(this)->includedRegionCache[VR];
  481. if (cachedQuery) {
  482. return cachedQuery == 1;
  483. }
  484. // Query the store to see if the region occurs in any live bindings.
  485. if (Store store = reapedStore.getStore()) {
  486. bool hasRegion =
  487. reapedStore.getStoreManager().includedInBindings(store, VR);
  488. cachedQuery = hasRegion ? 1 : 2;
  489. return hasRegion;
  490. }
  491. return false;
  492. }
  493. return VarContext->isParentOf(CurrentContext);
  494. }