Skip to content

Commit 2716967

Browse files
committed
[Clang][analyzer] replace Stmt* with ConstCFGElementRef in SymbolConjured
Closes #57270. This PR changes the `Stmt *` field in `SymbolConjured` with `CFGBlock::ConstCFGElementRef`. The motivation is that, when conjuring a symbol, there might not always be a statement available, causing information to be lost for conjured symbols, whereas the CFGElementRef can always be provided at the callsite. Following the idea, this PR changes callsites of functions to create conjured symbols, and replaces them with appropriate `CFGElementRef`s.
1 parent 7e11ef1 commit 2716967

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+523
-459
lines changed

clang/include/clang/Analysis/CFG.h

+15
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,21 @@ class CFGBlock {
695695
void dump() const {
696696
dumpToStream(llvm::errs());
697697
}
698+
699+
void Profile(llvm::FoldingSetNodeID &ID) const {
700+
ID.AddPointer(Parent);
701+
ID.AddInteger(Index);
702+
}
703+
704+
int64_t getID() const {
705+
if (Parent == nullptr || Parent->getParent() == nullptr) {
706+
return 0;
707+
}
708+
return Parent->getParent()
709+
->getAllocator()
710+
.template identifyKnownAlignedObject<CFGElement>(
711+
&*(Parent->begin() + Index));
712+
}
698713
};
699714

700715
template <bool IsReverse, bool IsConst> class ElementRefIterator {

clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#include "clang/AST/DeclCXX.h"
2020
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
2121
#include "llvm/ADT/StringExtras.h"
22+
#include "llvm/ADT/StringRef.h"
23+
#include "llvm/Support/raw_ostream.h"
24+
#include <cctype>
2225

2326
namespace clang {
2427

@@ -29,6 +32,16 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
2932
ASTContext &ACtx;
3033
ProgramStateRef State;
3134

35+
std::string printCFGElementRef(const CFGBlock::ConstCFGElementRef ElemRef) {
36+
std::string Str;
37+
llvm::raw_string_ostream OS(Str);
38+
ElemRef->dumpToStream(OS);
39+
// HACK: `CFGBlock::ConstCFGElementRef::dumpToStream` contains a new line
40+
// character in the end of the string, we don't want it so we remove it here.
41+
llvm::StringRef StrRef(Str);
42+
return StrRef.rtrim().str();
43+
}
44+
3245
std::string printStmt(const Stmt *S) {
3346
std::string Str;
3447
llvm::raw_string_ostream OS(Str);
@@ -114,7 +127,8 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
114127

115128
std::string VisitSymbolConjured(const SymbolConjured *S) {
116129
return "symbol of type '" + S->getType().getAsString() +
117-
"' conjured at statement '" + printStmt(S->getStmt()) + "'";
130+
"' conjured at statement '" +
131+
printCFGElementRef(S->getCFGElementRef()) + "'";
118132
}
119133

120134
std::string VisitSymbolDerived(const SymbolDerived *S) {

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

+4
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ class CheckerContext {
151151
return Pred->getSVal(S);
152152
}
153153

154+
CFGBlock::ConstCFGElementRef getCFGElementRef() const {
155+
return Eng.getCFGElementRef();
156+
}
157+
154158
/// Returns true if the value of \p E is greater than or equal to \p
155159
/// Val under unsigned comparison
156160
bool isGreaterOrEqual(const Expr *E, unsigned long long Val);

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ namespace ento {
2727
/// by the loop body in any iteration.
2828
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
2929
const LocationContext *LCtx,
30-
unsigned BlockCount, const Stmt *LoopStmt);
30+
unsigned BlockCount,
31+
const CFGBlock::ConstCFGElementRef ElemRef);
3132

3233
} // end namespace ento
3334
} // end namespace clang

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

+9-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
1414
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
1515

16+
#include "clang/Analysis/CFG.h"
1617
#include "clang/Basic/LLVM.h"
1718
#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
1819
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
@@ -314,7 +315,8 @@ class ProgramState : public llvm::FoldingSetNode {
314315
/// be triggered by this event.
315316
///
316317
/// \param Regions the set of regions to be invalidated.
317-
/// \param E the expression that caused the invalidation.
318+
/// \param ElemRef \p CFGBlock::ConstCFGElementRef that caused the
319+
/// invalidation.
318320
/// \param BlockCount The number of times the current basic block has been
319321
/// visited.
320322
/// \param CausesPointerEscape the flag is set to true when the invalidation
@@ -326,16 +328,18 @@ class ProgramState : public llvm::FoldingSetNode {
326328
/// \param ITraits information about special handling for particular regions
327329
/// or symbols.
328330
[[nodiscard]] ProgramStateRef
329-
invalidateRegions(ArrayRef<const MemRegion *> Regions, const Stmt *S,
331+
invalidateRegions(ArrayRef<const MemRegion *> Regions,
332+
const CFGBlock::ConstCFGElementRef ElemRef,
330333
unsigned BlockCount, const LocationContext *LCtx,
331334
bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
332335
const CallEvent *Call = nullptr,
333336
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
334337

335338
[[nodiscard]] ProgramStateRef
336-
invalidateRegions(ArrayRef<SVal> Values, const Stmt *S, unsigned BlockCount,
337-
const LocationContext *LCtx, bool CausesPointerEscape,
338-
InvalidatedSymbols *IS = nullptr,
339+
invalidateRegions(ArrayRef<SVal> Values,
340+
const CFGBlock::ConstCFGElementRef ElemRef,
341+
unsigned BlockCount, const LocationContext *LCtx,
342+
bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
339343
const CallEvent *Call = nullptr,
340344
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
341345

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

+22-37
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,19 +172,11 @@ class SValBuilder {
171172

172173
// Forwarding methods to SymbolManager.
173174

174-
const SymbolConjured* conjureSymbol(const Stmt *stmt,
175-
const LocationContext *LCtx,
176-
QualType type,
177-
unsigned visitCount,
178-
const void *symbolTag = nullptr) {
179-
return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
180-
}
181-
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);
175+
const SymbolConjured *
176+
conjureSymbol(const CFGBlock::ConstCFGElementRef ElemRef,
177+
const LocationContext *LCtx, QualType type, unsigned visitCount,
178+
const void *symbolTag = nullptr) {
179+
return SymMgr.conjureSymbol(ElemRef, LCtx, type, visitCount, symbolTag);
187180
}
188181

189182
/// Construct an SVal representing '0' for the specified type.
@@ -198,32 +191,24 @@ class SValBuilder {
198191
/// The advantage of symbols derived/built from other symbols is that we
199192
/// preserve the relation between related(or even equivalent) expressions, so
200193
/// 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);
194+
DefinedOrUnknownSVal
195+
conjureSymbolVal(const void *symbolTag,
196+
const CFGBlock::ConstCFGElementRef elemRef,
197+
const LocationContext *LCtx, unsigned count);
198+
DefinedOrUnknownSVal
199+
conjureSymbolVal(const void *symbolTag,
200+
const CFGBlock::ConstCFGElementRef elemRef,
201+
const LocationContext *LCtx, QualType type, unsigned count);
202+
DefinedOrUnknownSVal
203+
conjureSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
204+
const LocationContext *LCtx, QualType type,
205+
unsigned visitCount);
212206

213207
/// 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);
208+
DefinedSVal
209+
getConjuredHeapSymbolVal(const CFGBlock::ConstCFGElementRef elemRef,
210+
const LocationContext *LCtx, QualType type,
211+
unsigned Count);
227212

228213
/// Create an SVal representing the result of an alloca()-like call, that is,
229214
/// an AllocaRegion on the stack.

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

+7-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@
1414
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
1515

1616
#include "clang/AST/Type.h"
17+
#include "clang/Analysis/CFG.h"
18+
#include "clang/Basic/LLVM.h"
1719
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
1820
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
1921
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
2022
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
2123
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
2224
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
23-
#include "clang/Basic/LLVM.h"
2425
#include "llvm/ADT/ArrayRef.h"
2526
#include "llvm/ADT/DenseSet.h"
2627
#include "llvm/ADT/SmallVector.h"
@@ -223,8 +224,9 @@ class StoreManager {
223224
///
224225
/// \param[in] store The initial store.
225226
/// \param[in] Values The values to invalidate.
226-
/// \param[in] S The current statement being evaluated. Used to conjure
227-
/// symbols to mark the values of invalidated regions.
227+
/// \param[in] ElemRef The current \p CFGBlock::ConstCFGElementRef being
228+
/// evaluated. Used to conjure symbols to mark the values of invalidated
229+
/// regions.
228230
/// \param[in] Count The current block count. Used to conjure
229231
/// symbols to mark the values of invalidated regions.
230232
/// \param[in] Call The call expression which will be used to determine which
@@ -241,7 +243,8 @@ class StoreManager {
241243
/// even if they do not currently have bindings. Pass \c NULL if this
242244
/// information will not be used.
243245
virtual StoreRef invalidateRegions(
244-
Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
246+
Store store, ArrayRef<SVal> Values,
247+
const CFGBlock::ConstCFGElementRef ElemRef, unsigned Count,
245248
const LocationContext *LCtx, const CallEvent *Call,
246249
InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
247250
InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;

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

+20-26
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"
@@ -80,29 +81,27 @@ class SymbolRegionValue : public SymbolData {
8081
/// A symbol representing the result of an expression in the case when we do
8182
/// not know anything about what the expression is.
8283
class SymbolConjured : public SymbolData {
83-
const Stmt *S;
84+
const CFGBlock::ConstCFGElementRef ElemRef;
8485
QualType T;
8586
unsigned Count;
8687
const LocationContext *LCtx;
8788
const void *SymbolTag;
8889

8990
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) {
94-
// FIXME: 's' might be a nullptr if we're conducting invalidation
95-
// that was caused by a destructor call on a temporary object,
96-
// which has no statement associated with it.
97-
// Due to this, we might be creating the same invalidation symbol for
98-
// two different invalidation passes (for two different temporaries).
91+
SymbolConjured(SymbolID sym, CFGBlock::ConstCFGElementRef elemRef,
92+
const LocationContext *lctx, QualType t, unsigned count,
93+
const void *symbolTag)
94+
: SymbolData(SymbolConjuredKind, sym), ElemRef(elemRef), T(t),
95+
Count(count), LCtx(lctx), SymbolTag(symbolTag) {
9996
assert(lctx);
10097
assert(isValidTypeForSymbol(t));
10198
}
10299

103100
public:
104-
/// It might return null.
105-
const Stmt *getStmt() const { return S; }
101+
const CFGBlock::ConstCFGElementRef getCFGElementRef() const {
102+
return ElemRef;
103+
}
104+
106105
unsigned getCount() const { return Count; }
107106
/// It might return null.
108107
const void *getTag() const { return SymbolTag; }
@@ -113,19 +112,20 @@ class SymbolConjured : public SymbolData {
113112

114113
void dumpToStream(raw_ostream &os) const override;
115114

116-
static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S,
115+
static void Profile(llvm::FoldingSetNodeID &profile,
116+
const CFGBlock::ConstCFGElementRef ElemRef,
117117
const LocationContext *LCtx, QualType T, unsigned Count,
118118
const void *SymbolTag) {
119119
profile.AddInteger((unsigned)SymbolConjuredKind);
120-
profile.AddPointer(S);
120+
profile.Add(ElemRef);
121121
profile.AddPointer(LCtx);
122122
profile.Add(T);
123123
profile.AddInteger(Count);
124124
profile.AddPointer(SymbolTag);
125125
}
126126

127127
void Profile(llvm::FoldingSetNodeID& profile) override {
128-
Profile(profile, S, LCtx, T, Count, SymbolTag);
128+
Profile(profile, ElemRef, LCtx, T, Count, SymbolTag);
129129
}
130130

131131
// Implement isa<T> support.
@@ -533,18 +533,12 @@ class SymbolManager {
533533
template <typename SymExprT, typename... Args>
534534
const SymExprT *acquire(Args &&...args);
535535

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-
}
536+
const SymbolConjured *
537+
conjureSymbol(const CFGBlock::ConstCFGElementRef ElemRef,
538+
const LocationContext *LCtx, QualType T, unsigned VisitCount,
539+
const void *SymbolTag = nullptr) {
542540

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);
541+
return acquire<SymbolConjured>(ElemRef, LCtx, T, VisitCount, SymbolTag);
548542
}
549543

550544
QualType getType(const SymExpr *SE) const {

0 commit comments

Comments
 (0)