15
15
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
16
16
17
17
#include " clang/AST/Expr.h"
18
+ #include " clang/AST/OperationKinds.h"
18
19
#include " clang/AST/Type.h"
19
20
#include " clang/Analysis/AnalysisDeclContext.h"
20
21
#include " clang/Basic/LLVM.h"
27
28
#include " llvm/ADT/DenseSet.h"
28
29
#include " llvm/ADT/FoldingSet.h"
29
30
#include " llvm/ADT/ImmutableSet.h"
31
+ #include " llvm/ADT/STLExtras.h"
30
32
#include " llvm/ADT/iterator_range.h"
31
33
#include " llvm/Support/Allocator.h"
32
34
#include < cassert>
35
+ #include < type_traits>
33
36
34
37
namespace clang {
35
38
@@ -47,7 +50,7 @@ class SymbolRegionValue : public SymbolData {
47
50
48
51
friend class SymExprAllocator ;
49
52
SymbolRegionValue (SymbolID sym, const TypedValueRegion *r)
50
- : SymbolData(SymbolRegionValueKind , sym), R(r) {
53
+ : SymbolData(ClassKind , sym), R(r) {
51
54
assert (r);
52
55
assert (isValidTypeForSymbol (r->getValueType ()));
53
56
}
@@ -57,7 +60,7 @@ class SymbolRegionValue : public SymbolData {
57
60
const TypedValueRegion *getRegion () const { return R; }
58
61
59
62
static void Profile (llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
60
- profile.AddInteger ((unsigned ) SymbolRegionValueKind );
63
+ profile.AddInteger ((unsigned )ClassKind );
61
64
profile.AddPointer (R);
62
65
}
63
66
@@ -91,8 +94,8 @@ class SymbolConjured : public SymbolData {
91
94
SymbolConjured (SymbolID sym, ConstCFGElementRef elem,
92
95
const LocationContext *lctx, QualType t, unsigned count,
93
96
const void *symbolTag)
94
- : SymbolData(SymbolConjuredKind , sym), Elem(elem), T(t), Count(count),
95
- LCtx (lctx), SymbolTag(symbolTag) {
97
+ : SymbolData(ClassKind , sym), Elem(elem), T(t), Count(count), LCtx(lctx ),
98
+ SymbolTag (symbolTag) {
96
99
assert (lctx);
97
100
assert (isValidTypeForSymbol (t));
98
101
}
@@ -116,7 +119,7 @@ class SymbolConjured : public SymbolData {
116
119
static void Profile (llvm::FoldingSetNodeID &profile, ConstCFGElementRef Elem,
117
120
const LocationContext *LCtx, QualType T, unsigned Count,
118
121
const void *SymbolTag) {
119
- profile.AddInteger ((unsigned )SymbolConjuredKind );
122
+ profile.AddInteger ((unsigned )ClassKind );
120
123
profile.Add (Elem);
121
124
profile.AddPointer (LCtx);
122
125
profile.Add (T);
@@ -134,6 +137,101 @@ class SymbolConjured : public SymbolData {
134
137
static constexpr bool classof (Kind K) { return K == ClassKind; }
135
138
};
136
139
140
+ // / A symbol representing the result of an expression that became too
141
+ // / complicated. In other words, its complexity would have surpassed the
142
+ // / MaxSymbolComplexity threshold.
143
+ // / TODO: When the MaxSymbolComplexity is reached, we should propagate the taint
144
+ // / info to it.
145
+ class SymbolTooComplex final : public SymbolData {
146
+ // Pointer to either "SymExpr" or "APSInt".
147
+ const void *LHS;
148
+ const void *RHS = nullptr ; // optional
149
+ QualType Ty;
150
+ using OpKindType = std::make_unsigned_t <
151
+ std::common_type_t <BinaryOperatorKind, UnaryOperatorKind>>;
152
+ OpKindType Op = 0 ;
153
+
154
+ friend class SymExprAllocator ;
155
+
156
+ static const void *getPointer (APSIntPtr Value) { return Value.get (); }
157
+ static const void *getPointer (const SymExpr *Value) { return Value; }
158
+
159
+ template <typename LHSTYPE, typename RHSTYPE>
160
+ using assertTypesForOperands = std::enable_if_t <
161
+ llvm::is_one_of<LHSTYPE, const SymExpr *, APSIntPtr>::value &&
162
+ llvm::is_one_of<RHSTYPE, const SymExpr *, APSIntPtr>::value>;
163
+
164
+ // Constructing from BinarySymExprImpl ctor arguments.
165
+ template <typename LHSTYPE, typename RHSTYPE,
166
+ typename = assertTypesForOperands<LHSTYPE, RHSTYPE>>
167
+ SymbolTooComplex (SymbolID Sym, LHSTYPE LHS, BinaryOperatorKind Op,
168
+ RHSTYPE RHS, QualType Ty)
169
+ : SymbolData(ClassKind, Sym), LHS(getPointer(LHS)), RHS(getPointer(RHS)),
170
+ Ty (Ty), Op(static_cast <OpKindType>(Op)) {
171
+ assert (this ->LHS );
172
+ assert (this ->RHS );
173
+ }
174
+
175
+ // Constructing from UnarySymExpr ctor arguments.
176
+ SymbolTooComplex (SymbolID Sym, const SymExpr *Operand, UnaryOperatorKind Op,
177
+ QualType Ty)
178
+ : SymbolData(ClassKind, Sym), LHS(Operand), Ty(Ty),
179
+ Op(static_cast <OpKindType>(Op)) {
180
+ assert (LHS);
181
+ assert (!RHS);
182
+ }
183
+
184
+ // Constructing from SymbolCast ctor arguments.
185
+ SymbolTooComplex (SymbolID Sym, const SymExpr *Operand, QualType,
186
+ QualType ToTy)
187
+ : SymbolData(ClassKind, Sym), LHS(Operand), Ty(ToTy), Op(~0 ) {}
188
+
189
+ public:
190
+ QualType getType () const override { return Ty; }
191
+
192
+ StringRef getKindStr () const override ;
193
+
194
+ void dumpToStream (raw_ostream &os) const override ;
195
+
196
+ static void Profile (llvm::FoldingSetNodeID &profile, const void *LHS,
197
+ OpKindType Op, const void *RHS, QualType Ty) {
198
+ profile.AddInteger ((unsigned )ClassKind);
199
+ profile.AddPointer (LHS);
200
+ profile.AddPointer (RHS);
201
+ profile.Add (Ty);
202
+ profile.AddInteger (Op);
203
+ }
204
+
205
+ // Profile from BinarySymExprImpl ctor arguments.
206
+ template <typename LHSTYPE, typename RHSTYPE,
207
+ typename = assertTypesForOperands<LHSTYPE, RHSTYPE>>
208
+ static void Profile (llvm::FoldingSetNodeID &profile, LHSTYPE LHS,
209
+ OpKindType Op, RHSTYPE RHS, QualType Ty) {
210
+ Profile (profile, getPointer (LHS), Op, getPointer (RHS), Ty);
211
+ }
212
+
213
+ // Profile from UnarySymExpr ctor arguments.
214
+ static void Profile (llvm::FoldingSetNodeID &profile, const SymExpr *Operand,
215
+ UnaryOperatorKind Op, QualType Ty) {
216
+ Profile (profile, Operand, Op, /* RHS=*/ nullptr , Ty);
217
+ }
218
+
219
+ // Profile from SymbolCast ctor arguments.
220
+ static void Profile (llvm::FoldingSetNodeID &profile, const SymExpr *Operand,
221
+ QualType, QualType ToTy) {
222
+ Profile (profile, Operand, /* Op=*/ ~0 , /* RHS=*/ nullptr , ToTy);
223
+ }
224
+
225
+ void Profile (llvm::FoldingSetNodeID &profile) override {
226
+ Profile (profile, LHS, Op, RHS, Ty);
227
+ }
228
+
229
+ // Implement isa<T> support.
230
+ static constexpr Kind ClassKind = SymbolTooComplexKind;
231
+ static bool classof (const SymExpr *SE) { return classof (SE->getKind ()); }
232
+ static constexpr bool classof (Kind K) { return K == ClassKind; }
233
+ };
234
+
137
235
// / A symbol representing the value of a MemRegion whose parent region has
138
236
// / symbolic value.
139
237
class SymbolDerived : public SymbolData {
@@ -142,7 +240,7 @@ class SymbolDerived : public SymbolData {
142
240
143
241
friend class SymExprAllocator ;
144
242
SymbolDerived (SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
145
- : SymbolData(SymbolDerivedKind , sym), parentSymbol(parent), R(r) {
243
+ : SymbolData(ClassKind , sym), parentSymbol(parent), R(r) {
146
244
assert (parent);
147
245
assert (r);
148
246
assert (isValidTypeForSymbol (r->getValueType ()));
@@ -163,7 +261,7 @@ class SymbolDerived : public SymbolData {
163
261
164
262
static void Profile (llvm::FoldingSetNodeID& profile, SymbolRef parent,
165
263
const TypedValueRegion *r) {
166
- profile.AddInteger ((unsigned ) SymbolDerivedKind );
264
+ profile.AddInteger ((unsigned )ClassKind );
167
265
profile.AddPointer (r);
168
266
profile.AddPointer (parent);
169
267
}
@@ -188,7 +286,7 @@ class SymbolExtent : public SymbolData {
188
286
189
287
friend class SymExprAllocator ;
190
288
SymbolExtent (SymbolID sym, const SubRegion *r)
191
- : SymbolData(SymbolExtentKind , sym), R(r) {
289
+ : SymbolData(ClassKind , sym), R(r) {
192
290
assert (r);
193
291
}
194
292
@@ -203,7 +301,7 @@ class SymbolExtent : public SymbolData {
203
301
void dumpToStream (raw_ostream &os) const override ;
204
302
205
303
static void Profile (llvm::FoldingSetNodeID& profile, const SubRegion *R) {
206
- profile.AddInteger ((unsigned ) SymbolExtentKind );
304
+ profile.AddInteger ((unsigned )ClassKind );
207
305
profile.AddPointer (R);
208
306
}
209
307
@@ -214,7 +312,7 @@ class SymbolExtent : public SymbolData {
214
312
// Implement isa<T> support.
215
313
static constexpr Kind ClassKind = SymbolExtentKind;
216
314
static bool classof (const SymExpr *SE) { return classof (SE->getKind ()); }
217
- static constexpr bool classof (Kind K) { return K == SymbolExtentKind ; }
315
+ static constexpr bool classof (Kind K) { return K == ClassKind ; }
218
316
};
219
317
220
318
// / SymbolMetadata - Represents path-dependent metadata about a specific region.
@@ -232,16 +330,16 @@ class SymbolMetadata : public SymbolData {
232
330
const void *Tag;
233
331
234
332
friend class SymExprAllocator ;
235
- SymbolMetadata (SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
333
+ SymbolMetadata (SymbolID sym, const MemRegion * r, const Stmt *s, QualType t,
236
334
const LocationContext *LCtx, unsigned count, const void *tag)
237
- : SymbolData(SymbolMetadataKind , sym), R(r), S(s), T(t), LCtx(LCtx),
238
- Count (count), Tag(tag) {
239
- assert (r);
240
- assert (s);
241
- assert (isValidTypeForSymbol (t));
242
- assert (LCtx);
243
- assert (tag);
244
- }
335
+ : SymbolData(ClassKind , sym), R(r), S(s), T(t), LCtx(LCtx), Count(count ),
336
+ Tag (tag) {
337
+ assert (r);
338
+ assert (s);
339
+ assert (isValidTypeForSymbol (t));
340
+ assert (LCtx);
341
+ assert (tag);
342
+ }
245
343
246
344
public:
247
345
LLVM_ATTRIBUTE_RETURNS_NONNULL
@@ -267,7 +365,7 @@ class SymbolMetadata : public SymbolData {
267
365
static void Profile (llvm::FoldingSetNodeID &profile, const MemRegion *R,
268
366
const Stmt *S, QualType T, const LocationContext *LCtx,
269
367
unsigned Count, const void *Tag) {
270
- profile.AddInteger ((unsigned )SymbolMetadataKind );
368
+ profile.AddInteger ((unsigned )ClassKind );
271
369
profile.AddPointer (R);
272
370
profile.AddPointer (S);
273
371
profile.Add (T);
@@ -299,8 +397,8 @@ class SymbolCast : public SymExpr {
299
397
300
398
friend class SymExprAllocator ;
301
399
SymbolCast (SymbolID Sym, const SymExpr *In, QualType From, QualType To)
302
- : SymExpr(SymbolCastKind , Sym, computeComplexity(In, From, To)),
303
- Operand (In), FromTy(From), ToTy(To) {
400
+ : SymExpr(ClassKind , Sym, computeComplexity(In, From, To)), Operand(In ),
401
+ FromTy (From), ToTy(To) {
304
402
assert (In);
305
403
assert (isValidTypeForSymbol (From));
306
404
// FIXME: GenericTaintChecker creates symbols of void type.
@@ -321,7 +419,7 @@ class SymbolCast : public SymExpr {
321
419
322
420
static void Profile (llvm::FoldingSetNodeID& ID,
323
421
const SymExpr *In, QualType From, QualType To) {
324
- ID.AddInteger ((unsigned ) SymbolCastKind );
422
+ ID.AddInteger ((unsigned )ClassKind );
325
423
ID.AddPointer (In);
326
424
ID.Add (From);
327
425
ID.Add (To);
@@ -347,8 +445,8 @@ class UnarySymExpr : public SymExpr {
347
445
friend class SymExprAllocator ;
348
446
UnarySymExpr (SymbolID Sym, const SymExpr *In, UnaryOperator::Opcode Op,
349
447
QualType T)
350
- : SymExpr(UnarySymExprKind , Sym, computeComplexity(In, Op, T)),
351
- Operand (In), Op(Op), T(T) {
448
+ : SymExpr(ClassKind , Sym, computeComplexity(In, Op, T)), Operand(In ),
449
+ Op (Op), T(T) {
352
450
// Note, some unary operators are modeled as a binary operator. E.g. ++x is
353
451
// modeled as x + 1.
354
452
assert ((Op == UO_Minus || Op == UO_Not) && " non-supported unary expression" );
@@ -373,7 +471,7 @@ class UnarySymExpr : public SymExpr {
373
471
374
472
static void Profile (llvm::FoldingSetNodeID &ID, const SymExpr *In,
375
473
UnaryOperator::Opcode Op, QualType T) {
376
- ID.AddInteger ((unsigned )UnarySymExprKind );
474
+ ID.AddInteger ((unsigned )ClassKind );
377
475
ID.AddPointer (In);
378
476
ID.AddInteger (Op);
379
477
ID.Add (T);
@@ -498,33 +596,6 @@ using IntSymExpr = BinarySymExprImpl<APSIntPtr, const SymExpr *,
498
596
using SymSymExpr = BinarySymExprImpl<const SymExpr *, const SymExpr *,
499
597
SymExpr::Kind::SymSymExprKind>;
500
598
501
- struct MaybeSymExpr {
502
- MaybeSymExpr () = default ;
503
- explicit MaybeSymExpr (SymbolRef Sym) : Sym(Sym) {}
504
- bool isValid () const { return Sym; }
505
- bool isInvalid () const { return !isValid (); }
506
- SymbolRef operator ->() const { return Sym; }
507
-
508
- SymbolRef getOrNull () const { return Sym; }
509
- template <typename SymT> const SymT *getOrNull () const {
510
- return llvm::dyn_cast_if_present<SymT>(Sym);
511
- }
512
-
513
- DefinedOrUnknownSVal getOrUnknown () const {
514
- if (isInvalid ())
515
- return UnknownVal ();
516
- return nonloc::SymbolVal (Sym);
517
- }
518
-
519
- nonloc::SymbolVal getOrAssert () const {
520
- assert (Sym);
521
- return nonloc::SymbolVal (Sym);
522
- }
523
-
524
- private:
525
- SymbolRef Sym = nullptr ;
526
- };
527
-
528
599
class SymExprAllocator {
529
600
SymbolID NextSymbolID = 0 ;
530
601
llvm::BumpPtrAllocator &Alloc;
@@ -569,7 +640,8 @@ class SymbolManager {
569
640
// / Create or retrieve a SymExpr of type \p SymExprT for the given arguments.
570
641
// / Use the arguments to check for an existing SymExpr and return it,
571
642
// / otherwise, create a new one and keep a pointer to it to avoid duplicates.
572
- template <typename SymExprT, typename ... Args> auto acquire (Args &&...args);
643
+ template <typename SymExprT, typename ... Args>
644
+ LLVM_ATTRIBUTE_RETURNS_NONNULL const auto *acquire (Args &&...args);
573
645
574
646
const SymbolConjured *conjureSymbol (ConstCFGElementRef Elem,
575
647
const LocationContext *LCtx, QualType T,
@@ -707,14 +779,15 @@ class SymbolVisitor {
707
779
virtual bool VisitMemRegion (const MemRegion *) { return true ; }
708
780
};
709
781
782
+ // Returns a pointer to T if T is a SymbolData, otherwise SymExpr.
710
783
template <typename T, typename ... Args>
711
- auto SymbolManager::acquire (Args &&...args) {
784
+ const auto * SymbolManager::acquire (Args &&...args) {
712
785
constexpr bool IsSymbolData = SymbolData::classof (T::ClassKind);
713
786
if constexpr (IsSymbolData) {
714
787
assert (T::computeComplexity (args...) == 1 );
715
788
} else {
716
789
if (T::computeComplexity (args...) > MaxCompComplexity) {
717
- return MaybeSymExpr ( );
790
+ return static_cast < const SymExpr *>(acquire<SymbolTooComplex>(args...) );
718
791
}
719
792
}
720
793
@@ -725,12 +798,13 @@ auto SymbolManager::acquire(Args &&...args) {
725
798
if (!SD) {
726
799
SD = Alloc.make <T>(std::forward<Args>(args)...);
727
800
DataSet.InsertNode (SD, InsertPos);
801
+ assert (SD->complexity () <= MaxCompComplexity);
728
802
}
729
803
730
804
if constexpr (IsSymbolData) {
731
805
return cast<T>(SD);
732
806
} else {
733
- return MaybeSymExpr (SD) ;
807
+ return SD ;
734
808
}
735
809
}
736
810
0 commit comments