clang  3.9.0
SymbolManager.cpp
Go to the documentation of this file.
1 //== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values
11 // created for use by ExprEngine and related classes.
12 //
13 //===----------------------------------------------------------------------===//
14 
19 #include "llvm/Support/raw_ostream.h"
20 
21 using namespace clang;
22 using namespace ento;
23 
24 void SymExpr::anchor() { }
25 
26 LLVM_DUMP_METHOD void SymExpr::dump() const {
27  dumpToStream(llvm::errs());
28 }
29 
30 void SymIntExpr::dumpToStream(raw_ostream &os) const {
31  os << '(';
32  getLHS()->dumpToStream(os);
33  os << ") "
35  << getRHS().getZExtValue();
36  if (getRHS().isUnsigned())
37  os << 'U';
38 }
39 
40 void IntSymExpr::dumpToStream(raw_ostream &os) const {
41  os << getLHS().getZExtValue();
42  if (getLHS().isUnsigned())
43  os << 'U';
44  os << ' '
46  << " (";
47  getRHS()->dumpToStream(os);
48  os << ')';
49 }
50 
51 void SymSymExpr::dumpToStream(raw_ostream &os) const {
52  os << '(';
53  getLHS()->dumpToStream(os);
54  os << ") "
56  << " (";
57  getRHS()->dumpToStream(os);
58  os << ')';
59 }
60 
61 void SymbolCast::dumpToStream(raw_ostream &os) const {
62  os << '(' << ToTy.getAsString() << ") (";
63  Operand->dumpToStream(os);
64  os << ')';
65 }
66 
67 void SymbolConjured::dumpToStream(raw_ostream &os) const {
68  os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}';
69 }
70 
71 void SymbolDerived::dumpToStream(raw_ostream &os) const {
72  os << "derived_$" << getSymbolID() << '{'
73  << getParentSymbol() << ',' << getRegion() << '}';
74 }
75 
76 void SymbolExtent::dumpToStream(raw_ostream &os) const {
77  os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
78 }
79 
80 void SymbolMetadata::dumpToStream(raw_ostream &os) const {
81  os << "meta_$" << getSymbolID() << '{'
82  << getRegion() << ',' << T.getAsString() << '}';
83 }
84 
85 void SymbolData::anchor() { }
86 
87 void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
88  os << "reg_$" << getSymbolID() << "<" << R << ">";
89 }
90 
92  return itr == X.itr;
93 }
94 
96  return itr != X.itr;
97 }
98 
100  itr.push_back(SE);
101 }
102 
104  assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
105  expand();
106  return *this;
107 }
108 
110  assert(!itr.empty() && "attempting to dereference an 'end' iterator");
111  return itr.back();
112 }
113 
114 void SymExpr::symbol_iterator::expand() {
115  const SymExpr *SE = itr.pop_back_val();
116 
117  switch (SE->getKind()) {
118  case SymExpr::SymbolRegionValueKind:
119  case SymExpr::SymbolConjuredKind:
120  case SymExpr::SymbolDerivedKind:
121  case SymExpr::SymbolExtentKind:
122  case SymExpr::SymbolMetadataKind:
123  return;
124  case SymExpr::SymbolCastKind:
125  itr.push_back(cast<SymbolCast>(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 SymSymExpr *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 
143 unsigned SymExpr::computeComplexity() const {
144  unsigned R = 0;
145  for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I)
146  R++;
147  return R;
148 }
149 
150 const SymbolRegionValue*
152  llvm::FoldingSetNodeID profile;
153  SymbolRegionValue::Profile(profile, R);
154  void *InsertPos;
155  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
156  if (!SD) {
157  SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
158  new (SD) SymbolRegionValue(SymbolCounter, R);
159  DataSet.InsertNode(SD, InsertPos);
160  ++SymbolCounter;
161  }
162 
163  return cast<SymbolRegionValue>(SD);
164 }
165 
167  const LocationContext *LCtx,
168  QualType T,
169  unsigned Count,
170  const void *SymbolTag) {
171  llvm::FoldingSetNodeID profile;
172  SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
173  void *InsertPos;
174  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
175  if (!SD) {
176  SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
177  new (SD) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
178  DataSet.InsertNode(SD, InsertPos);
179  ++SymbolCounter;
180  }
181 
182  return cast<SymbolConjured>(SD);
183 }
184 
185 const SymbolDerived*
187  const TypedValueRegion *R) {
188 
189  llvm::FoldingSetNodeID profile;
190  SymbolDerived::Profile(profile, parentSymbol, R);
191  void *InsertPos;
192  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
193  if (!SD) {
194  SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
195  new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
196  DataSet.InsertNode(SD, InsertPos);
197  ++SymbolCounter;
198  }
199 
200  return cast<SymbolDerived>(SD);
201 }
202 
203 const SymbolExtent*
205  llvm::FoldingSetNodeID profile;
206  SymbolExtent::Profile(profile, R);
207  void *InsertPos;
208  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
209  if (!SD) {
210  SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
211  new (SD) SymbolExtent(SymbolCounter, R);
212  DataSet.InsertNode(SD, InsertPos);
213  ++SymbolCounter;
214  }
215 
216  return cast<SymbolExtent>(SD);
217 }
218 
219 const SymbolMetadata*
221  unsigned Count, const void *SymbolTag) {
222 
223  llvm::FoldingSetNodeID profile;
224  SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
225  void *InsertPos;
226  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
227  if (!SD) {
228  SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
229  new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
230  DataSet.InsertNode(SD, InsertPos);
231  ++SymbolCounter;
232  }
233 
234  return cast<SymbolMetadata>(SD);
235 }
236 
237 const SymbolCast*
239  QualType From, QualType To) {
240  llvm::FoldingSetNodeID ID;
241  SymbolCast::Profile(ID, Op, From, To);
242  void *InsertPos;
243  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
244  if (!data) {
245  data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
246  new (data) SymbolCast(Op, From, To);
247  DataSet.InsertNode(data, InsertPos);
248  }
249 
250  return cast<SymbolCast>(data);
251 }
252 
255  const llvm::APSInt& v,
256  QualType t) {
257  llvm::FoldingSetNodeID ID;
258  SymIntExpr::Profile(ID, lhs, op, v, t);
259  void *InsertPos;
260  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
261 
262  if (!data) {
263  data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
264  new (data) SymIntExpr(lhs, op, v, t);
265  DataSet.InsertNode(data, InsertPos);
266  }
267 
268  return cast<SymIntExpr>(data);
269 }
270 
271 const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
273  const SymExpr *rhs,
274  QualType t) {
275  llvm::FoldingSetNodeID ID;
276  IntSymExpr::Profile(ID, lhs, op, rhs, t);
277  void *InsertPos;
278  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
279 
280  if (!data) {
281  data = (IntSymExpr*) BPAlloc.Allocate<IntSymExpr>();
282  new (data) IntSymExpr(lhs, op, rhs, t);
283  DataSet.InsertNode(data, InsertPos);
284  }
285 
286  return cast<IntSymExpr>(data);
287 }
288 
291  const SymExpr *rhs,
292  QualType t) {
293  llvm::FoldingSetNodeID ID;
294  SymSymExpr::Profile(ID, lhs, op, rhs, t);
295  void *InsertPos;
296  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
297 
298  if (!data) {
299  data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
300  new (data) SymSymExpr(lhs, op, rhs, t);
301  DataSet.InsertNode(data, InsertPos);
302  }
303 
304  return cast<SymSymExpr>(data);
305 }
306 
308  return T;
309 }
310 
312  return R->getValueType();
313 }
314 
316  ASTContext &Ctx = R->getMemRegionManager()->getContext();
317  return Ctx.getSizeType();
318 }
319 
321  return T;
322 }
323 
325  return R->getValueType();
326 }
327 
329  llvm::DeleteContainerSeconds(SymbolDependencies);
330 }
331 
333  T = T.getCanonicalType();
334 
335  if (Loc::isLocType(T))
336  return true;
337 
339  return true;
340 
341  if (T->isRecordType() && !T->isUnionType())
342  return true;
343 
344  return false;
345 }
346 
348  const SymbolRef Dependent) {
349  SymbolDependTy::iterator I = SymbolDependencies.find(Primary);
350  SymbolRefSmallVectorTy *dependencies = nullptr;
351  if (I == SymbolDependencies.end()) {
352  dependencies = new SymbolRefSmallVectorTy();
353  SymbolDependencies[Primary] = dependencies;
354  } else {
355  dependencies = I->second;
356  }
357  dependencies->push_back(Dependent);
358 }
359 
361  const SymbolRef Primary) {
362  SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
363  if (I == SymbolDependencies.end())
364  return nullptr;
365  return I->second;
366 }
367 
368 void SymbolReaper::markDependentsLive(SymbolRef sym) {
369  // Do not mark dependents more then once.
370  SymbolMapTy::iterator LI = TheLiving.find(sym);
371  assert(LI != TheLiving.end() && "The primary symbol is not live.");
372  if (LI->second == HaveMarkedDependents)
373  return;
374  LI->second = HaveMarkedDependents;
375 
376  if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
377  for (SymbolRefSmallVectorTy::const_iterator I = Deps->begin(),
378  E = Deps->end(); I != E; ++I) {
379  if (TheLiving.find(*I) != TheLiving.end())
380  continue;
381  markLive(*I);
382  }
383  }
384 }
385 
387  TheLiving[sym] = NotProcessed;
388  TheDead.erase(sym);
389  markDependentsLive(sym);
390 }
391 
392 void SymbolReaper::markLive(const MemRegion *region) {
393  RegionRoots.insert(region);
394  markElementIndicesLive(region);
395 }
396 
398  for (auto SR = dyn_cast<SubRegion>(region); SR;
399  SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
400  if (auto ER = dyn_cast<ElementRegion>(SR)) {
401  SVal Idx = ER->getIndex();
402  for (auto SI = Idx.symbol_begin(), SE = Idx.symbol_end(); SI != SE; ++SI)
403  markLive(*SI);
404  }
405  }
406 }
407 
409  if (isa<SymbolMetadata>(sym))
410  MetadataInUse.insert(sym);
411 }
412 
414  if (isLive(sym))
415  return false;
416 
417  TheDead.insert(sym);
418  return true;
419 }
420 
422  if (RegionRoots.count(MR))
423  return true;
424 
425  MR = MR->getBaseRegion();
426 
427  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
428  return isLive(SR->getSymbol());
429 
430  if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
431  return isLive(VR, true);
432 
433  // FIXME: This is a gross over-approximation. What we really need is a way to
434  // tell if anything still refers to this region. Unlike SymbolicRegions,
435  // AllocaRegions don't have associated symbols, though, so we don't actually
436  // have a way to track their liveness.
437  if (isa<AllocaRegion>(MR))
438  return true;
439 
440  if (isa<CXXThisRegion>(MR))
441  return true;
442 
443  if (isa<MemSpaceRegion>(MR))
444  return true;
445 
446  if (isa<CodeTextRegion>(MR))
447  return true;
448 
449  return false;
450 }
451 
453  if (TheLiving.count(sym)) {
454  markDependentsLive(sym);
455  return true;
456  }
457 
458  bool KnownLive;
459 
460  switch (sym->getKind()) {
461  case SymExpr::SymbolRegionValueKind:
462  KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
463  break;
464  case SymExpr::SymbolConjuredKind:
465  KnownLive = false;
466  break;
467  case SymExpr::SymbolDerivedKind:
468  KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
469  break;
470  case SymExpr::SymbolExtentKind:
471  KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
472  break;
473  case SymExpr::SymbolMetadataKind:
474  KnownLive = MetadataInUse.count(sym) &&
475  isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
476  if (KnownLive)
477  MetadataInUse.erase(sym);
478  break;
479  case SymExpr::SymIntExprKind:
480  KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
481  break;
482  case SymExpr::IntSymExprKind:
483  KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
484  break;
485  case SymExpr::SymSymExprKind:
486  KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
487  isLive(cast<SymSymExpr>(sym)->getRHS());
488  break;
489  case SymExpr::SymbolCastKind:
490  KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
491  break;
492  }
493 
494  if (KnownLive)
495  markLive(sym);
496 
497  return KnownLive;
498 }
499 
500 bool
501 SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
502  if (LCtx == nullptr)
503  return false;
504 
505  if (LCtx != ELCtx) {
506  // If the reaper's location context is a parent of the expression's
507  // location context, then the expression value is now "out of scope".
508  if (LCtx->isParentOf(ELCtx))
509  return false;
510  return true;
511  }
512 
513  // If no statement is provided, everything is this and parent contexts is live.
514  if (!Loc)
515  return true;
516 
517  return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
518 }
519 
520 bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
521  const StackFrameContext *VarContext = VR->getStackFrame();
522 
523  if (!VarContext)
524  return true;
525 
526  if (!LCtx)
527  return false;
528  const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
529 
530  if (VarContext == CurrentContext) {
531  // If no statement is provided, everything is live.
532  if (!Loc)
533  return true;
534 
535  if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
536  return true;
537 
538  if (!includeStoreBindings)
539  return false;
540 
541  unsigned &cachedQuery =
542  const_cast<SymbolReaper*>(this)->includedRegionCache[VR];
543 
544  if (cachedQuery) {
545  return cachedQuery == 1;
546  }
547 
548  // Query the store to see if the region occurs in any live bindings.
549  if (Store store = reapedStore.getStore()) {
550  bool hasRegion =
551  reapedStore.getStoreManager().includedInBindings(store, VR);
552  cachedQuery = hasRegion ? 1 : 2;
553  return hasRegion;
554  }
555 
556  return false;
557  }
558 
559  return VarContext->isParentOf(CurrentContext);
560 }
SmallVector< SymbolRef, 2 > SymbolRefSmallVectorTy
Definition: SymExpr.h:96
virtual void dump() const
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:494
A (possibly-)qualified type.
Definition: Type.h:598
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:79
bool operator==(const symbol_iterator &X) const
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
const llvm::APSInt & getRHS() const
const SymExpr * getLHS() const
bool maybeDead(SymbolRef sym)
If a symbol is known to be live, marks the symbol as live.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const IntSymExpr * getIntSymExpr(const llvm::APSInt &lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t)
const StackFrameContext * getStackFrame() const
Definition: MemRegion.cpp:170
static void Profile(llvm::FoldingSetNodeID &profile, const TypedValueRegion *R)
Definition: SymbolManager.h:51
bool isRecordType() const
Definition: Type.h:5539
std::string getAsString() const
Definition: Type.h:924
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
Definition: StoreRef.h:26
const SymExpr * getRHS() const
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
SymbolRef getParentSymbol() const
const MemRegion * getBaseRegion() const
Definition: MemRegion.cpp:1129
const SymbolRefSmallVectorTy * getDependentSymbols(const SymbolRef Primary)
bool isUnionType() const
Definition: Type.cpp:391
Symbolic value.
Definition: SymExpr.h:29
const SymbolDerived * getDerivedSymbol(SymbolRef parentSymbol, const TypedValueRegion *R)
void markInUse(SymbolRef sym)
Marks a symbol as important to a checker.
SymbolID getSymbolID() const
Definition: SymExpr.h:111
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:92
static void Profile(llvm::FoldingSetNodeID &profile, SymbolRef parent, const TypedValueRegion *r)
unsigned computeComplexity() const
void markElementIndicesLive(const MemRegion *region)
static bool canSymbolicate(QualType T)
bool operator!=(const symbol_iterator &X) const
void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent)
Add artificial symbol dependency.
QualType getType() const override
const SymExpr * getLHS() const
static void Profile(llvm::FoldingSetNodeID &ID, const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt &rhs, QualType t)
const VarDecl * getDecl() const
Definition: MemRegion.h:873
static bool isLocType(QualType T)
Definition: SVals.h:291
BinaryOperatorKind
bool isLiveRegion(const MemRegion *region)
bool isLive(const CFGBlock *B, const VarDecl *D)
Return true if a variable is live at the end of a specified block.
const SymIntExpr * getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt &rhs, QualType t)
bool isParentOf(const LocationContext *LC) const
const SubRegion * getRegion() const
Represents a symbolic expression like 'x' + 3.
A symbol representing the value of a MemRegion whose parent region has symbolic value.
SymExpr::symbol_iterator symbol_begin() const
Definition: SVals.h:177
QualType getType() const override
detail::InMemoryDirectory::const_iterator I
static void Profile(llvm::FoldingSetNodeID &ID, const llvm::APSInt &lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t)
static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S, QualType T, unsigned Count, const LocationContext *LCtx, const void *SymbolTag)
Definition: SymbolManager.h:94
SymbolicRegion - A special, "non-concrete" region.
Definition: MemRegion.h:707
static void Profile(llvm::FoldingSetNodeID &profile, const MemRegion *R, const Stmt *S, QualType T, unsigned Count, const void *Tag)
Represents a cast expression.
const TypedValueRegion * getRegion() const
const SymExpr * getRHS() const
Kind getKind() const
Definition: SymExpr.h:48
do v
Definition: arm_acle.h:78
const SymbolCast * getCastSymbol(const SymExpr *Operand, QualType From, QualType To)
const SymSymExpr * getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t)
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:5730
QualType getType() const override
const TemplateArgument * iterator
Definition: Type.h:4233
const StackFrameContext * getCurrentStackFrame() const
const std::string ID
const SymbolRegionValue * getRegionValueSymbol(const TypedValueRegion *R)
Make a unique symbol for MemRegion R according to its kind.
const SymbolMetadata * getMetadataSymbol(const MemRegion *R, const Stmt *S, QualType T, unsigned VisitCount, const void *SymbolTag=nullptr)
Creates a metadata symbol associated with a specific region.
SymExpr::symbol_iterator symbol_end() const
Definition: SVals.h:185
QualType getType() const override
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:46
Represents a symbolic expression like 3 - 'x'.
void dumpToStream(raw_ostream &os) const override
A class responsible for cleaning up unused symbols.
A symbol representing the result of an expression in the case when we do not know anything about what...
Definition: SymbolManager.h:73
void dumpToStream(raw_ostream &os) const override
A symbol representing the value stored at a MemRegion.
Definition: SymbolManager.h:42
StringRef getOpcodeStr() const
Definition: Expr.h:2959
static void Profile(llvm::FoldingSetNodeID &ID, const SymExpr *In, QualType From, QualType To)
const llvm::APSInt & getLHS() const
static symbol_iterator symbol_end()
Definition: SymExpr.h:78
QualType getType() const override
detail::InMemoryDirectory::const_iterator E
const SymbolConjured * conjureSymbol(const Stmt *E, const LocationContext *LCtx, QualType T, unsigned VisitCount, const void *SymbolTag=nullptr)
void dumpToStream(raw_ostream &os) const override
virtual void dumpToStream(raw_ostream &os) const
Definition: SymExpr.h:52
QualType getCanonicalType() const
Definition: Type.h:5298
SubRegion - A region that subsets another larger region.
Definition: MemRegion.h:410
BinaryOperator::Opcode getOpcode() const
SymbolMetadata - Represents path-dependent metadata about a specific region.
static void Profile(llvm::FoldingSetNodeID &profile, const SubRegion *R)
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:12171
const SymbolExtent * getExtentSymbol(const SubRegion *R)
void dumpToStream(raw_ostream &os) const override
symbol_iterator symbol_begin() const
Definition: SymExpr.h:77
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
SymbolExtent - Represents the extent (size in bytes) of a bounded region.
void dumpToStream(raw_ostream &os) const override
Represents a symbolic expression like 'x' + 'y'.
const MemRegion * getRegion() const
bool isLive(SymbolRef sym)
static void Profile(llvm::FoldingSetNodeID &ID, const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t)
Iterator over symbols that the current symbol depends on.
Definition: SymExpr.h:62