From: Zhongxing Xu Date: Tue, 16 Mar 2010 13:14:16 +0000 (+0000) Subject: Add VisitCXXContructExpr logic to the analyzer. This still has not fully worked X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c506357c3778092c2a3251243f12524e8eb89274;p=clang Add VisitCXXContructExpr logic to the analyzer. This still has not fully worked since RemoveDeadBinding mistakenly remove the binding to CXXThisRegion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98629 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 763bbcc9e1..916511e8bd 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -347,7 +347,10 @@ protected: void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet & Dst); - + + void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest, + ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// Create a C++ temporary object for an rvalue. void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst); diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 130d805bb8..e64ba9446d 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -19,6 +19,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/ParentMap.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/DeclCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManager.h" @@ -2335,7 +2336,11 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet Tmp; if (InitEx) { - if (VD->getType()->isReferenceType()) + if (const CXXConstructExpr *E = dyn_cast(InitEx)) { + VisitCXXConstructExpr(E, GetState(Pred)->getLValue(VD, + Pred->getLocationContext()), Pred, Dst); + return; + } else if (VD->getType()->isReferenceType()) VisitLValue(InitEx, Pred, Tmp); else Visit(InitEx, Pred, Tmp); @@ -2826,7 +2831,8 @@ void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet & Dst) { // Get the this object region from StoreManager. const MemRegion *R = - ValMgr.getRegionManager().getCXXThisRegion(TE->getType(), + ValMgr.getRegionManager().getCXXThisRegion( + getContext().getCanonicalType(TE->getType()), Pred->getLocationContext()); const GRState *state = GetState(Pred); @@ -3126,6 +3132,78 @@ void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred, } } +void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest, + ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + + const CXXConstructorDecl *CD = E->getConstructor(); + assert(CD); + + if (!CD->isThisDeclarationADefinition()) + // FIXME: invalidate the object. + return; + + + // Evaluate other arguments. + CXXConstructExpr::arg_iterator AB + = const_cast(E)->arg_begin(); + CXXConstructExpr::arg_iterator AE + = const_cast(E)->arg_end(); + llvm::SmallVector WorkList; + WorkList.reserve(AE - AB); + WorkList.push_back(CallExprWLItem(AB, Pred)); + ExplodedNodeSet ArgsEvaluated; + const FunctionProtoType *Proto = CD->getType()->getAs(); + + while (!WorkList.empty()) { + CallExprWLItem Item = WorkList.back(); + WorkList.pop_back(); + + if (Item.I == AE) { + ArgsEvaluated.insert(Item.N); + continue; + } + + // Evaluate the argument. + ExplodedNodeSet Tmp; + const unsigned ParamIdx = Item.I - AB; + + bool VisitAsLvalue = false; + + if (ParamIdx < Proto->getNumArgs()) + VisitAsLvalue = Proto->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)); + } + // The callee stack frame context used to create the 'this' parameter region. + const StackFrameContext *SFC = AMgr.getStackFrame(CD, + Pred->getLocationContext(), + E, Builder->getBlock(), Builder->getIndex()); + + Type *T = CD->getParent()->getTypeForDecl(); + QualType PT = getContext().getPointerType(QualType(T,0)); + const CXXThisRegion *ThisR = ValMgr.getRegionManager().getCXXThisRegion(PT, + SFC); + + CallEnter Loc(E, CD, Pred->getLocationContext()); + for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(), + NE = ArgsEvaluated.end(); NI != NE; ++NI) { + const GRState *state = GetState(*NI); + // Setup 'this' region. + state = state->bindLoc(loc::MemRegionVal(ThisR), Dest); + ExplodedNode *N = Builder->generateNode(Loc, state, Pred); + if (N) + Dst.Add(N); + } +} //===----------------------------------------------------------------------===// // Checker registration/lookup. //===----------------------------------------------------------------------===// diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index b53fdee138..307ef78803 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -22,6 +22,8 @@ #include "clang/Analysis/Support/Optional.h" #include "clang/Basic/TargetInfo.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/ImmutableList.h" @@ -1841,18 +1843,29 @@ Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc, GRState const *RegionStoreManager::EnterStackFrame(GRState const *state, StackFrameContext const *frame) { FunctionDecl const *FD = cast(frame->getDecl()); - CallExpr const *CE = cast(frame->getCallSite()); - FunctionDecl::param_const_iterator PI = FD->param_begin(); + Store store = state->getStore(); - CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); + if (CallExpr const *CE = dyn_cast(frame->getCallSite())) { + CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); - // Copy the arg expression value to the arg variables. - Store store = state->getStore(); - for (; AI != AE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI); - store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI, frame)), ArgVal); - } + // Copy the arg expression value to the arg variables. + for (; AI != AE; ++AI, ++PI) { + SVal ArgVal = state->getSVal(*AI); + store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal); + } + } else if (const CXXConstructExpr *CE = + dyn_cast(frame->getCallSite())) { + CXXConstructExpr::const_arg_iterator AI = CE->arg_begin(), + AE = CE->arg_end(); + + // Copy the arg expression value to the arg variables. + for (; AI != AE; ++AI, ++PI) { + SVal ArgVal = state->getSVal(*AI); + store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal); + } + } else + assert(0 && "Unhandled call expression."); return state->makeWithStore(store); }