[PATCH] D27091: Add the way to extract SVals of arguments used in a call for a given StackFrameCtx

2016-12-09 Thread Anna Zaks via Phabricator via cfe-commits
zaks.anna added a comment.

Update: Adding support for top frame to the CallEvent is difficult, so let's 
just use CallEvent API in the checkers for all frames but the top one and have 
custom top frame handling in the Recursion checker itself. The top frame 
handling does not need to be complete (handle all call types) since in the 
worst case we will be missing bugs (no false positives due to this).


https://reviews.llvm.org/D27091



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27091: Add the way to extract SVals of arguments used in a call for a given StackFrameCtx

2016-12-01 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

Chatted about this a bit more. Because `CallEvent` is an API designed mostly 
for convenience, and `ProgramState` is a core API that needs to stay as clean 
and separate from other entities and easy to understand as possible, it would 
be the best to

1. construct a `CallEvent` in the checker (which is cheap) and query that,
2. and also allow constructing `CallEvent`s for the top frame (with 
`StackFrameContext::inTopFrame()`, with null call site ("origin") expression), 
and
3. add a branch to the `CallEvent::getArgSVal()` method (and similar methods 
for obtaining implicit arguments like C++ `this`, ObjC `self`, ObjC `super`) to 
handle the top frame case.

If this sounds hard, handling this completely on the checker side is fine, 
because few checker are using this at the moment.


https://reviews.llvm.org/D27091



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27091: Add the way to extract SVals of arguments used in a call for a given StackFrameCtx

2016-11-30 Thread Anna Zaks via Phabricator via cfe-commits
zaks.anna added a comment.

Artem just pointed out that I have "Smalls" instead of "SVals" in my first 
comment.


https://reviews.llvm.org/D27091



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27091: Add the way to extract SVals of arguments used in a call for a given StackFrameCtx

2016-11-30 Thread Anna Zaks via Phabricator via cfe-commits
zaks.anna added a comment.

> Hmm, i'm thinking of just the opposite - refactor the CallEvent methods to 
> use the respective new  ProgramState methods.
> 
> This way we'd avoid touching the CallEvent allocator for a simple Environment 
> lookup, while still avoiding code duplication.

I see what you are suggesting, but I still have the concerns I've mentioned in 
my first comment. **The whole purpose of CallEvent is to allow an easy and 
lightweight way of dealing with all the different types of calls**, which is 
exactly what we are doing in this checker. CallEvent is used for this exact 
purpose elsewhere throughout the analyzer. What do you mean by "touching  the 
CallEvent allocator" and why would you want to discourage that?

CallEventManager::getCaller contains logic to dispatch to different CallEvent 
types depending on what call we are dealing with. The argument lookup will 
depend on type of the call. The method added in this PR does not deal with all 
call types, but only with CallExpr, so you'd need to duplicate the code from 
CallEvent construction to here.

As I've mentioned before, I do not think that Call dispatch logic and API for 
looking up arguments SVals should belong to ProgramState as it is a higher 
abstraction and should not reason about LocationContexts or Calls (which are 
part of Program Location and AST respectively). In addition, using CallEven to 
look up argument values is much simpler to understand for API users.


https://reviews.llvm.org/D27091



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27091: Add the way to extract SVals of arguments used in a call for a given StackFrameCtx

2016-11-30 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

Hmm, i'm thinking of just the opposite - refactor the CallEvent methods to use 
the respective new ProgramState methods.

This way we'd avoid touching the CallEvent allocator for a simple Environment 
lookup, while still avoiding code duplication.


https://reviews.llvm.org/D27091



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27091: Add the way to extract SVals of arguments used in a call for a given StackFrameCtx

2016-11-29 Thread Anna Zaks via Phabricator via cfe-commits
zaks.anna added a comment.

Hi!

Looks like this this is used by the Infinite recursion checker. Specifically, 
the checker not only needs to get Smalls for arguments of the current 
CallEvent, but it also looks for arguments of other calls on the stack. The 
checker walks the LocationContext and uses this new API to look up the 
arguments passed to the calls on the stack.

The two concerns I have with this patch is that it is extending the overloaded 
ProgramState API and also that this does not fully cover all the call types we 
have in C/ObjC/C++. The good news is that the CallEvent API was created 
specifically to encapsulate this complexity and it already contains the needed 
API to look up the SVal of the argument. Have you considered creating CallEvent 
for the calls on the stack and using that existing API to find the Smalls of 
the arguments.

Here is some documentation from CallEvent.h:
`
 /// CallEvents are created through the factory methods of CallEventManager.
 ///
 /// CallEvents should always be cheap to create and destroy. In order for
 /// CallEventManager to be able to re-use CallEvent-sized memory blocks,
 /// subclasses of CallEvent may not add any data members to the base class.
 /// Use the "Data" and "Location" fields instead.

`

It looks like this code from BugReporterVisitors.cpp is doing something similar:

  ` // Don't automatically suppress a report if one of the arguments is
   // known to be a null pointer. Instead, start tracking /that/ null
   // value back to its origin.
   ProgramStateManager  = BRC.getStateManager();
   CallEventManager  = StateMgr.getCallEventManager();
  
   ProgramStateRef State = N->getState();
   CallEventRef<> Call = CallMgr.getCaller(StackFrame, State);
   for (unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
 Optional ArgV = Call->getArgSVal(I).getAs();
 if (!ArgV)
   continue;

`

 

I hope this approach works and you could just add that code to your checker. 
(If not, we can investigate other options.)


https://reviews.llvm.org/D27091



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D27091: Add the way to extract SVals of arguments used in a call for a given StackFrameCtx

2016-11-24 Thread Krzysztof Wiśniewski via cfe-commits
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(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  = 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(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(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  = 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