зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
aa4fe05939
Коммит
6a02b609c2
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче