diff options
author | Marcin Swiderski <marcin.sfider@gmail.com> | 2010-11-18 06:29:23 +0000 |
---|---|---|
committer | Marcin Swiderski <marcin.sfider@gmail.com> | 2010-11-18 06:29:23 +0000 |
commit | 6a02b609c2e23b28d24f9db4c8006137c6b55ae4 (patch) | |
tree | dbe6a4ecd7355f2fffc6b03b88a487cda4833943 | |
parent | aa4fe05939ffbfd746b8f0065cc0b5e06ea94fe2 (diff) |
Added method for handling CXXOperatorCallExpr differently from CallExpr if CXXOperatorCallExpr represents method call.
Also fixed returning ExpolodedNodeSet from VisitCXXMethodCallExpr.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119684 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Checker/PathSensitive/GRExprEngine.h | 9 | ||||
-rw-r--r-- | lib/Checker/GRCXXExprEngine.cpp | 43 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 9 |
3 files changed, 52 insertions, 9 deletions
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 998eceffc3..d49fd85e6f 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -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. diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp index 4c996bb22e..642c26e240 100644 --- a/lib/Checker/GRCXXExprEngine.cpp +++ b/lib/Checker/GRCXXExprEngine.cpp @@ -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)); } } diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 2dcb354f00..ddd3d50fe5 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -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); |