void DynamicTypePropagation::checkPostCall(const CallEvent &Call, CheckerContext &C) const { // We can obtain perfect type info for return values from some calls. if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { // Get the returned value if it's a region. const MemRegion *RetReg = Call.getReturnValue().getAsRegion(); if (!RetReg) return; ProgramStateRef State = C.getState(); switch (Msg->getMethodFamily()) { default: break; // We assume that the type of the object returned by alloc and new are the // pointer to the object of the class specified in the receiver of the // message. case OMF_alloc: case OMF_new: { // Get the type of object that will get created. const ObjCMessageExpr *MsgE = Msg->getOriginExpr(); const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C); if (!ObjTy) return; QualType DynResTy = C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0)); C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy, false)); break; } case OMF_init: { // Assume, the result of the init method has the same dynamic type as // the receiver and propagate the dynamic type info. const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion(); if (!RecReg) return; DynamicTypeInfo RecDynType = State->getDynamicTypeInfo(RecReg); C.addTransition(State->setDynamicTypeInfo(RetReg, RecDynType)); break; } } return; } if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { // We may need to undo the effects of our pre-call check. switch (Ctor->getOriginExpr()->getConstructionKind()) { case CXXConstructExpr::CK_Complete: case CXXConstructExpr::CK_Delegating: // No additional work necessary. // Note: This will leave behind the actual type of the object for // complete constructors, but arguably that's a good thing, since it // means the dynamic type info will be correct even for objects // constructed with operator new. return; case CXXConstructExpr::CK_NonVirtualBase: case CXXConstructExpr::CK_VirtualBase: if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) { // We just finished a base constructor. Now we can use the subclass's // type when resolving virtual calls. const Decl *D = C.getLocationContext()->getDecl(); recordFixedType(Target, cast<CXXConstructorDecl>(D), C); } return; } } }