Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- SymbolManager.h - Management of Symbolic Values ----------*- C++ -*-===//
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
 
14
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
15
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
16
 
17
#include "clang/AST/Expr.h"
18
#include "clang/AST/Type.h"
19
#include "clang/Analysis/AnalysisDeclContext.h"
20
#include "clang/Basic/LLVM.h"
21
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
22
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
23
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
24
#include "llvm/ADT/DenseMap.h"
25
#include "llvm/ADT/DenseSet.h"
26
#include "llvm/ADT/FoldingSet.h"
27
#include "llvm/Support/Allocator.h"
28
#include <cassert>
29
 
30
namespace clang {
31
 
32
class ASTContext;
33
class Stmt;
34
 
35
namespace ento {
36
 
37
class BasicValueFactory;
38
class StoreManager;
39
 
40
///A symbol representing the value stored at a MemRegion.
41
class SymbolRegionValue : public SymbolData {
42
  const TypedValueRegion *R;
43
 
44
public:
45
  SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
46
      : SymbolData(SymbolRegionValueKind, sym), R(r) {
47
    assert(r);
48
    assert(isValidTypeForSymbol(r->getValueType()));
49
  }
50
 
51
  LLVM_ATTRIBUTE_RETURNS_NONNULL
52
  const TypedValueRegion* getRegion() const { return R; }
53
 
54
  static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
55
    profile.AddInteger((unsigned) SymbolRegionValueKind);
56
    profile.AddPointer(R);
57
  }
58
 
59
  void Profile(llvm::FoldingSetNodeID& profile) override {
60
    Profile(profile, R);
61
  }
62
 
63
  StringRef getKindStr() const override;
64
 
65
  void dumpToStream(raw_ostream &os) const override;
66
  const MemRegion *getOriginRegion() const override { return getRegion(); }
67
 
68
  QualType getType() const override;
69
 
70
  // Implement isa<T> support.
71
  static bool classof(const SymExpr *SE) {
72
    return SE->getKind() == SymbolRegionValueKind;
73
  }
74
};
75
 
76
/// A symbol representing the result of an expression in the case when we do
77
/// not know anything about what the expression is.
78
class SymbolConjured : public SymbolData {
79
  const Stmt *S;
80
  QualType T;
81
  unsigned Count;
82
  const LocationContext *LCtx;
83
  const void *SymbolTag;
84
 
85
public:
86
  SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
87
                 QualType t, unsigned count, const void *symbolTag)
88
      : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
89
        LCtx(lctx), SymbolTag(symbolTag) {
90
    // FIXME: 's' might be a nullptr if we're conducting invalidation
91
    // that was caused by a destructor call on a temporary object,
92
    // which has no statement associated with it.
93
    // Due to this, we might be creating the same invalidation symbol for
94
    // two different invalidation passes (for two different temporaries).
95
    assert(lctx);
96
    assert(isValidTypeForSymbol(t));
97
  }
98
 
99
  /// It might return null.
100
  const Stmt *getStmt() const { return S; }
101
  unsigned getCount() const { return Count; }
102
  /// It might return null.
103
  const void *getTag() const { return SymbolTag; }
104
 
105
  QualType getType() const override;
106
 
107
  StringRef getKindStr() const override;
108
 
109
  void dumpToStream(raw_ostream &os) const override;
110
 
111
  static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
112
                      QualType T, unsigned Count, const LocationContext *LCtx,
113
                      const void *SymbolTag) {
114
    profile.AddInteger((unsigned) SymbolConjuredKind);
115
    profile.AddPointer(S);
116
    profile.AddPointer(LCtx);
117
    profile.Add(T);
118
    profile.AddInteger(Count);
119
    profile.AddPointer(SymbolTag);
120
  }
121
 
122
  void Profile(llvm::FoldingSetNodeID& profile) override {
123
    Profile(profile, S, T, Count, LCtx, SymbolTag);
124
  }
125
 
126
  // Implement isa<T> support.
127
  static bool classof(const SymExpr *SE) {
128
    return SE->getKind() == SymbolConjuredKind;
129
  }
130
};
131
 
132
/// A symbol representing the value of a MemRegion whose parent region has
133
/// symbolic value.
134
class SymbolDerived : public SymbolData {
135
  SymbolRef parentSymbol;
136
  const TypedValueRegion *R;
137
 
138
public:
139
  SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
140
      : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {
141
    assert(parent);
142
    assert(r);
143
    assert(isValidTypeForSymbol(r->getValueType()));
144
  }
145
 
146
  LLVM_ATTRIBUTE_RETURNS_NONNULL
147
  SymbolRef getParentSymbol() const { return parentSymbol; }
148
  LLVM_ATTRIBUTE_RETURNS_NONNULL
149
  const TypedValueRegion *getRegion() const { return R; }
150
 
151
  QualType getType() const override;
152
 
153
  StringRef getKindStr() const override;
154
 
155
  void dumpToStream(raw_ostream &os) const override;
156
  const MemRegion *getOriginRegion() const override { return getRegion(); }
157
 
158
  static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
159
                      const TypedValueRegion *r) {
160
    profile.AddInteger((unsigned) SymbolDerivedKind);
161
    profile.AddPointer(r);
162
    profile.AddPointer(parent);
163
  }
164
 
165
  void Profile(llvm::FoldingSetNodeID& profile) override {
166
    Profile(profile, parentSymbol, R);
167
  }
168
 
169
  // Implement isa<T> support.
170
  static bool classof(const SymExpr *SE) {
171
    return SE->getKind() == SymbolDerivedKind;
172
  }
173
};
174
 
175
/// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
176
///  Clients should not ask the SymbolManager for a region's extent. Always use
177
///  SubRegion::getExtent instead -- the value returned may not be a symbol.
178
class SymbolExtent : public SymbolData {
179
  const SubRegion *R;
180
 
181
public:
182
  SymbolExtent(SymbolID sym, const SubRegion *r)
183
      : SymbolData(SymbolExtentKind, sym), R(r) {
184
    assert(r);
185
  }
186
 
187
  LLVM_ATTRIBUTE_RETURNS_NONNULL
188
  const SubRegion *getRegion() const { return R; }
189
 
190
  QualType getType() const override;
191
 
192
  StringRef getKindStr() const override;
193
 
194
  void dumpToStream(raw_ostream &os) const override;
195
 
196
  static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
197
    profile.AddInteger((unsigned) SymbolExtentKind);
198
    profile.AddPointer(R);
199
  }
200
 
201
  void Profile(llvm::FoldingSetNodeID& profile) override {
202
    Profile(profile, R);
203
  }
204
 
205
  // Implement isa<T> support.
206
  static bool classof(const SymExpr *SE) {
207
    return SE->getKind() == SymbolExtentKind;
208
  }
209
};
210
 
211
/// SymbolMetadata - Represents path-dependent metadata about a specific region.
212
///  Metadata symbols remain live as long as they are marked as in use before
213
///  dead-symbol sweeping AND their associated regions are still alive.
214
///  Intended for use by checkers.
215
class SymbolMetadata : public SymbolData {
216
  const MemRegion* R;
217
  const Stmt *S;
218
  QualType T;
219
  const LocationContext *LCtx;
220
  unsigned Count;
221
  const void *Tag;
222
 
223
public:
224
  SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
225
                 const LocationContext *LCtx, unsigned count, const void *tag)
226
      : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx),
227
        Count(count), Tag(tag) {
228
      assert(r);
229
      assert(s);
230
      assert(isValidTypeForSymbol(t));
231
      assert(LCtx);
232
      assert(tag);
233
    }
234
 
235
    LLVM_ATTRIBUTE_RETURNS_NONNULL
236
    const MemRegion *getRegion() const { return R; }
237
 
238
    LLVM_ATTRIBUTE_RETURNS_NONNULL
239
    const Stmt *getStmt() const { return S; }
240
 
241
    LLVM_ATTRIBUTE_RETURNS_NONNULL
242
    const LocationContext *getLocationContext() const { return LCtx; }
243
 
244
    unsigned getCount() const { return Count; }
245
 
246
    LLVM_ATTRIBUTE_RETURNS_NONNULL
247
    const void *getTag() const { return Tag; }
248
 
249
    QualType getType() const override;
250
 
251
    StringRef getKindStr() const override;
252
 
253
    void dumpToStream(raw_ostream &os) const override;
254
 
255
    static void Profile(llvm::FoldingSetNodeID &profile, const MemRegion *R,
256
                        const Stmt *S, QualType T, const LocationContext *LCtx,
257
                        unsigned Count, const void *Tag) {
258
      profile.AddInteger((unsigned)SymbolMetadataKind);
259
      profile.AddPointer(R);
260
      profile.AddPointer(S);
261
      profile.Add(T);
262
      profile.AddPointer(LCtx);
263
      profile.AddInteger(Count);
264
      profile.AddPointer(Tag);
265
    }
266
 
267
  void Profile(llvm::FoldingSetNodeID& profile) override {
268
    Profile(profile, R, S, T, LCtx, Count, Tag);
269
  }
270
 
271
  // Implement isa<T> support.
272
  static bool classof(const SymExpr *SE) {
273
    return SE->getKind() == SymbolMetadataKind;
274
  }
275
};
276
 
277
/// Represents a cast expression.
278
class SymbolCast : public SymExpr {
279
  const SymExpr *Operand;
280
 
281
  /// Type of the operand.
282
  QualType FromTy;
283
 
284
  /// The type of the result.
285
  QualType ToTy;
286
 
287
public:
288
  SymbolCast(const SymExpr *In, QualType From, QualType To)
289
      : SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) {
290
    assert(In);
291
    assert(isValidTypeForSymbol(From));
292
    // FIXME: GenericTaintChecker creates symbols of void type.
293
    // Otherwise, 'To' should also be a valid type.
294
  }
295
 
296
  unsigned computeComplexity() const override {
297
    if (Complexity == 0)
298
      Complexity = 1 + Operand->computeComplexity();
299
    return Complexity;
300
  }
301
 
302
  QualType getType() const override { return ToTy; }
303
 
304
  LLVM_ATTRIBUTE_RETURNS_NONNULL
305
  const SymExpr *getOperand() const { return Operand; }
306
 
307
  void dumpToStream(raw_ostream &os) const override;
308
 
309
  static void Profile(llvm::FoldingSetNodeID& ID,
310
                      const SymExpr *In, QualType From, QualType To) {
311
    ID.AddInteger((unsigned) SymbolCastKind);
312
    ID.AddPointer(In);
313
    ID.Add(From);
314
    ID.Add(To);
315
  }
316
 
317
  void Profile(llvm::FoldingSetNodeID& ID) override {
318
    Profile(ID, Operand, FromTy, ToTy);
319
  }
320
 
321
  // Implement isa<T> support.
322
  static bool classof(const SymExpr *SE) {
323
    return SE->getKind() == SymbolCastKind;
324
  }
325
};
326
 
327
/// Represents a symbolic expression involving a unary operator.
328
class UnarySymExpr : public SymExpr {
329
  const SymExpr *Operand;
330
  UnaryOperator::Opcode Op;
331
  QualType T;
332
 
333
public:
334
  UnarySymExpr(const SymExpr *In, UnaryOperator::Opcode Op, QualType T)
335
      : SymExpr(UnarySymExprKind), Operand(In), Op(Op), T(T) {
336
    // Note, some unary operators are modeled as a binary operator. E.g. ++x is
337
    // modeled as x + 1.
338
    assert((Op == UO_Minus || Op == UO_Not) && "non-supported unary expression");
339
    // Unary expressions are results of arithmetic. Pointer arithmetic is not
340
    // handled by unary expressions, but it is instead handled by applying
341
    // sub-regions to regions.
342
    assert(isValidTypeForSymbol(T) && "non-valid type for unary symbol");
343
    assert(!Loc::isLocType(T) && "unary symbol should be nonloc");
344
  }
345
 
346
  unsigned computeComplexity() const override {
347
    if (Complexity == 0)
348
      Complexity = 1 + Operand->computeComplexity();
349
    return Complexity;
350
  }
351
 
352
  const SymExpr *getOperand() const { return Operand; }
353
  UnaryOperator::Opcode getOpcode() const { return Op; }
354
  QualType getType() const override { return T; }
355
 
356
  void dumpToStream(raw_ostream &os) const override;
357
 
358
  static void Profile(llvm::FoldingSetNodeID &ID, const SymExpr *In,
359
                      UnaryOperator::Opcode Op, QualType T) {
360
    ID.AddInteger((unsigned)UnarySymExprKind);
361
    ID.AddPointer(In);
362
    ID.AddInteger(Op);
363
    ID.Add(T);
364
  }
365
 
366
  void Profile(llvm::FoldingSetNodeID &ID) override {
367
    Profile(ID, Operand, Op, T);
368
  }
369
 
370
  // Implement isa<T> support.
371
  static bool classof(const SymExpr *SE) {
372
    return SE->getKind() == UnarySymExprKind;
373
  }
374
};
375
 
376
/// Represents a symbolic expression involving a binary operator
377
class BinarySymExpr : public SymExpr {
378
  BinaryOperator::Opcode Op;
379
  QualType T;
380
 
381
protected:
382
  BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t)
383
      : SymExpr(k), Op(op), T(t) {
384
    assert(classof(this));
385
    // Binary expressions are results of arithmetic. Pointer arithmetic is not
386
    // handled by binary expressions, but it is instead handled by applying
387
    // sub-regions to regions.
388
    assert(isValidTypeForSymbol(t) && !Loc::isLocType(t));
389
  }
390
 
391
public:
392
  // FIXME: We probably need to make this out-of-line to avoid redundant
393
  // generation of virtual functions.
394
  QualType getType() const override { return T; }
395
 
396
  BinaryOperator::Opcode getOpcode() const { return Op; }
397
 
398
  // Implement isa<T> support.
399
  static bool classof(const SymExpr *SE) {
400
    Kind k = SE->getKind();
401
    return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS;
402
  }
403
 
404
protected:
405
  static unsigned computeOperandComplexity(const SymExpr *Value) {
406
    return Value->computeComplexity();
407
  }
408
  static unsigned computeOperandComplexity(const llvm::APSInt &Value) {
409
    return 1;
410
  }
411
 
412
  static const llvm::APSInt *getPointer(const llvm::APSInt &Value) {
413
    return &Value;
414
  }
415
  static const SymExpr *getPointer(const SymExpr *Value) { return Value; }
416
 
417
  static void dumpToStreamImpl(raw_ostream &os, const SymExpr *Value);
418
  static void dumpToStreamImpl(raw_ostream &os, const llvm::APSInt &Value);
419
  static void dumpToStreamImpl(raw_ostream &os, BinaryOperator::Opcode op);
420
};
421
 
422
/// Template implementation for all binary symbolic expressions
423
template <class LHSTYPE, class RHSTYPE, SymExpr::Kind ClassKind>
424
class BinarySymExprImpl : public BinarySymExpr {
425
  LHSTYPE LHS;
426
  RHSTYPE RHS;
427
 
428
public:
429
  BinarySymExprImpl(LHSTYPE lhs, BinaryOperator::Opcode op, RHSTYPE rhs,
430
                    QualType t)
431
      : BinarySymExpr(ClassKind, op, t), LHS(lhs), RHS(rhs) {
432
    assert(getPointer(lhs));
433
    assert(getPointer(rhs));
434
  }
435
 
436
  void dumpToStream(raw_ostream &os) const override {
437
    dumpToStreamImpl(os, LHS);
438
    dumpToStreamImpl(os, getOpcode());
439
    dumpToStreamImpl(os, RHS);
440
  }
441
 
442
  LHSTYPE getLHS() const { return LHS; }
443
  RHSTYPE getRHS() const { return RHS; }
444
 
445
  unsigned computeComplexity() const override {
446
    if (Complexity == 0)
447
      Complexity =
448
          computeOperandComplexity(RHS) + computeOperandComplexity(LHS);
449
    return Complexity;
450
  }
451
 
452
  static void Profile(llvm::FoldingSetNodeID &ID, LHSTYPE lhs,
453
                      BinaryOperator::Opcode op, RHSTYPE rhs, QualType t) {
454
    ID.AddInteger((unsigned)ClassKind);
455
    ID.AddPointer(getPointer(lhs));
456
    ID.AddInteger(op);
457
    ID.AddPointer(getPointer(rhs));
458
    ID.Add(t);
459
  }
460
 
461
  void Profile(llvm::FoldingSetNodeID &ID) override {
462
    Profile(ID, LHS, getOpcode(), RHS, getType());
463
  }
464
 
465
  // Implement isa<T> support.
466
  static bool classof(const SymExpr *SE) { return SE->getKind() == ClassKind; }
467
};
468
 
469
/// Represents a symbolic expression like 'x' + 3.
470
using SymIntExpr = BinarySymExprImpl<const SymExpr *, const llvm::APSInt &,
471
                                     SymExpr::Kind::SymIntExprKind>;
472
 
473
/// Represents a symbolic expression like 3 - 'x'.
474
using IntSymExpr = BinarySymExprImpl<const llvm::APSInt &, const SymExpr *,
475
                                     SymExpr::Kind::IntSymExprKind>;
476
 
477
/// Represents a symbolic expression like 'x' + 'y'.
478
using SymSymExpr = BinarySymExprImpl<const SymExpr *, const SymExpr *,
479
                                     SymExpr::Kind::SymSymExprKind>;
480
 
481
class SymbolManager {
482
  using DataSetTy = llvm::FoldingSet<SymExpr>;
483
  using SymbolDependTy =
484
      llvm::DenseMap<SymbolRef, std::unique_ptr<SymbolRefSmallVectorTy>>;
485
 
486
  DataSetTy DataSet;
487
 
488
  /// Stores the extra dependencies between symbols: the data should be kept
489
  /// alive as long as the key is live.
490
  SymbolDependTy SymbolDependencies;
491
 
492
  unsigned SymbolCounter = 0;
493
  llvm::BumpPtrAllocator& BPAlloc;
494
  BasicValueFactory &BV;
495
  ASTContext &Ctx;
496
 
497
public:
498
  SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
499
                llvm::BumpPtrAllocator& bpalloc)
500
      : SymbolDependencies(16), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
501
 
502
  static bool canSymbolicate(QualType T);
503
 
504
  /// Make a unique symbol for MemRegion R according to its kind.
505
  const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R);
506
 
507
  const SymbolConjured* conjureSymbol(const Stmt *E,
508
                                      const LocationContext *LCtx,
509
                                      QualType T,
510
                                      unsigned VisitCount,
511
                                      const void *SymbolTag = nullptr);
512
 
513
  const SymbolConjured* conjureSymbol(const Expr *E,
514
                                      const LocationContext *LCtx,
515
                                      unsigned VisitCount,
516
                                      const void *SymbolTag = nullptr) {
517
    return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
518
  }
519
 
520
  const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
521
                                        const TypedValueRegion *R);
522
 
523
  const SymbolExtent *getExtentSymbol(const SubRegion *R);
524
 
525
  /// Creates a metadata symbol associated with a specific region.
526
  ///
527
  /// VisitCount can be used to differentiate regions corresponding to
528
  /// different loop iterations, thus, making the symbol path-dependent.
529
  const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S,
530
                                          QualType T,
531
                                          const LocationContext *LCtx,
532
                                          unsigned VisitCount,
533
                                          const void *SymbolTag = nullptr);
534
 
535
  const SymbolCast* getCastSymbol(const SymExpr *Operand,
536
                                  QualType From, QualType To);
537
 
538
  const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
539
                                  const llvm::APSInt& rhs, QualType t);
540
 
541
  const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
542
                                  const llvm::APSInt& rhs, QualType t) {
543
    return getSymIntExpr(&lhs, op, rhs, t);
544
  }
545
 
546
  const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs,
547
                                  BinaryOperator::Opcode op,
548
                                  const SymExpr *rhs, QualType t);
549
 
550
  const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
551
                                  const SymExpr *rhs, QualType t);
552
 
553
  const UnarySymExpr *getUnarySymExpr(const SymExpr *operand,
554
                                      UnaryOperator::Opcode op, QualType t);
555
 
556
  QualType getType(const SymExpr *SE) const {
557
    return SE->getType();
558
  }
559
 
560
  /// Add artificial symbol dependency.
561
  ///
562
  /// The dependent symbol should stay alive as long as the primary is alive.
563
  void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent);
564
 
565
  const SymbolRefSmallVectorTy *getDependentSymbols(const SymbolRef Primary);
566
 
567
  ASTContext &getContext() { return Ctx; }
568
  BasicValueFactory &getBasicVals() { return BV; }
569
};
570
 
571
/// A class responsible for cleaning up unused symbols.
572
class SymbolReaper {
573
  enum SymbolStatus {
574
    NotProcessed,
575
    HaveMarkedDependents
576
  };
577
 
578
  using SymbolSetTy = llvm::DenseSet<SymbolRef>;
579
  using SymbolMapTy = llvm::DenseMap<SymbolRef, SymbolStatus>;
580
  using RegionSetTy = llvm::DenseSet<const MemRegion *>;
581
 
582
  SymbolMapTy TheLiving;
583
  SymbolSetTy MetadataInUse;
584
 
585
  RegionSetTy LiveRegionRoots;
586
  // The lazily copied regions are locations for which a program
587
  // can access the value stored at that location, but not its address.
588
  // These regions are constructed as a set of regions referred to by
589
  // lazyCompoundVal.
590
  RegionSetTy LazilyCopiedRegionRoots;
591
 
592
  const StackFrameContext *LCtx;
593
  const Stmt *Loc;
594
  SymbolManager& SymMgr;
595
  StoreRef reapedStore;
596
  llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
597
 
598
public:
599
  /// Construct a reaper object, which removes everything which is not
600
  /// live before we execute statement s in the given location context.
601
  ///
602
  /// If the statement is NULL, everything is this and parent contexts is
603
  /// considered live.
604
  /// If the stack frame context is NULL, everything on stack is considered
605
  /// dead.
606
  SymbolReaper(const StackFrameContext *Ctx, const Stmt *s,
607
               SymbolManager &symmgr, StoreManager &storeMgr)
608
      : LCtx(Ctx), Loc(s), SymMgr(symmgr), reapedStore(nullptr, storeMgr) {}
609
 
610
  /// It might return null.
611
  const LocationContext *getLocationContext() const { return LCtx; }
612
 
613
  bool isLive(SymbolRef sym);
614
  bool isLiveRegion(const MemRegion *region);
615
  bool isLive(const Expr *ExprVal, const LocationContext *LCtx) const;
616
  bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
617
 
618
  /// Unconditionally marks a symbol as live.
619
  ///
620
  /// This should never be
621
  /// used by checkers, only by the state infrastructure such as the store and
622
  /// environment. Checkers should instead use metadata symbols and markInUse.
623
  void markLive(SymbolRef sym);
624
 
625
  /// Marks a symbol as important to a checker.
626
  ///
627
  /// For metadata symbols,
628
  /// this will keep the symbol alive as long as its associated region is also
629
  /// live. For other symbols, this has no effect; checkers are not permitted
630
  /// to influence the life of other symbols. This should be used before any
631
  /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
632
  void markInUse(SymbolRef sym);
633
 
634
  using region_iterator = RegionSetTy::const_iterator;
635
 
636
  region_iterator region_begin() const { return LiveRegionRoots.begin(); }
637
  region_iterator region_end() const { return LiveRegionRoots.end(); }
638
 
639
  /// Returns whether or not a symbol has been confirmed dead.
640
  ///
641
  /// This should only be called once all marking of dead symbols has completed.
642
  /// (For checkers, this means only in the checkDeadSymbols callback.)
643
  bool isDead(SymbolRef sym) {
644
    return !isLive(sym);
645
  }
646
 
647
  void markLive(const MemRegion *region);
648
  void markLazilyCopied(const MemRegion *region);
649
  void markElementIndicesLive(const MemRegion *region);
650
 
651
  /// Set to the value of the symbolic store after
652
  /// StoreManager::removeDeadBindings has been called.
653
  void setReapedStore(StoreRef st) { reapedStore = st; }
654
 
655
private:
656
  bool isLazilyCopiedRegion(const MemRegion *region) const;
657
  // A readable region is a region that live or lazily copied.
658
  // Any symbols that refer to values in regions are alive if the region
659
  // is readable.
660
  bool isReadableRegion(const MemRegion *region);
661
 
662
  /// Mark the symbols dependent on the input symbol as live.
663
  void markDependentsLive(SymbolRef sym);
664
};
665
 
666
class SymbolVisitor {
667
protected:
668
  ~SymbolVisitor() = default;
669
 
670
public:
671
  SymbolVisitor() = default;
672
  SymbolVisitor(const SymbolVisitor &) = default;
673
  SymbolVisitor(SymbolVisitor &&) {}
674
 
675
  /// A visitor method invoked by ProgramStateManager::scanReachableSymbols.
676
  ///
677
  /// The method returns \c true if symbols should continue be scanned and \c
678
  /// false otherwise.
679
  virtual bool VisitSymbol(SymbolRef sym) = 0;
680
  virtual bool VisitMemRegion(const MemRegion *) { return true; }
681
};
682
 
683
} // namespace ento
684
 
685
} // namespace clang
686
 
687
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H