diff options
author | Anna Zaks <ganna@apple.com> | 2013-02-25 22:10:34 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2013-02-25 22:10:34 +0000 |
commit | db061e40d639da0d938f915f0eef9e9772019c22 (patch) | |
tree | 3ed41eda7b9adcdcbf7274ee330de4f85fe0a61f /lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp | |
parent | 6f8e9b6caed0bf6108cf90f0d54fa637b60b3b9e (diff) |
[analyzer] Restrict ObjC type inference to methods that have related result type.
This addresses a case when we inline a wrong method due to incorrect
dynamic type inference. Specifically, when user code contains a method from init
family, which creates an instance of another class.
Use hasRelatedResultType() to find out if our inference rules should be triggered.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176054 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp | 62 |
1 files changed, 32 insertions, 30 deletions
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 08af45df37..9f176a4b5b 100644 --- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -110,38 +110,40 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call, 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 = + const ObjCMethodDecl *D = Msg->getDecl(); + + if (D && D->hasRelatedResultType()) { + 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; - } + 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; } |