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