[cfe-commits] r100098 - in /cfe/trunk: include/clang/Checker/PathSensitive/GRExprEngine.h lib/Checker/GRExprEngine.cpp

Zhongxing Xu xuzhongxing at gmail.com
Thu Apr 1 00:58:50 PDT 2010


Author: zhongxingxu
Date: Thu Apr  1 02:58:50 2010
New Revision: 100098

URL: http://llvm.org/viewvc/llvm-project?rev=100098&view=rev
Log:
Initial support for visiting CXXMemberCallExpr.

Modified:
    cfe/trunk/include/clang/Checker/PathSensitive/GRExprEngine.h
    cfe/trunk/lib/Checker/GRExprEngine.cpp

Modified: cfe/trunk/include/clang/Checker/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Checker/PathSensitive/GRExprEngine.h?rev=100098&r1=100097&r2=100098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Checker/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Checker/PathSensitive/GRExprEngine.h Thu Apr  1 02:58:50 2010
@@ -348,6 +348,10 @@
   void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
                              ExplodedNode *Pred,
                              ExplodedNodeSet &Dst);
+
+  void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
+                              ExplodedNodeSet &Dst);
+
   void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
                     ExplodedNodeSet &Dst);
 
@@ -356,7 +360,7 @@
                                 ExplodedNodeSet &Dst);
 
   /// Synthesize CXXThisRegion.
-  const CXXThisRegion *getCXXThisRegion(const CXXConstructExpr *E,
+  const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD,
                                         const StackFrameContext *SFC);
 
   /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic

Modified: cfe/trunk/lib/Checker/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngine.cpp?rev=100098&r1=100097&r2=100098&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngine.cpp Thu Apr  1 02:58:50 2010
@@ -584,7 +584,6 @@
 
   switch (S->getStmtClass()) {
     // C++ stuff we don't support yet.
-    case Stmt::CXXMemberCallExprClass:
     case Stmt::CXXNamedCastExprClass:
     case Stmt::CXXStaticCastExprClass:
     case Stmt::CXXDynamicCastExprClass:
@@ -673,6 +672,12 @@
       break;
     }
 
+    case Stmt::CXXMemberCallExprClass: {
+      CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
+      VisitCXXMemberCallExpr(MCE, Pred, Dst);
+      break;
+    }
+
       // FIXME: ChooseExpr is really a constant.  We need to fix
       //        the CFG do not model them as explicit control-flow.
 
@@ -1342,7 +1347,7 @@
 
   // Bind the constructed object value to CXXConstructExpr.
   if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
-    const CXXThisRegion *ThisR = getCXXThisRegion(CCE, LocCtx);
+    const CXXThisRegion *ThisR = getCXXThisRegion(CCE->getConstructor(),LocCtx);
     // We might not have 'this' region in the binding if we didn't inline
     // the ctor call.
     SVal ThisV = state->getSVal(ThisR);
@@ -3222,7 +3227,7 @@
                                                     Pred->getLocationContext(),
                                    E, Builder->getBlock(), Builder->getIndex());
 
-  const CXXThisRegion *ThisR = getCXXThisRegion(E, SFC);
+  const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
 
   CallEnter Loc(E, CD, Pred->getLocationContext());
   for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
@@ -3236,12 +3241,90 @@
   }
 }
 
-const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXConstructExpr *E,
+void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, 
+                                          ExplodedNode *Pred, 
+                                          ExplodedNodeSet &Dst) {
+  // Get the method type.
+  const FunctionProtoType *FnType = 
+                       MCE->getCallee()->getType()->getAs<FunctionProtoType>();
+  assert(FnType && "Method type not available");
+
+  // Evaluate explicit arguments with a worklist.
+  CallExpr::arg_iterator AB = const_cast<CXXMemberCallExpr*>(MCE)->arg_begin(),
+                         AE = const_cast<CXXMemberCallExpr*>(MCE)->arg_end();
+  llvm::SmallVector<CallExprWLItem, 20> WorkList;
+  WorkList.reserve(AE - AB);
+  WorkList.push_back(CallExprWLItem(AB, Pred));
+  ExplodedNodeSet ArgsEvaluated;
+
+  while (!WorkList.empty()) {
+    CallExprWLItem Item = WorkList.back();
+    WorkList.pop_back();
+
+    if (Item.I == AE) {
+      ArgsEvaluated.insert(Item.N);
+      continue;
+    }
+
+    ExplodedNodeSet Tmp;
+    const unsigned ParamIdx = Item.I - AB;
+    bool VisitAsLvalue = FnType->getArgType(ParamIdx)->isReferenceType();
+
+    if (VisitAsLvalue)
+      VisitLValue(*Item.I, Item.N, Tmp);
+    else
+      Visit(*Item.I, Item.N, Tmp);
+
+    ++(Item.I);
+    for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI != NE; ++NI)
+      WorkList.push_back(CallExprWLItem(Item.I, *NI));
+  }
+  // Evaluate the implicit object argument.
+  ExplodedNodeSet AllArgsEvaluated;
+  const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee()->IgnoreParens());
+  if (!ME)
+    return;
+  Expr *ObjArgExpr = ME->getBase();
+  for (ExplodedNodeSet::iterator I = ArgsEvaluated.begin(), 
+                                 E = ArgsEvaluated.end(); I != E; ++I) {
+    if (ME->isArrow())
+      Visit(ObjArgExpr, *I, AllArgsEvaluated);
+    else
+      VisitLValue(ObjArgExpr, *I, AllArgsEvaluated);
+  }
+
+  const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
+  assert(MD && "not a CXXMethodDecl?");
+
+  if (!MD->isThisDeclarationADefinition())
+    // FIXME: conservative method call evaluation.
+    return;
+
+  const StackFrameContext *SFC = AMgr.getStackFrame(MD, 
+                                                    Pred->getLocationContext(),
+                                                    MCE, 
+                                                    Builder->getBlock(), 
+                                                    Builder->getIndex());
+  const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
+  CallEnter Loc(MCE, MD, Pred->getLocationContext());
+  for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
+         E = AllArgsEvaluated.end(); I != E; ++I) {
+    // Set up 'this' region.
+    const GRState *state = GetState(*I);
+    state = state->bindLoc(loc::MemRegionVal(ThisR),state->getSVal(ObjArgExpr));
+    ExplodedNode *N = Builder->generateNode(Loc, state, *I);
+    if (N)
+      Dst.Add(N);
+  }
+}
+
+const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
                                                  const StackFrameContext *SFC) {
-  Type *T = E->getConstructor()->getParent()->getTypeForDecl();
+  Type *T = D->getParent()->getTypeForDecl();
   QualType PT = getContext().getPointerType(QualType(T,0));
   return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
 }
+
 //===----------------------------------------------------------------------===//
 // Checker registration/lookup.
 //===----------------------------------------------------------------------===//





More information about the cfe-commits mailing list