Skip to content

Commit 97c4e0e

Browse files
committed
WIP: use CFGElement in conjuredSymbol
1 parent 3e61c1a commit 97c4e0e

File tree

8 files changed

+200
-144
lines changed

8 files changed

+200
-144
lines changed

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

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/Expr.h"
2020
#include "clang/AST/ExprObjC.h"
2121
#include "clang/AST/Type.h"
22+
#include "clang/Analysis/CFG.h"
2223
#include "clang/Basic/LLVM.h"
2324
#include "clang/Basic/LangOptions.h"
2425
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
@@ -171,20 +172,27 @@ class SValBuilder {
171172

172173
// Forwarding methods to SymbolManager.
173174

174-
const SymbolConjured* conjureSymbol(const Stmt *stmt,
175+
const SymbolConjured *conjureSymbol(const CFGBlock::CFGElementRef ElemRef,
175176
const LocationContext *LCtx,
176-
QualType type,
177-
unsigned visitCount,
177+
QualType type, unsigned visitCount,
178178
const void *symbolTag = nullptr) {
179-
return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
179+
return SymMgr.conjureSymbol(ElemRef, LCtx, type, visitCount, symbolTag);
180180
}
181181

182-
const SymbolConjured* conjureSymbol(const Expr *expr,
183-
const LocationContext *LCtx,
184-
unsigned visitCount,
185-
const void *symbolTag = nullptr) {
186-
return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
187-
}
182+
// const SymbolConjured* conjureSymbol(const Stmt *stmt,
183+
// const LocationContext *LCtx,
184+
// QualType type,
185+
// unsigned visitCount,
186+
// const void *symbolTag = nullptr) {
187+
// return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
188+
// }
189+
190+
// const SymbolConjured* conjureSymbol(const Expr *expr,
191+
// const LocationContext *LCtx,
192+
// unsigned visitCount,
193+
// const void *symbolTag = nullptr) {
194+
// return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
195+
// }
188196

189197
/// Construct an SVal representing '0' for the specified type.
190198
DefinedOrUnknownSVal makeZeroVal(QualType type);
@@ -198,33 +206,38 @@ class SValBuilder {
198206
/// The advantage of symbols derived/built from other symbols is that we
199207
/// preserve the relation between related(or even equivalent) expressions, so
200208
/// conjured symbols should be used sparingly.
201-
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
202-
const Expr *expr,
203-
const LocationContext *LCtx,
204-
unsigned count);
205-
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Stmt *S,
206-
const LocationContext *LCtx,
207-
QualType type, unsigned count);
208-
DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
209-
const LocationContext *LCtx,
210-
QualType type,
211-
unsigned visitCount);
212-
213-
/// Conjure a symbol representing heap allocated memory region.
214-
///
215-
/// Note, the expression should represent a location.
216-
DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
217-
const LocationContext *LCtx,
218-
unsigned Count);
219-
220-
/// Conjure a symbol representing heap allocated memory region.
221-
///
222-
/// Note, now, the expression *doesn't* need to represent a location.
223-
/// But the type need to!
224-
DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
225-
const LocationContext *LCtx,
226-
QualType type, unsigned Count);
227-
209+
// DefinedOrUnknownSVal
210+
// conjureSymbolVal(const void *symbolTag,
211+
// const CFGBlock::ConstCFGElementRef elemRef,
212+
// const LocationContext *LCtx, unsigned count);
213+
DefinedOrUnknownSVal
214+
conjureSymbolVal(const void *symbolTag,
215+
const CFGBlock::ConstCFGElementRef elemRef,
216+
const LocationContext *LCtx, QualType type, unsigned count);
217+
DefinedOrUnknownSVal
218+
conjureSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
219+
const LocationContext *LCtx, QualType type,
220+
unsigned visitCount);
221+
222+
// /// Conjure a symbol representing heap allocated memory region.
223+
// ///
224+
// /// Note, the expression should represent a location.
225+
// DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
226+
// const LocationContext *LCtx,
227+
// unsigned Count);
228+
229+
// /// Conjure a symbol representing heap allocated memory region.
230+
// ///
231+
// /// Note, now, the expression *doesn't* need to represent a location.
232+
// /// But the type need to!
233+
// DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
234+
// const LocationContext *LCtx,
235+
// QualType type, unsigned Count);
236+
237+
DefinedSVal
238+
getConjuredHeapSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
239+
const LocationContext *LCtx, QualType type,
240+
unsigned Count);
228241
/// Create an SVal representing the result of an alloca()-like call, that is,
229242
/// an AllocaRegion on the stack.
230243
///

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

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "clang/AST/Expr.h"
1818
#include "clang/AST/Type.h"
1919
#include "clang/Analysis/AnalysisDeclContext.h"
20+
#include "clang/Analysis/CFG.h"
2021
#include "clang/Basic/LLVM.h"
2122
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h"
2223
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
@@ -85,12 +86,14 @@ class SymbolConjured : public SymbolData {
8586
unsigned Count;
8687
const LocationContext *LCtx;
8788
const void *SymbolTag;
89+
const CFGBlock::ConstCFGElementRef ElemRef;
8890

8991
friend class SymExprAllocator;
90-
SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
91-
QualType t, unsigned count, const void *symbolTag)
92-
: SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
93-
LCtx(lctx), SymbolTag(symbolTag) {
92+
SymbolConjured(SymbolID sym, CFGBlock::ConstCFGElementRef elemRef,
93+
const LocationContext *lctx, QualType t, unsigned count,
94+
const void *symbolTag)
95+
: SymbolData(SymbolConjuredKind, sym), S(nullptr), T(t), Count(count),
96+
LCtx(lctx), SymbolTag(symbolTag), ElemRef(elemRef) {
9497
// FIXME: 's' might be a nullptr if we're conducting invalidation
9598
// that was caused by a destructor call on a temporary object,
9699
// which has no statement associated with it.
@@ -102,7 +105,12 @@ class SymbolConjured : public SymbolData {
102105

103106
public:
104107
/// It might return null.
105-
const Stmt *getStmt() const { return S; }
108+
const Stmt *getStmt() const {
109+
if (auto Stmt = ElemRef->getAs<CFGStmt>()) {
110+
return Stmt->getStmt();
111+
}
112+
return S;
113+
}
106114
unsigned getCount() const { return Count; }
107115
/// It might return null.
108116
const void *getTag() const { return SymbolTag; }
@@ -113,19 +121,21 @@ class SymbolConjured : public SymbolData {
113121

114122
void dumpToStream(raw_ostream &os) const override;
115123

116-
static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S,
124+
static void Profile(llvm::FoldingSetNodeID &profile,
125+
const CFGBlock::ConstCFGElementRef ElemRef,
117126
const LocationContext *LCtx, QualType T, unsigned Count,
118127
const void *SymbolTag) {
119128
profile.AddInteger((unsigned)SymbolConjuredKind);
120-
profile.AddPointer(S);
129+
// profile.Add(ElemRef);
130+
// profile.AddPointer(S);
121131
profile.AddPointer(LCtx);
122132
profile.Add(T);
123133
profile.AddInteger(Count);
124134
profile.AddPointer(SymbolTag);
125135
}
126136

127137
void Profile(llvm::FoldingSetNodeID& profile) override {
128-
Profile(profile, S, LCtx, T, Count, SymbolTag);
138+
Profile(profile, ElemRef, LCtx, T, Count, SymbolTag);
129139
}
130140

131141
// Implement isa<T> support.
@@ -533,20 +543,28 @@ class SymbolManager {
533543
template <typename SymExprT, typename... Args>
534544
const SymExprT *acquire(Args &&...args);
535545

536-
const SymbolConjured *conjureSymbol(const Stmt *E,
537-
const LocationContext *LCtx, QualType T,
538-
unsigned VisitCount,
539-
const void *SymbolTag = nullptr) {
540-
return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
541-
}
546+
// const SymbolConjured *conjureSymbol(const Stmt *E,
547+
// const LocationContext *LCtx, QualType
548+
// T, unsigned VisitCount, const void
549+
// *SymbolTag = nullptr) {
550+
// return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
551+
// }
542552

543-
const SymbolConjured* conjureSymbol(const Expr *E,
544-
const LocationContext *LCtx,
545-
unsigned VisitCount,
546-
const void *SymbolTag = nullptr) {
547-
return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
553+
const SymbolConjured *
554+
conjureSymbol(const CFGBlock::ConstCFGElementRef ElemRef,
555+
const LocationContext *LCtx, QualType T, unsigned VisitCount,
556+
const void *SymbolTag = nullptr) {
557+
558+
return acquire<SymbolConjured>(ElemRef, LCtx, T, VisitCount, SymbolTag);
548559
}
549560

561+
// const SymbolConjured* conjureSymbol(const Expr *E,
562+
// const LocationContext *LCtx,
563+
// unsigned VisitCount,
564+
// const void *SymbolTag = nullptr) {
565+
// return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
566+
// }
567+
550568
QualType getType(const SymExpr *SE) const {
551569
return SE->getType();
552570
}

clang/lib/StaticAnalyzer/Core/ExprEngine.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,8 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
437437
// values inside Reg would be correct.
438438
SVal InitVal = State->getSVal(Init, LC);
439439
if (InitVal.isUnknown()) {
440-
InitVal = getSValBuilder().conjureSymbolVal(Result, LC, Init->getType(),
441-
currBldrCtx->blockCount());
440+
InitVal = getSValBuilder().conjureSymbolVal(
441+
getCFGElementRef(), LC, Init->getType(), currBldrCtx->blockCount());
442442
State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
443443

444444
// Then we'd need to take the value that certainly exists and bind it
@@ -447,7 +447,7 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
447447
// Try to recover some path sensitivity in case we couldn't
448448
// compute the value.
449449
InitValWithAdjustments = getSValBuilder().conjureSymbolVal(
450-
Result, LC, InitWithAdjustments->getType(),
450+
getCFGElementRef(), LC, InitWithAdjustments->getType(),
451451
currBldrCtx->blockCount());
452452
}
453453
State =
@@ -1213,9 +1213,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
12131213
// If we fail to get the value for some reason, use a symbolic value.
12141214
if (InitVal.isUnknownOrUndef()) {
12151215
SValBuilder &SVB = getSValBuilder();
1216-
InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
1217-
Field->getType(),
1218-
currBldrCtx->blockCount());
1216+
InitVal =
1217+
SVB.conjureSymbolVal(getCFGElementRef(), stackFrame,
1218+
Field->getType(), currBldrCtx->blockCount());
12191219
}
12201220
} else {
12211221
InitVal = State->getSVal(BMI->getInit(), stackFrame);
@@ -2054,9 +2054,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
20542054

20552055
for (const auto N : preVisit) {
20562056
const LocationContext *LCtx = N->getLocationContext();
2057-
SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
2058-
resultType,
2059-
currBldrCtx->blockCount());
2057+
SVal result =
2058+
svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
2059+
resultType, currBldrCtx->blockCount());
20602060
ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
20612061

20622062
// Escape pointers passed into the list, unless it's an ObjC boxed

clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "clang/AST/DeclCXX.h"
1414
#include "clang/AST/ExprCXX.h"
15+
#include "clang/Analysis/CFG.h"
1516
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1617
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
1718
#include <optional>
@@ -26,13 +27,15 @@ using llvm::APSInt;
2627
/// (offset) if it is unknown so that memory arithmetic always
2728
/// results in an ElementRegion.
2829
/// \p Count The number of times the current basic block was visited.
29-
static SVal conjureOffsetSymbolOnLocation(
30-
SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder,
31-
unsigned Count, const LocationContext *LCtx) {
32-
QualType Ty = Expression->getType();
30+
static SVal conjureOffsetSymbolOnLocation(SVal Symbol, SVal Other,
31+
CFGBlock::ConstCFGElementRef elemRef,
32+
QualType Ty, SValBuilder &svalBuilder,
33+
unsigned Count,
34+
const LocationContext *LCtx) {
35+
// QualType Ty = Expression->getType();
3336
if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() &&
3437
Symbol.isUnknown()) {
35-
return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count);
38+
return svalBuilder.conjureSymbolVal(elemRef, LCtx, Ty, Count);
3639
}
3740
return Symbol;
3841
}
@@ -65,8 +68,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
6568
// FIXME: Handle structs.
6669
if (RightV.isUnknown()) {
6770
unsigned Count = currBldrCtx->blockCount();
68-
RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx,
69-
Count);
71+
RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
72+
B->getRHS()->getType(), Count);
7073
}
7174
// Simulate the effects of a "store": bind the value of the RHS
7275
// to the L-Value represented by the LHS.
@@ -84,9 +87,11 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
8487
// SymSymExpr.
8588
unsigned Count = currBldrCtx->blockCount();
8689
RightV = conjureOffsetSymbolOnLocation(
87-
RightV, LeftV, RHS, svalBuilder, Count, LCtx);
88-
LeftV = conjureOffsetSymbolOnLocation(
89-
LeftV, RightV, LHS, svalBuilder, Count, LCtx);
90+
RightV, LeftV, getCFGElementRef(), RHS->getType(), svalBuilder,
91+
Count, LCtx);
92+
LeftV = conjureOffsetSymbolOnLocation(LeftV, RightV, getCFGElementRef(),
93+
LHS->getType(), svalBuilder,
94+
Count, LCtx);
9095
}
9196

9297
// Although we don't yet model pointers-to-members, we do need to make
@@ -165,8 +170,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
165170
// The symbolic value is actually for the type of the left-hand side
166171
// expression, not the computation type, as this is the value the
167172
// LValue on the LHS will bind to.
168-
LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy,
169-
currBldrCtx->blockCount());
173+
LHSVal = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
174+
LTy, currBldrCtx->blockCount());
170175
// However, we need to convert the symbol to the computation type.
171176
Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
172177
} else {
@@ -459,9 +464,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
459464
} else {
460465
// If we don't know if the cast succeeded, conjure a new symbol.
461466
if (val.isUnknown()) {
462-
DefinedOrUnknownSVal NewSym =
463-
svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
464-
currBldrCtx->blockCount());
467+
DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal(
468+
nullptr, getCFGElementRef(), LCtx, resultType,
469+
currBldrCtx->blockCount());
465470
state = state->BindExpr(CastE, LCtx, NewSym);
466471
} else
467472
// Else, bind to the derived region value.
@@ -483,9 +488,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
483488

484489
// Failed to cast or the result is unknown, fall back to conservative.
485490
if (val.isUnknown()) {
486-
val =
487-
svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
488-
currBldrCtx->blockCount());
491+
val = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
492+
resultType,
493+
currBldrCtx->blockCount());
489494
}
490495
state = state->BindExpr(CastE, LCtx, val);
491496
Bldr.generateNode(CastE, Pred, state);
@@ -529,7 +534,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
529534
if (CastE->isGLValue())
530535
resultType = getContext().getPointerType(resultType);
531536
SVal result = svalBuilder.conjureSymbolVal(
532-
/*symbolTag=*/nullptr, CastE, LCtx, resultType,
537+
/*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
533538
currBldrCtx->blockCount());
534539
state = state->BindExpr(CastE, LCtx, result);
535540
Bldr.generateNode(CastE, Pred, state);
@@ -621,8 +626,8 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
621626
Ty = getContext().getPointerType(Ty);
622627
}
623628

624-
InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty,
625-
currBldrCtx->blockCount());
629+
InitVal = svalBuilder.conjureSymbolVal(
630+
nullptr, getCFGElementRef(), LC, Ty, currBldrCtx->blockCount());
626631
}
627632

628633

@@ -839,8 +844,8 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
839844
}
840845

841846
if (!hasValue)
842-
V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
843-
currBldrCtx->blockCount());
847+
V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
848+
Ex->getType(), currBldrCtx->blockCount());
844849

845850
// Generate a new node with the binding from the appropriate path.
846851
B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
@@ -1122,8 +1127,8 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
11221127
// Conjure a new symbol if necessary to recover precision.
11231128
if (Result.isUnknown()){
11241129
DefinedOrUnknownSVal SymVal =
1125-
svalBuilder.conjureSymbolVal(nullptr, U, LCtx,
1126-
currBldrCtx->blockCount());
1130+
svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
1131+
U->getType(), currBldrCtx->blockCount());
11271132
Result = SymVal;
11281133

11291134
// If the value is a location, ++/-- should always preserve

0 commit comments

Comments
 (0)