r367608 - [analyzer] StackFrameContext: Add NodeBuilderContext::blockCount() to its profile
Csaba Dabis via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 1 13:41:13 PDT 2019
Author: charusso
Date: Thu Aug 1 13:41:13 2019
New Revision: 367608
URL: http://llvm.org/viewvc/llvm-project?rev=367608&view=rev
Log:
[analyzer] StackFrameContext: Add NodeBuilderContext::blockCount() to its profile
Summary:
It allows discriminating between stack frames of the same call that is
called multiple times in a loop.
Thanks to Artem Dergachev for the great idea!
Reviewed By: NoQ
Tags: #clang
Differential Revision: https://reviews.llvm.org/D65587
Added:
cfe/trunk/test/Analysis/stack-frame-context-revision.cpp
Modified:
cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
cfe/trunk/test/Analysis/loop-block-counts.c
cfe/trunk/test/Analysis/loop-unrolling.cpp
Modified: cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h (original)
+++ cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h Thu Aug 1 13:41:13 2019
@@ -183,9 +183,8 @@ public:
const ImplicitParamDecl *getSelfDecl() const;
const StackFrameContext *getStackFrame(LocationContext const *Parent,
- const Stmt *S,
- const CFGBlock *Blk,
- unsigned Idx);
+ const Stmt *S, const CFGBlock *Blk,
+ unsigned BlockCount, unsigned Idx);
const BlockInvocationContext *
getBlockInvocationContext(const LocationContext *parent,
@@ -303,15 +302,19 @@ class StackFrameContext : public Locatio
// The parent block of the callsite.
const CFGBlock *Block;
+ // The number of times the 'Block' has been visited.
+ // It allows discriminating between stack frames of the same call that is
+ // called multiple times in a loop.
+ const unsigned BlockCount;
+
// The index of the callsite in the CFGBlock.
- unsigned Index;
+ const unsigned Index;
StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
- const Stmt *s, const CFGBlock *blk,
- unsigned idx,
- int64_t ID)
- : LocationContext(StackFrame, ctx, parent, ID), CallSite(s),
- Block(blk), Index(idx) {}
+ const Stmt *s, const CFGBlock *blk, unsigned blockCount,
+ unsigned idx, int64_t ID)
+ : LocationContext(StackFrame, ctx, parent, ID), CallSite(s), Block(blk),
+ BlockCount(blockCount), Index(idx) {}
public:
~StackFrameContext() override = default;
@@ -329,9 +332,10 @@ public:
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const Stmt *s,
- const CFGBlock *blk, unsigned idx) {
+ const CFGBlock *blk, unsigned blockCount, unsigned idx) {
ProfileCommon(ID, StackFrame, ctx, parent, s);
ID.AddPointer(blk);
+ ID.AddInteger(blockCount);
ID.AddInteger(idx);
}
@@ -410,8 +414,8 @@ public:
const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
const LocationContext *parent,
- const Stmt *s,
- const CFGBlock *blk, unsigned idx);
+ const Stmt *s, const CFGBlock *blk,
+ unsigned blockCount, unsigned idx);
const ScopeContext *getScope(AnalysisDeclContext *ctx,
const LocationContext *parent,
@@ -483,26 +487,25 @@ public:
bool synthesizeBodies() const { return SynthesizeBodies; }
const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
- LocationContext const *Parent,
- const Stmt *S,
- const CFGBlock *Blk,
- unsigned Idx) {
- return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
+ const LocationContext *Parent,
+ const Stmt *S, const CFGBlock *Blk,
+ unsigned BlockCount, unsigned Idx) {
+ return LocContexts.getStackFrame(Ctx, Parent, S, Blk, BlockCount, Idx);
}
// Get the top level stack frame.
const StackFrameContext *getStackFrame(const Decl *D) {
return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
- 0);
+ 0, 0);
}
// Get a stack frame with parent.
StackFrameContext const *getStackFrame(const Decl *D,
- LocationContext const *Parent,
- const Stmt *S,
- const CFGBlock *Blk,
- unsigned Idx) {
- return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
+ const LocationContext *Parent,
+ const Stmt *S, const CFGBlock *Blk,
+ unsigned BlockCount, unsigned Idx) {
+ return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, BlockCount,
+ Idx);
}
/// Get a reference to {@code BodyFarm} instance.
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h Thu Aug 1 13:41:13 2019
@@ -386,11 +386,12 @@ public:
/// during analysis if the call is inlined, but it may still be useful
/// in intermediate calculations even if the call isn't inlined.
/// May fail; returns null on failure.
- const StackFrameContext *getCalleeStackFrame() const;
+ const StackFrameContext *getCalleeStackFrame(unsigned BlockCount) const;
/// Returns memory location for a parameter variable within the callee stack
/// frame. May fail; returns null on failure.
- const VarRegion *getParameterLocation(unsigned Index) const;
+ const VarRegion *getParameterLocation(unsigned Index,
+ unsigned BlockCount) const;
/// Returns true if on the current path, the argument was constructed by
/// calling a C++ constructor over it. This is an internal detail of the
Modified: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp (original)
+++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp Thu Aug 1 13:41:13 2019
@@ -310,8 +310,10 @@ BodyFarm &AnalysisDeclContextManager::ge
const StackFrameContext *
AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S,
- const CFGBlock *Blk, unsigned Idx) {
- return getLocationContextManager().getStackFrame(this, Parent, S, Blk, Idx);
+ const CFGBlock *Blk, unsigned BlockCount,
+ unsigned Idx) {
+ return getLocationContextManager().getStackFrame(this, Parent, S, Blk,
+ BlockCount, Idx);
}
const BlockInvocationContext *
@@ -359,7 +361,8 @@ void LocationContext::ProfileCommon(llvm
}
void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, Index);
+ Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block,
+ BlockCount, Index);
}
void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
@@ -392,18 +395,16 @@ LocationContextManager::getLocationConte
return L;
}
-const StackFrameContext*
-LocationContextManager::getStackFrame(AnalysisDeclContext *ctx,
- const LocationContext *parent,
- const Stmt *s,
- const CFGBlock *blk, unsigned idx) {
+const StackFrameContext *LocationContextManager::getStackFrame(
+ AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
+ const CFGBlock *blk, unsigned blockCount, unsigned idx) {
llvm::FoldingSetNodeID ID;
- StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
+ StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
void *InsertPos;
auto *L =
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
- L = new StackFrameContext(ctx, parent, s, blk, idx, ++NewID);
+ L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
Contexts.InsertNode(L, InsertPos);
}
return L;
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Thu Aug 1 13:41:13 2019
@@ -191,7 +191,8 @@ AnalysisDeclContext *CallEvent::getCalle
return ADC;
}
-const StackFrameContext *CallEvent::getCalleeStackFrame() const {
+const StackFrameContext *
+CallEvent::getCalleeStackFrame(unsigned BlockCount) const {
AnalysisDeclContext *ADC = getCalleeAnalysisDeclContext();
if (!ADC)
return nullptr;
@@ -217,11 +218,12 @@ const StackFrameContext *CallEvent::getC
break;
assert(Idx < Sz);
- return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, Idx);
+ return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, BlockCount, Idx);
}
-const VarRegion *CallEvent::getParameterLocation(unsigned Index) const {
- const StackFrameContext *SFC = getCalleeStackFrame();
+const VarRegion *CallEvent::getParameterLocation(unsigned Index,
+ unsigned BlockCount) const {
+ const StackFrameContext *SFC = getCalleeStackFrame(BlockCount);
// We cannot construct a VarRegion without a stack frame.
if (!SFC)
return nullptr;
@@ -322,7 +324,7 @@ ProgramStateRef CallEvent::invalidateReg
if (getKind() != CE_CXXAllocator)
if (isArgumentConstructedDirectly(Idx))
if (auto AdjIdx = getAdjustedParameterIndex(Idx))
- if (const VarRegion *VR = getParameterLocation(*AdjIdx))
+ if (const VarRegion *VR = getParameterLocation(*AdjIdx, BlockCount))
ValuesToInvalidate.push_back(loc::MemRegionVal(VR));
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Thu Aug 1 13:41:13 2019
@@ -323,7 +323,8 @@ std::pair<ProgramStateRef, SVal> ExprEng
CallEventManager &CEMgr = getStateManager().getCallEventManager();
SVal V = UnknownVal();
auto getArgLoc = [&](CallEventRef<> Caller) -> Optional<SVal> {
- const LocationContext *FutureSFC = Caller->getCalleeStackFrame();
+ const LocationContext *FutureSFC =
+ Caller->getCalleeStackFrame(currBldrCtx->blockCount());
// Return early if we are unable to reliably foresee
// the future stack frame.
if (!FutureSFC)
@@ -342,7 +343,7 @@ std::pair<ProgramStateRef, SVal> ExprEng
// because this-argument is implemented as a normal argument in
// operator call expressions but not in operator declarations.
const VarRegion *VR = Caller->getParameterLocation(
- *Caller->getAdjustedParameterIndex(Idx));
+ *Caller->getAdjustedParameterIndex(Idx), currBldrCtx->blockCount());
if (!VR)
return None;
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Thu Aug 1 13:41:13 2019
@@ -451,9 +451,8 @@ bool ExprEngine::inlineCall(const CallEv
// Construct a new stack frame for the callee.
AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
const StackFrameContext *CalleeSFC =
- CalleeADC->getStackFrame(ParentOfCallee, CallE,
- currBldrCtx->getBlock(),
- currStmtIdx);
+ CalleeADC->getStackFrame(ParentOfCallee, CallE, currBldrCtx->getBlock(),
+ currBldrCtx->blockCount(), currStmtIdx);
CallEnter Loc(CallE, CalleeSFC, CurLC);
Modified: cfe/trunk/test/Analysis/loop-block-counts.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/loop-block-counts.c?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/loop-block-counts.c (original)
+++ cfe/trunk/test/Analysis/loop-block-counts.c Thu Aug 1 13:41:13 2019
@@ -12,7 +12,7 @@ void loop() {
for (int i = 0; i < 2; ++i)
callee(&arr[i]);
// FIXME: Should be UNKNOWN.
- clang_analyzer_eval(arr[0] == arr[1]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(arr[0] == arr[1]); // expected-warning{{FALSE}}
}
void loopWithCall() {
Modified: cfe/trunk/test/Analysis/loop-unrolling.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/loop-unrolling.cpp?rev=367608&r1=367607&r2=367608&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/loop-unrolling.cpp (original)
+++ cfe/trunk/test/Analysis/loop-unrolling.cpp Thu Aug 1 13:41:13 2019
@@ -347,9 +347,9 @@ int simple_known_bound_loop() {
int simple_unknown_bound_loop() {
for (int i = 2; i < getNum(); i++) {
#ifdef DFS
- clang_analyzer_numTimesReached(); // expected-warning {{10}}
+ clang_analyzer_numTimesReached(); // expected-warning {{16}}
#else
- clang_analyzer_numTimesReached(); // expected-warning {{13}}
+ clang_analyzer_numTimesReached(); // expected-warning {{8}}
#endif
}
return 0;
@@ -368,10 +368,10 @@ int nested_inlined_unroll1() {
int nested_inlined_no_unroll1() {
int k;
for (int i = 0; i < 9; i++) {
-#ifdef ANALYZER_CM_Z3
- clang_analyzer_numTimesReached(); // expected-warning {{13}}
+#ifdef DFS
+ clang_analyzer_numTimesReached(); // expected-warning {{18}}
#else
- clang_analyzer_numTimesReached(); // expected-warning {{15}}
+ clang_analyzer_numTimesReached(); // expected-warning {{14}}
#endif
k = simple_unknown_bound_loop(); // reevaluation without inlining, splits the state as well
}
Added: cfe/trunk/test/Analysis/stack-frame-context-revision.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stack-frame-context-revision.cpp?rev=367608&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/stack-frame-context-revision.cpp (added)
+++ cfe/trunk/test/Analysis/stack-frame-context-revision.cpp Thu Aug 1 13:41:13 2019
@@ -0,0 +1,37 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -verify %s
+
+// expected-no-diagnostics:
+// From now the profile of the 'StackFrameContext' also contains the
+// 'NodeBuilderContext::blockCount()'. With this addition we can distinguish
+// between the 'StackArgumentsSpaceRegion' of the 'P' arguments being different
+// on every iteration.
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+template <typename PointerTy>
+struct SmarterPointer {
+ PointerTy getFromVoidPointer(void *P) const {
+ return static_cast<PointerTy>(P);
+ }
+
+ PointerTy getPointer() const {
+ return getFromVoidPointer(reinterpret_cast<void *>(Value));
+ }
+
+ intptr_t Value = 13;
+};
+
+struct Node {
+ SmarterPointer<Node *> Pred;
+};
+
+void test(Node *N) {
+ while (N) {
+ SmarterPointer<Node *> Next = N->Pred;
+ delete N;
+
+ N = Next.getPointer();
+ // no-warning: 'Use of memory after it is freed' was here as the same
+ // 'StackArgumentsSpaceRegion' purged out twice as 'P'.
+ }
+}
More information about the cfe-commits
mailing list