Added method for handling CXXOperatorCallExpr differently from CallExpr if CXXOperato...
authorMarcin Swiderski <marcin.sfider@gmail.com>
Thu, 18 Nov 2010 06:29:23 +0000 (06:29 +0000)
committerMarcin Swiderski <marcin.sfider@gmail.com>
Thu, 18 Nov 2010 06:29:23 +0000 (06:29 +0000)
Also fixed returning ExpolodedNodeSet from VisitCXXMethodCallExpr.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119684 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Checker/PathSensitive/GRExprEngine.h
lib/Checker/GRCXXExprEngine.cpp
lib/Checker/GRExprEngine.cpp

index 998eceffc3f8d7e583007b1bc3205aa69050342e..d49fd85e6f952abf0556a99c4b739b660cda66bd 100644 (file)
@@ -431,6 +431,9 @@ public:
   void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
                               ExplodedNodeSet &Dst);
 
+  void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
+                                ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
   void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
                        ExplodedNodeSet &Dst);
 
@@ -454,6 +457,12 @@ public:
                      ExplodedNode *Pred, ExplodedNodeSet &Dst,
                      bool FstArgAsLValue = false);
 
+  /// Evaluate method call itself. Used for CXXMethodCallExpr and
+  /// CXXOperatorCallExpr.
+  void EvalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
+                      const Expr *ThisExpr, ExplodedNode *Pred,
+                      ExplodedNodeSet &Src, ExplodedNodeSet &Dst);
+
   /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
   ///  expressions of the form 'x != 0' and generate new nodes (stored in Dst)
   ///  with those assumptions.
index 4c996bb22ee53bf5f02ee1f46a57c9a91d08e177..642c26e2408c07d7e41bca847a39c4573dcdb5e1 100644 (file)
@@ -169,13 +169,43 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
       VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
   }
 
-  // Allow checkers to pre-visit the member call.
-  ExplodedNodeSet PreVisitChecks;
-  CheckerVisit(MCE, PreVisitChecks, AllArgsEvaluated, PreVisitStmtCallback);
-
   // Now evaluate the call itself.
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
   assert(MD && "not a CXXMethodDecl?");
+  EvalMethodCall(MCE, MD, ObjArgExpr, Pred, AllArgsEvaluated, Dst);
+}
+
+void GRExprEngine::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C,
+                                            ExplodedNode *Pred,
+                                            ExplodedNodeSet &Dst) {
+  const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(C->getCalleeDecl());
+  if (!MD) {
+    // If the operator doesn't represent a method call treat as regural call.
+    VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
+    return;
+  }
+
+  // Determine the type of function we're calling (if available).
+  const FunctionProtoType *Proto = NULL;
+  QualType FnType = C->getCallee()->IgnoreParens()->getType();
+  if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
+    Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
+
+  // Evaluate arguments treating the first one (object method is called on)
+  // as alvalue.
+  ExplodedNodeSet ArgsEvaluated;
+  EvalArguments(C->arg_begin(), C->arg_end(), Proto, Pred, ArgsEvaluated, true);
+
+  // Now evaluate the call itself.
+  EvalMethodCall(C, MD, C->getArg(0), Pred, ArgsEvaluated, Dst);
+}
+
+void GRExprEngine::EvalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
+                                  const Expr *ThisExpr, ExplodedNode *Pred,
+                                  ExplodedNodeSet &Src, ExplodedNodeSet &Dst) {
+  // Allow checkers to pre-visit the member call.
+  ExplodedNodeSet PreVisitChecks;
+  CheckerVisit(MCE, PreVisitChecks, Src, PreVisitStmtCallback);
 
   if (!(MD->isThisDeclarationADefinition() && AMgr.shouldInlineCall())) {
     // FIXME: conservative method call evaluation.
@@ -183,7 +213,6 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
     return;
   }
 
-  ExplodedNodeSet SetupThis;
   const StackFrameContext *SFC = AMgr.getStackFrame(MD, 
                                                     Pred->getLocationContext(),
                                                     MCE, 
@@ -195,8 +224,8 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
          E = PreVisitChecks.end(); I != E; ++I) {
     // Set up 'this' region.
     const GRState *state = GetState(*I);
-    state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
-    SetupThis.Add(Builder->generateNode(Loc, state, *I));
+    state = state->bindLoc(loc::MemRegionVal(ThisR), state->getSVal(ThisExpr));
+    Dst.Add(Builder->generateNode(Loc, state, *I));
   }
 }
 
index 2dcb354f00ba287af07c31c92d3b470fee648768..ddd3d50fe56bbc9e8b9af5c65a063cf913e203fc 100644 (file)
@@ -895,8 +895,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
       break;
     }
 
-    case Stmt::CallExprClass:
-    case Stmt::CXXOperatorCallExprClass: {
+    case Stmt::CallExprClass: {
       const CallExpr* C = cast<CallExpr>(S);
       VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
       break;
@@ -916,6 +915,12 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
       break;
     }
 
+    case Stmt::CXXOperatorCallExprClass: {
+      const CXXOperatorCallExpr *C = cast<CXXOperatorCallExpr>(S);
+      VisitCXXOperatorCallExpr(C, Pred, Dst);
+      break;
+    }
+
     case Stmt::CXXNewExprClass: {
       const CXXNewExpr *NE = cast<CXXNewExpr>(S);
       VisitCXXNewExpr(NE, Pred, Dst);