diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index 518c8a0b60e5cffcb7e022884886a7a6b716a0a7..da95a1cf4c1dcb1f1b418e2d90734937b8202670 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -25,6 +25,7 @@ #include "clang/Analysis/PathSensitive/BugReporter.h" #include "clang/AST/Type.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprCXX.h" namespace clang { @@ -203,9 +204,10 @@ protected: } public: - ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, const GRState* St, - ProgramPoint::Kind K = ProgramPoint::PostStmtKind, - const void *tag = 0); + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, + const GRState* St, + ProgramPoint::Kind K = ProgramPoint::PostStmtKind, + const void *tag = 0); protected: /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. @@ -315,18 +317,21 @@ protected: void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); - void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, ExplodedNode* Pred, + void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, + ExplodedNode* Pred, ExplodedNodeSet& Dst, SVal ElementV); /// VisitObjCMessageExpr - Transfer function for ObjC message expressions. - void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, + ExplodedNodeSet& Dst); void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME, ObjCMessageExpr::arg_iterator I, ObjCMessageExpr::arg_iterator E, ExplodedNode* Pred, ExplodedNodeSet& Dst); - void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, ExplodedNode* Pred, + void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, + ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitReturnStmt - Transfer function logic for return statements. @@ -337,8 +342,11 @@ protected: ExplodedNodeSet& Dst); /// VisitUnaryOperator - Transfer function logic for unary operators. - void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst, - bool asLValue); + void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, + ExplodedNodeSet & Dst); /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) @@ -362,7 +370,7 @@ public: SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op, NonLoc L, SVal R, QualType T) { - return R.isValid() ? SVator.EvalBinOpNN(state, op, L, cast(R), T) : R; + return R.isValid() ? SVator.EvalBinOpNN(state,op,L, cast(R), T) : R; } SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, diff --git a/clang/include/clang/Analysis/PathSensitive/MemRegion.h b/clang/include/clang/Analysis/PathSensitive/MemRegion.h index 2fe5ea0cf3abd9704791eed62678fe52ae32a610..f0ae39498ec8999a95df79b233263299f72dc912 100644 --- a/clang/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/clang/include/clang/Analysis/PathSensitive/MemRegion.h @@ -73,7 +73,8 @@ public: FieldRegionKind, ObjCIvarRegionKind, ObjCObjectRegionKind, - END_DECL_REGIONS = ObjCObjectRegionKind, + CXXObjectRegionKind, + END_DECL_REGIONS = CXXObjectRegionKind, END_TYPED_REGIONS = END_DECL_REGIONS }; @@ -752,6 +753,30 @@ public: } }; +class CXXObjectRegion : public TypedRegion { + friend class MemRegionManager; + + // T - The object type. + QualType T; + + CXXObjectRegion(QualType t, const MemRegion *sReg) + : TypedRegion(sReg, CXXObjectRegionKind), T(t) {} + + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + QualType T, const MemRegion *sReg); + +public: + QualType getValueType(ASTContext& C) const { + return T; + } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == CXXObjectRegionKind; + } +}; + template const RegionTy* MemRegion::getAs() const { if (const RegionTy* RT = dyn_cast(this)) @@ -877,6 +902,8 @@ public: const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* superRegion); + const CXXObjectRegion *getCXXObjectRegion(QualType T); + const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, diff --git a/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index 648710f7ad12fbbbea10f544486b21e3ad033348..fcc1cd306b614b1417c2ac164b13698a8cec60b9 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/include/clang/Analysis/PathSensitive/Store.h @@ -103,6 +103,9 @@ public: virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; + // T - the object type. + Loc getThisObject(QualType T); + // FIXME: Make out-of-line. virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, const MemRegion *region) { diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index a0ec87d2f75cc7bafd284029141fe19c5f93bba9..f93ed7871b5c5da32deeebd4051779aa22b7d644 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -506,7 +506,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { case Stmt::CXXTypeidExprClass: case Stmt::CXXBoolLiteralExprClass: case Stmt::CXXNullPtrLiteralExprClass: - case Stmt::CXXThisExprClass: case Stmt::CXXThrowExprClass: case Stmt::CXXDefaultArgExprClass: case Stmt::CXXZeroInitValueExprClass: @@ -567,7 +566,8 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { break; } - if (AMgr.shouldEagerlyAssume() && (B->isRelationalOp() || B->isEqualityOp())) { + if (AMgr.shouldEagerlyAssume() && + (B->isRelationalOp() || B->isEqualityOp())) { ExplodedNodeSet Tmp; VisitBinaryOperator(cast(S), Pred, Tmp, false); EvalEagerlyAssume(Dst, Tmp, cast(S)); @@ -608,6 +608,10 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { break; } + case Stmt::CXXThisExprClass: + VisitCXXThisExpr(cast(S), Pred, Dst); + break; + case Stmt::DeclRefExprClass: VisitDeclRefExpr(cast(S), Pred, Dst, false); break; @@ -692,7 +696,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { case Stmt::UnaryOperatorClass: { UnaryOperator *U = cast(S); - if (AMgr.shouldEagerlyAssume() && (U->getOpcode() == UnaryOperator::LNot)) { + if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UnaryOperator::LNot)) { ExplodedNodeSet Tmp; VisitUnaryOperator(U, Pred, Tmp, false); EvalEagerlyAssume(Dst, Tmp, U); @@ -709,7 +713,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, Ex = Ex->IgnoreParens(); - if (Ex != CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)) { + if (Ex != CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)){ Dst.Add(Pred); return; } @@ -1025,7 +1029,8 @@ void GRExprEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) { void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst) { - assert (Ex == CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)); + assert(Ex == CurrentStmt && + Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)); const GRState* state = GetState(Pred); SVal X = state->getSVal(Ex); @@ -1149,7 +1154,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, assert(B->getOpcode() == BinaryOperator::LAnd || B->getOpcode() == BinaryOperator::LOr); - assert(B == CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B)); + assert(B==CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B)); const GRState* state = GetState(Pred); SVal X = state->getSVal(B); @@ -2067,7 +2072,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred, } EvalBind(Dst, DS, DS, *I, state, - loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true); + loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true); } else { state = state->bindDeclWithNoInit(state->getRegion(VD, LC)); @@ -2129,7 +2134,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, InitListExpr::reverse_iterator NewItr = X.Itr + 1; - for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) { + for (ExplodedNodeSet::iterator NI=Tmp.begin(),NE=Tmp.end();NI!=NE;++NI) { // Get the last initializer value. state = GetState(*NI); SVal InitV = state->getSVal(cast(*X.Itr)); @@ -2161,7 +2166,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet Tmp; Expr* Init = E->getInit(0); Visit(Init, Pred, Tmp); - for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I != EI; ++I) { + for (ExplodedNodeSet::iterator I=Tmp.begin(), EI=Tmp.end(); I != EI; ++I) { state = GetState(*I); MakeNode(Dst, E, *I, state->BindExpr(E, state->getSVal(Init))); } @@ -2429,7 +2434,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, ExplodedNodeSet Tmp2; EvalLoad(Tmp2, Ex, *I, state, V1); - for (ExplodedNodeSet::iterator I2 = Tmp2.begin(), E2 = Tmp2.end(); I2!=E2; ++I2) { + for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) { state = GetState(*I2); SVal V2_untested = state->getSVal(Ex); @@ -2492,14 +2497,23 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, } } -void GRExprEngine::VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst) { + +void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, + ExplodedNodeSet & Dst) { + // Get the this object region from StoreManager. + Loc V = getStoreManager().getThisObject(TE->getType()->getPointeeType()); + MakeNode(Dst, TE, Pred, GetState(Pred)->BindExpr(TE, V)); +} + +void GRExprEngine::VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, + ExplodedNodeSet& Dst) { VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst); } void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A, AsmStmt::outputs_iterator I, AsmStmt::outputs_iterator E, - ExplodedNode* Pred, ExplodedNodeSet& Dst) { + ExplodedNode* Pred, ExplodedNodeSet& Dst) { if (I == E) { VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst); return; @@ -2510,14 +2524,15 @@ void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A, ++I; - for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI) + for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end();NI != NE;++NI) VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst); } void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A, AsmStmt::inputs_iterator I, AsmStmt::inputs_iterator E, - ExplodedNode* Pred, ExplodedNodeSet& Dst) { + ExplodedNode* Pred, + ExplodedNodeSet& Dst) { if (I == E) { // We have processed both the inputs and the outputs. All of the outputs @@ -2645,7 +2660,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Simulate the effects of a "store": bind the value of the RHS // to the L-Value represented by the LHS. - EvalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV, RightV); + EvalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV); continue; } diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp index bc3a5b704552c6813c0d694cdcc478559e784dc8..04d730c5c80fb9a2339b605ec22558f83067899a 100644 --- a/clang/lib/Analysis/MemRegion.cpp +++ b/clang/lib/Analysis/MemRegion.cpp @@ -291,6 +291,17 @@ void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion()); } +void CXXObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, + QualType T, + const MemRegion *sReg) { + ID.AddPointer(T.getTypePtr()); + ID.AddPointer(sReg); +} + +void CXXObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ProfileRegion(ID, T, getSuperRegion()); +} + //===----------------------------------------------------------------------===// // Region pretty-printing. //===----------------------------------------------------------------------===// @@ -558,6 +569,11 @@ MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d, return getSubRegion(d, superRegion); } +const CXXObjectRegion * +MemRegionManager::getCXXObjectRegion(QualType T) { + return getSubRegion(T, getUnknownRegion()); +} + const AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt, const LocationContext *LC) { diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index bc3680e23da17959606c5bcd08b00ae3e8a227a5..b83ddf224bb28aad18641009c72abb714f1161b7 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -746,6 +746,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, case MemRegion::ObjCIvarRegionKind: case MemRegion::ObjCObjectRegionKind: case MemRegion::SymbolicRegionKind: + case MemRegion::CXXObjectRegionKind: return UnknownVal(); case MemRegion::StringRegionKind: { @@ -869,6 +870,7 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state, case MemRegion::FieldRegionKind: case MemRegion::ObjCObjectRegionKind: case MemRegion::ObjCIvarRegionKind: + case MemRegion::CXXObjectRegionKind: return UnknownVal(); case MemRegion::FunctionTextRegionKind: diff --git a/clang/lib/Analysis/Store.cpp b/clang/lib/Analysis/Store.cpp index 56f8a0a70c9574fd54a1fb225b3af2a6cf2c4d8c..0479c684d71113d605bfd1f37d0e325fd10eb1e2 100644 --- a/clang/lib/Analysis/Store.cpp +++ b/clang/lib/Analysis/Store.cpp @@ -106,6 +106,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy) case MemRegion::FieldRegionKind: case MemRegion::ObjCIvarRegionKind: case MemRegion::VarRegionKind: + case MemRegion::CXXObjectRegionKind: return MakeElementRegion(R, PointeeTy); case MemRegion::ElementRegionKind: { @@ -240,3 +241,8 @@ SVal StoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL, const LocationContext *LC) { return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)); } + +Loc StoreManager::getThisObject(QualType T) { + const CXXObjectRegion *R = MRMgr.getCXXObjectRegion(T); + return loc::MemRegionVal(R); +}