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

his patch adds getArgsSVal method to ProgramState that allows the user to 
obtain SVals of argumetns used in a call that created the given StackFrameCtx. 
The problem with arguments SVals being overwritten has been fixed according to 
@NoQ 's suggestion from the previous revision of this patch 
(https://reviews.llvm.org/D26760)


https://reviews.llvm.org/D27091

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
@@ -294,6 +294,10 @@
   /// Get the lvalue for an array index.
   SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
 
+  /// Get the symbolic value of arguments used in a call
+  /// that created the given stack frame
+  SVal getArgSVal(const StackFrameContext *SFC, const unsigned ArgIdx) const;
+
   /// Returns the SVal bound to the statement 'S' in the state's environment.
   SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
   
@@ -725,6 +729,36 @@
   return UnknownVal();
 }
 
+inline SVal ProgramState::getArgSVal(const StackFrameContext *SFC,
+                                     const unsigned ArgIdx) const {
+  const FunctionDecl *FunctionDecl = SFC->getDecl()->getAsFunction();
+  const ObjCMethodDecl *MethodDecl =
+      dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
+  unsigned NumArgs = FunctionDecl
+                     ? FunctionDecl->getNumParams()
+                     : MethodDecl->getSelector().getNumArgs();
+  assert(ArgIdx < NumArgs && "Arg access out of range!");
+
+  if (SFC->inTopFrame()) {
+    // if we are in the top frame we don't have any arguments bound in
+    // the environment because the call wasn't modeled in the first place.
+    const VarDecl *ArgDecl = FunctionDecl
+                             ? FunctionDecl->parameters()[ArgIdx]
+                             : MethodDecl->parameters()[ArgIdx];
+    const Loc ArgLoc = getLValue(ArgDecl, SFC);
+    StoreManager &storeMgr = stateMgr->getStoreManager();
+    Store initialStore = storeMgr.getInitialStore(SFC).getStore();
+    return storeMgr.getBinding(initialStore, ArgLoc);
+  } else {
+    // in this case we need to ask the environment as  the arguments' memory
+    // region may have been purged as no longer needed.
+    const Stmt *callSite = SFC->getCallSite();
+    const CallExpr *callSiteExpr = dyn_cast<CallExpr>(callSite);
+    const Expr *argExpr = callSiteExpr->getArg(ArgIdx);
+    return getSVal(argExpr, SFC->getParent());
+  }
+}
+
 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
@@ -294,6 +294,10 @@
   /// Get the lvalue for an array index.
   SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
 
+  /// Get the symbolic value of arguments used in a call
+  /// that created the given stack frame
+  SVal getArgSVal(const StackFrameContext *SFC, const unsigned ArgIdx) const;
+
   /// Returns the SVal bound to the statement 'S' in the state's environment.
   SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
   
@@ -725,6 +729,36 @@
   return UnknownVal();
 }
 
+inline SVal ProgramState::getArgSVal(const StackFrameContext *SFC,
+                                     const unsigned ArgIdx) const {
+  const FunctionDecl *FunctionDecl = SFC->getDecl()->getAsFunction();
+  const ObjCMethodDecl *MethodDecl =
+      dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
+  unsigned NumArgs = FunctionDecl
+                     ? FunctionDecl->getNumParams()
+                     : MethodDecl->getSelector().getNumArgs();
+  assert(ArgIdx < NumArgs && "Arg access out of range!");
+
+  if (SFC->inTopFrame()) {
+    // if we are in the top frame we don't have any arguments bound in
+    // the environment because the call wasn't modeled in the first place.
+    const VarDecl *ArgDecl = FunctionDecl
+                             ? FunctionDecl->parameters()[ArgIdx]
+                             : MethodDecl->parameters()[ArgIdx];
+    const Loc ArgLoc = getLValue(ArgDecl, SFC);
+    StoreManager &storeMgr = stateMgr->getStoreManager();
+    Store initialStore = storeMgr.getInitialStore(SFC).getStore();
+    return storeMgr.getBinding(initialStore, ArgLoc);
+  } else {
+    // in this case we need to ask the environment as  the arguments' memory
+    // region may have been purged as no longer needed.
+    const Stmt *callSite = SFC->getCallSite();
+    const CallExpr *callSiteExpr = dyn_cast<CallExpr>(callSite);
+    const Expr *argExpr = callSiteExpr->getArg(ArgIdx);
+    return getSVal(argExpr, SFC->getParent());
+  }
+}
+
 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