k-wisniewski created this revision.
k-wisniewski added reviewers: a.sidorin, zaks.anna, NoQ, dcoughlin.
k-wisniewski added subscribers: cfe-commits, NoQ.

Artem Dergachev (@NoQ ) helped me correctly handle C++ method calls in my 
RecursionChecker (that finds infnite recursion) and this is the method that I 
use to obtain SVal of "this" parameter of a method call represented by 
StackFrameCtx.


https://reviews.llvm.org/D26762

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


Index: include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
 
+#include "clang/AST/ExprCXX.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
@@ -298,6 +299,11 @@
   /// that created the given stack frame
   SVal getArgSVal(const StackFrameContext *SFC, const unsigned ArgIdx) const;
 
+  /// Get the symbolic value of the "this" object for a method call
+  /// that created the given stack frame. Returns None if the
+  /// stack frame does not represent a method call.
+  Optional<SVal> getThisSVal(const StackFrameContext *SFC) const;
+
   /// Returns the SVal bound to the statement 'S' in the state's environment.
   SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
   
@@ -751,6 +757,29 @@
   }
 }
 
+inline Optional<SVal>
+ProgramState::getThisSVal(const StackFrameContext *SFC) const {
+  if (SFC->inTopFrame()) {
+    const FunctionDecl *FD = SFC->getDecl()->getAsFunction();
+    if (!FD)
+      return None;
+    const CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(FD->getParent());
+    if (!RD)
+      return None;
+    Loc ThisLoc = getStateManager().getSValBuilder().getCXXThis(RD, SFC);
+    return getSVal(ThisLoc);
+  } else {
+    const Stmt *S = SFC->getCallSite();
+    if (!S)
+      return None;
+    if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(S))
+      return getSVal(MCE->getImplicitObjectArgument(), SFC->getParent());
+    else if (const auto *CCE = dyn_cast<CXXConstructExpr>(S))
+      return getSVal(CCE, SFC->getParent());
+    return None;
+  }
+}
+
 inline SVal ProgramState::getSVal(const Stmt *Ex,
                                   const LocationContext *LCtx) const{
   return Env.getSVal(EnvironmentEntry(Ex, LCtx),


Index: include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
 
+#include "clang/AST/ExprCXX.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
@@ -298,6 +299,11 @@
   /// that created the given stack frame
   SVal getArgSVal(const StackFrameContext *SFC, const unsigned ArgIdx) const;
 
+  /// Get the symbolic value of the "this" object for a method call
+  /// that created the given stack frame. Returns None if the
+  /// stack frame does not represent a method call.
+  Optional<SVal> getThisSVal(const StackFrameContext *SFC) const;
+
   /// Returns the SVal bound to the statement 'S' in the state's environment.
   SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
   
@@ -751,6 +757,29 @@
   }
 }
 
+inline Optional<SVal>
+ProgramState::getThisSVal(const StackFrameContext *SFC) const {
+  if (SFC->inTopFrame()) {
+    const FunctionDecl *FD = SFC->getDecl()->getAsFunction();
+    if (!FD)
+      return None;
+    const CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(FD->getParent());
+    if (!RD)
+      return None;
+    Loc ThisLoc = getStateManager().getSValBuilder().getCXXThis(RD, SFC);
+    return getSVal(ThisLoc);
+  } else {
+    const Stmt *S = SFC->getCallSite();
+    if (!S)
+      return None;
+    if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(S))
+      return getSVal(MCE->getImplicitObjectArgument(), SFC->getParent());
+    else if (const auto *CCE = dyn_cast<CXXConstructExpr>(S))
+      return getSVal(CCE, SFC->getParent());
+    return None;
+  }
+}
+
 inline SVal ProgramState::getSVal(const Stmt *Ex,
                                   const LocationContext *LCtx) const{
   return Env.getSVal(EnvironmentEntry(Ex, LCtx),
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to