Skip to content

Commit f8a9d4c

Browse files
Add SymExpr::SymbolTooComplex
1 parent a5ae39c commit f8a9d4c

File tree

9 files changed

+203
-151
lines changed

9 files changed

+203
-151
lines changed

clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -317,21 +317,21 @@ class SValBuilder {
317317
return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits));
318318
}
319319

320-
DefinedOrUnknownSVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
321-
APSIntPtr rhs, QualType type);
320+
nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
321+
APSIntPtr rhs, QualType type);
322322

323-
DefinedOrUnknownSVal makeNonLoc(APSIntPtr rhs, BinaryOperator::Opcode op,
324-
const SymExpr *lhs, QualType type);
323+
nonloc::SymbolVal makeNonLoc(APSIntPtr rhs, BinaryOperator::Opcode op,
324+
const SymExpr *lhs, QualType type);
325325

326-
DefinedOrUnknownSVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
327-
const SymExpr *rhs, QualType type);
326+
nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
327+
const SymExpr *rhs, QualType type);
328328

329-
DefinedOrUnknownSVal makeNonLoc(const SymExpr *operand,
330-
UnaryOperator::Opcode op, QualType type);
329+
nonloc::SymbolVal makeNonLoc(const SymExpr *operand, UnaryOperator::Opcode op,
330+
QualType type);
331331

332332
/// Create a NonLoc value for cast.
333-
DefinedOrUnknownSVal makeNonLoc(const SymExpr *operand, QualType fromTy,
334-
QualType toTy);
333+
nonloc::SymbolVal makeNonLoc(const SymExpr *operand, QualType fromTy,
334+
QualType toTy);
335335

336336
nonloc::ConcreteInt makeTruthVal(bool b, QualType type) {
337337
return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type));

clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h

Lines changed: 131 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
1616

1717
#include "clang/AST/Expr.h"
18+
#include "clang/AST/OperationKinds.h"
1819
#include "clang/AST/Type.h"
1920
#include "clang/Analysis/AnalysisDeclContext.h"
2021
#include "clang/Basic/LLVM.h"
@@ -27,9 +28,11 @@
2728
#include "llvm/ADT/DenseSet.h"
2829
#include "llvm/ADT/FoldingSet.h"
2930
#include "llvm/ADT/ImmutableSet.h"
31+
#include "llvm/ADT/STLExtras.h"
3032
#include "llvm/ADT/iterator_range.h"
3133
#include "llvm/Support/Allocator.h"
3234
#include <cassert>
35+
#include <type_traits>
3336

3437
namespace clang {
3538

@@ -47,7 +50,7 @@ class SymbolRegionValue : public SymbolData {
4750

4851
friend class SymExprAllocator;
4952
SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
50-
: SymbolData(SymbolRegionValueKind, sym), R(r) {
53+
: SymbolData(ClassKind, sym), R(r) {
5154
assert(r);
5255
assert(isValidTypeForSymbol(r->getValueType()));
5356
}
@@ -57,7 +60,7 @@ class SymbolRegionValue : public SymbolData {
5760
const TypedValueRegion *getRegion() const { return R; }
5861

5962
static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
60-
profile.AddInteger((unsigned) SymbolRegionValueKind);
63+
profile.AddInteger((unsigned)ClassKind);
6164
profile.AddPointer(R);
6265
}
6366

@@ -91,8 +94,8 @@ class SymbolConjured : public SymbolData {
9194
SymbolConjured(SymbolID sym, ConstCFGElementRef elem,
9295
const LocationContext *lctx, QualType t, unsigned count,
9396
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) {
9699
assert(lctx);
97100
assert(isValidTypeForSymbol(t));
98101
}
@@ -116,7 +119,7 @@ class SymbolConjured : public SymbolData {
116119
static void Profile(llvm::FoldingSetNodeID &profile, ConstCFGElementRef Elem,
117120
const LocationContext *LCtx, QualType T, unsigned Count,
118121
const void *SymbolTag) {
119-
profile.AddInteger((unsigned)SymbolConjuredKind);
122+
profile.AddInteger((unsigned)ClassKind);
120123
profile.Add(Elem);
121124
profile.AddPointer(LCtx);
122125
profile.Add(T);
@@ -134,6 +137,101 @@ class SymbolConjured : public SymbolData {
134137
static constexpr bool classof(Kind K) { return K == ClassKind; }
135138
};
136139

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+
137235
/// A symbol representing the value of a MemRegion whose parent region has
138236
/// symbolic value.
139237
class SymbolDerived : public SymbolData {
@@ -142,7 +240,7 @@ class SymbolDerived : public SymbolData {
142240

143241
friend class SymExprAllocator;
144242
SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
145-
: SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) {
243+
: SymbolData(ClassKind, sym), parentSymbol(parent), R(r) {
146244
assert(parent);
147245
assert(r);
148246
assert(isValidTypeForSymbol(r->getValueType()));
@@ -163,7 +261,7 @@ class SymbolDerived : public SymbolData {
163261

164262
static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
165263
const TypedValueRegion *r) {
166-
profile.AddInteger((unsigned) SymbolDerivedKind);
264+
profile.AddInteger((unsigned)ClassKind);
167265
profile.AddPointer(r);
168266
profile.AddPointer(parent);
169267
}
@@ -188,7 +286,7 @@ class SymbolExtent : public SymbolData {
188286

189287
friend class SymExprAllocator;
190288
SymbolExtent(SymbolID sym, const SubRegion *r)
191-
: SymbolData(SymbolExtentKind, sym), R(r) {
289+
: SymbolData(ClassKind, sym), R(r) {
192290
assert(r);
193291
}
194292

@@ -203,7 +301,7 @@ class SymbolExtent : public SymbolData {
203301
void dumpToStream(raw_ostream &os) const override;
204302

205303
static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
206-
profile.AddInteger((unsigned) SymbolExtentKind);
304+
profile.AddInteger((unsigned)ClassKind);
207305
profile.AddPointer(R);
208306
}
209307

@@ -214,7 +312,7 @@ class SymbolExtent : public SymbolData {
214312
// Implement isa<T> support.
215313
static constexpr Kind ClassKind = SymbolExtentKind;
216314
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; }
218316
};
219317

220318
/// SymbolMetadata - Represents path-dependent metadata about a specific region.
@@ -232,16 +330,16 @@ class SymbolMetadata : public SymbolData {
232330
const void *Tag;
233331

234332
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,
236334
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+
}
245343

246344
public:
247345
LLVM_ATTRIBUTE_RETURNS_NONNULL
@@ -267,7 +365,7 @@ class SymbolMetadata : public SymbolData {
267365
static void Profile(llvm::FoldingSetNodeID &profile, const MemRegion *R,
268366
const Stmt *S, QualType T, const LocationContext *LCtx,
269367
unsigned Count, const void *Tag) {
270-
profile.AddInteger((unsigned)SymbolMetadataKind);
368+
profile.AddInteger((unsigned)ClassKind);
271369
profile.AddPointer(R);
272370
profile.AddPointer(S);
273371
profile.Add(T);
@@ -299,8 +397,8 @@ class SymbolCast : public SymExpr {
299397

300398
friend class SymExprAllocator;
301399
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) {
304402
assert(In);
305403
assert(isValidTypeForSymbol(From));
306404
// FIXME: GenericTaintChecker creates symbols of void type.
@@ -321,7 +419,7 @@ class SymbolCast : public SymExpr {
321419

322420
static void Profile(llvm::FoldingSetNodeID& ID,
323421
const SymExpr *In, QualType From, QualType To) {
324-
ID.AddInteger((unsigned) SymbolCastKind);
422+
ID.AddInteger((unsigned)ClassKind);
325423
ID.AddPointer(In);
326424
ID.Add(From);
327425
ID.Add(To);
@@ -347,8 +445,8 @@ class UnarySymExpr : public SymExpr {
347445
friend class SymExprAllocator;
348446
UnarySymExpr(SymbolID Sym, const SymExpr *In, UnaryOperator::Opcode Op,
349447
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) {
352450
// Note, some unary operators are modeled as a binary operator. E.g. ++x is
353451
// modeled as x + 1.
354452
assert((Op == UO_Minus || Op == UO_Not) && "non-supported unary expression");
@@ -373,7 +471,7 @@ class UnarySymExpr : public SymExpr {
373471

374472
static void Profile(llvm::FoldingSetNodeID &ID, const SymExpr *In,
375473
UnaryOperator::Opcode Op, QualType T) {
376-
ID.AddInteger((unsigned)UnarySymExprKind);
474+
ID.AddInteger((unsigned)ClassKind);
377475
ID.AddPointer(In);
378476
ID.AddInteger(Op);
379477
ID.Add(T);
@@ -498,33 +596,6 @@ using IntSymExpr = BinarySymExprImpl<APSIntPtr, const SymExpr *,
498596
using SymSymExpr = BinarySymExprImpl<const SymExpr *, const SymExpr *,
499597
SymExpr::Kind::SymSymExprKind>;
500598

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-
528599
class SymExprAllocator {
529600
SymbolID NextSymbolID = 0;
530601
llvm::BumpPtrAllocator &Alloc;
@@ -569,7 +640,8 @@ class SymbolManager {
569640
/// Create or retrieve a SymExpr of type \p SymExprT for the given arguments.
570641
/// Use the arguments to check for an existing SymExpr and return it,
571642
/// 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);
573645

574646
const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
575647
const LocationContext *LCtx, QualType T,
@@ -707,14 +779,15 @@ class SymbolVisitor {
707779
virtual bool VisitMemRegion(const MemRegion *) { return true; }
708780
};
709781

782+
// Returns a pointer to T if T is a SymbolData, otherwise SymExpr.
710783
template <typename T, typename... Args>
711-
auto SymbolManager::acquire(Args &&...args) {
784+
const auto *SymbolManager::acquire(Args &&...args) {
712785
constexpr bool IsSymbolData = SymbolData::classof(T::ClassKind);
713786
if constexpr (IsSymbolData) {
714787
assert(T::computeComplexity(args...) == 1);
715788
} else {
716789
if (T::computeComplexity(args...) > MaxCompComplexity) {
717-
return MaybeSymExpr();
790+
return static_cast<const SymExpr *>(acquire<SymbolTooComplex>(args...));
718791
}
719792
}
720793

@@ -725,12 +798,13 @@ auto SymbolManager::acquire(Args &&...args) {
725798
if (!SD) {
726799
SD = Alloc.make<T>(std::forward<Args>(args)...);
727800
DataSet.InsertNode(SD, InsertPos);
801+
assert(SD->complexity() <= MaxCompComplexity);
728802
}
729803

730804
if constexpr (IsSymbolData) {
731805
return cast<T>(SD);
732806
} else {
733-
return MaybeSymExpr(SD);
807+
return SD;
734808
}
735809
}
736810

clang/include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ SYMBOL(SymbolCast, SymExpr)
4545

4646
ABSTRACT_SYMBOL(SymbolData, SymExpr)
4747
SYMBOL(SymbolConjured, SymbolData)
48+
SYMBOL(SymbolTooComplex, SymbolData)
4849
SYMBOL(SymbolDerived, SymbolData)
4950
SYMBOL(SymbolExtent, SymbolData)
5051
SYMBOL(SymbolMetadata, SymbolData)

0 commit comments

Comments
 (0)