From: Zhongxing Xu Date: Fri, 26 Nov 2010 08:21:53 +0000 (+0000) Subject: Regionstore: support derived-to-base cast by creating a CXXBaseObjectRegion. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4fd56816e0925c04f2c92e75399f5c9018d5d6fb;p=clang Regionstore: support derived-to-base cast by creating a CXXBaseObjectRegion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120173 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index 6cb68e6beb..61fa00adf3 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -93,8 +93,9 @@ public: VarRegionKind = BEG_DECL_REGIONS, FieldRegionKind, ObjCIvarRegionKind, + END_DECL_REGIONS = ObjCIvarRegionKind, CXXObjectRegionKind, - END_DECL_REGIONS = CXXObjectRegionKind, + CXXBaseObjectRegionKind, END_TYPED_REGIONS = END_DECL_REGIONS }; @@ -850,6 +851,31 @@ public: } }; +// CXXBaseObjectRegion represents a base object within a C++ object. It is +// identified by the base class declaration and the region of its parent object. +class CXXBaseObjectRegion : public TypedRegion { + friend class MemRegionManager; + + const CXXRecordDecl *decl; + + CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg) + : TypedRegion(sReg, CXXBaseObjectRegionKind), decl(d) {} + + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + const CXXRecordDecl *decl, const MemRegion *sReg); + +public: + QualType getValueType() const; + + void dumpToStream(llvm::raw_ostream& os) const; + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion *region) { + return region->getKind() == CXXBaseObjectRegionKind; + } +}; + template const RegionTy* MemRegion::getAs() const { if (const RegionTy* RT = dyn_cast(this)) @@ -976,6 +1002,9 @@ public: const CXXObjectRegion *getCXXObjectRegion(Expr const *Ex, LocationContext const *LC); + const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl, + const MemRegion *superRegion); + const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index 8aad4ff251..44638ec236 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -130,6 +130,11 @@ public: /// conversions between arrays and pointers. virtual SVal ArrayToPointer(Loc Array) = 0; + /// Evaluates DerivedToBase casts. + virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) { + return UnknownVal(); + } + class CastResult { const GRState *state; const MemRegion *region; diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 4121144fad..f541a7ece4 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -2688,8 +2688,7 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_IntegralComplexToFloatingComplex: case CK_AnyPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: + case CK_ObjCObjectLValueCast: { // Delegate to SValuator to process. for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { @@ -2702,7 +2701,20 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, } return; } - + + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + // For DerivedToBase cast, delegate to the store manager. + for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) { + ExplodedNode *node = *I; + const GRState *state = GetState(node); + SVal val = state->getSVal(Ex); + val = getStoreManager().evalDerivedToBase(val, T); + state = state->BindExpr(CastE, val); + MakeNode(Dst, CastE, node, state); + } + return; + // Various C++ casts that are not handled yet. case CK_Dynamic: case CK_ToUnion: diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp index 4414c1a57a..366a574683 100644 --- a/lib/Checker/MemRegion.cpp +++ b/lib/Checker/MemRegion.cpp @@ -218,6 +218,10 @@ DefinedOrUnknownSVal StringRegion::getExtent(ValueManager& ValMgr) const { return ValMgr.makeIntVal(getStringLiteral()->getByteLength()+1, SizeTy); } +QualType CXXBaseObjectRegion::getValueType() const { + return QualType(decl->getTypeForDecl(), 0); +} + //===----------------------------------------------------------------------===// // FoldingSet profiling. //===----------------------------------------------------------------------===// @@ -367,6 +371,17 @@ void CXXObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { ProfileRegion(ID, Ex, getSuperRegion()); } +void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, + const CXXRecordDecl *decl, + const MemRegion *sReg) { + ID.AddPointer(decl); + ID.AddPointer(sReg); +} + +void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ProfileRegion(ID, decl, superRegion); +} + //===----------------------------------------------------------------------===// // Region pretty-printing. //===----------------------------------------------------------------------===// @@ -411,6 +426,10 @@ void CXXObjectRegion::dumpToStream(llvm::raw_ostream &os) const { os << "temp_object"; } +void CXXBaseObjectRegion::dumpToStream(llvm::raw_ostream &os) const { + os << "base " << decl->getName(); +} + void CXXThisRegion::dumpToStream(llvm::raw_ostream &os) const { os << "this"; } @@ -687,6 +706,12 @@ MemRegionManager::getCXXObjectRegion(Expr const *E, return getSubRegion(E, getStackLocalsRegion(SFC)); } +const CXXBaseObjectRegion * +MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *decl, + const MemRegion *superRegion) { + return getSubRegion(decl, superRegion); +} + const CXXThisRegion* MemRegionManager::getCXXThisRegion(QualType thisPointerTy, const LocationContext *LC) { diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index e5b1bca5d8..59c8730009 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -224,6 +224,9 @@ public: /// casts from arrays to pointers. SVal ArrayToPointer(Loc Array); + /// For DerivedToBase casts, create a CXXBaseObjectRegion and return it. + virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType); + SVal EvalBinOp(BinaryOperator::Opcode Op,Loc L, NonLoc R, QualType resultTy); Store getInitialStore(const LocationContext *InitLoc) { @@ -804,6 +807,14 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) { return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx)); } +SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType basePtrType) { + const CXXRecordDecl *baseDecl = basePtrType->getCXXRecordDeclForPointerType(); + assert(baseDecl && "not a CXXRecordDecl?"); + loc::MemRegionVal &derivedRegVal = cast(derived); + const MemRegion *baseReg = + MRMgr.getCXXBaseObjectRegion(baseDecl, derivedRegVal.getRegion()); + return loc::MemRegionVal(baseReg); +} //===----------------------------------------------------------------------===// // Pointer arithmetic. //===----------------------------------------------------------------------===// @@ -869,6 +880,7 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R, case MemRegion::FieldRegionKind: case MemRegion::ObjCIvarRegionKind: case MemRegion::CXXObjectRegionKind: + case MemRegion::CXXBaseObjectRegionKind: return UnknownVal(); case MemRegion::FunctionTextRegionKind: diff --git a/test/Analysis/derived-to-base.cpp b/test/Analysis/derived-to-base.cpp new file mode 100644 index 0000000000..2a9244ef34 --- /dev/null +++ b/test/Analysis/derived-to-base.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store region %s + +class A { +protected: + int x; +}; + +class B : public A { +public: + void f(); +}; + +void B::f() { + x = 3; +}