DynamicTypePropagation.cpp revision fbc4444eb2675934b44f3720ef9a5f368ecbeb0a
1c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks//== DynamicTypePropagation.cpp ----------------------------------- -*- C++ -*--=// 2c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// 3c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// The LLVM Compiler Infrastructure 4c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// 5c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// This file is distributed under the University of Illinois Open Source 6c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// License. See LICENSE.TXT for details. 7c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// 8c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks//===----------------------------------------------------------------------===// 9c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// 10c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// This checker defines the rules for dynamic type gathering and propagation. 11c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks// 12c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks//===----------------------------------------------------------------------===// 13c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 14c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "ClangSACheckers.h" 1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/Builtins.h" 1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/Checker.h" 18c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 20c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 21c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 22c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 23c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksusing namespace clang; 24c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksusing namespace ento; 25c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 26c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksnamespace { 27c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksclass DynamicTypePropagation: 280ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose public Checker< check::PreCall, 290ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose check::PostCall, 30fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose check::PostStmt<ImplicitCastExpr>, 31fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose check::PostStmt<CXXNewExpr> > { 32c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, 33c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks CheckerContext &C) const; 34c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 35c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks /// \brief Return a better dynamic type if one can be derived from the cast. 36c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE, 37c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CheckerContext &C) const; 38c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zakspublic: 390ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 40c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks void checkPostCall(const CallEvent &Call, CheckerContext &C) const; 41c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const; 42fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const; 43c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks}; 44c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 45c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 464e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rosestatic void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD, 474e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose CheckerContext &C) { 484e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose assert(Region); 494e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose assert(MD); 504e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose 514e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose ASTContext &Ctx = C.getASTContext(); 524e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent())); 534e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose 544e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose ProgramStateRef State = C.getState(); 554e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose State = State->setDynamicTypeInfo(Region, Ty, /*CanBeSubclass=*/false); 564e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose C.addTransition(State); 574e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 584e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose} 594e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose 600ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rosevoid DynamicTypePropagation::checkPreCall(const CallEvent &Call, 610ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose CheckerContext &C) const { 624e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { 630ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose // C++11 [class.cdtor]p4: When a virtual function is called directly or 640ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose // indirectly from a constructor or from a destructor, including during 650ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose // the construction or destruction of the class’s non-static data members, 660ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose // and the object to which the call applies is the object under 670ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose // construction or destruction, the function called is the final overrider 680ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose // in the constructor's or destructor's class and not one overriding it in 690ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose // a more-derived class. 704e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose 714e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose switch (Ctor->getOriginExpr()->getConstructionKind()) { 724e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_Complete: 734e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_Delegating: 744e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // No additional type info necessary. 754e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 764e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_NonVirtualBase: 774e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_VirtualBase: 784e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) 794e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose recordFixedType(Target, Ctor->getDecl(), C); 804e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 814e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose } 824e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose 834e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 844e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose } 854e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose 864e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose if (const CXXDestructorCall *Dtor = dyn_cast<CXXDestructorCall>(&Call)) { 874e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // C++11 [class.cdtor]p4 (see above) 88200fa2e70d52ae6d620e81cd45536071fdde70c0Jordan Rose if (!Dtor->isBaseDestructor()) 89200fa2e70d52ae6d620e81cd45536071fdde70c0Jordan Rose return; 900ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose 910ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion(); 920ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose if (!Target) 930ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose return; 940ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose 95200fa2e70d52ae6d620e81cd45536071fdde70c0Jordan Rose const Decl *D = Dtor->getDecl(); 960ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose if (!D) 970ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose return; 980ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose 994e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose recordFixedType(Target, cast<CXXDestructorDecl>(D), C); 1004e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 1010ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose } 1020ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose} 1030ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose 104c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksvoid DynamicTypePropagation::checkPostCall(const CallEvent &Call, 105c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks CheckerContext &C) const { 106c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // We can obtain perfect type info for return values from some calls. 107c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { 108c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 109c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // Get the returned value if it's a region. 1102f3017f9cbd3774f690c979410bfec38423d03afJordan Rose const MemRegion *RetReg = Call.getReturnValue().getAsRegion(); 111c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (!RetReg) 112c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return; 113c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 114c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks ProgramStateRef State = C.getState(); 115db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks const ObjCMethodDecl *D = Msg->getDecl(); 116db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks 117db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks if (D && D->hasRelatedResultType()) { 118db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks switch (Msg->getMethodFamily()) { 119db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks default: 120db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks break; 121db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks 122db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks // We assume that the type of the object returned by alloc and new are the 123db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks // pointer to the object of the class specified in the receiver of the 124db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks // message. 125db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks case OMF_alloc: 126db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks case OMF_new: { 127db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks // Get the type of object that will get created. 128db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks const ObjCMessageExpr *MsgE = Msg->getOriginExpr(); 129db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C); 130db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks if (!ObjTy) 131db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks return; 132db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks QualType DynResTy = 133c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0)); 134db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy, false)); 135db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks break; 136db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks } 137db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks case OMF_init: { 138db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks // Assume, the result of the init method has the same dynamic type as 139db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks // the receiver and propagate the dynamic type info. 140db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion(); 141db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks if (!RecReg) 142db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks return; 143db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks DynamicTypeInfo RecDynType = State->getDynamicTypeInfo(RecReg); 144db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks C.addTransition(State->setDynamicTypeInfo(RetReg, RecDynType)); 145db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks break; 146db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks } 147db061e40d639da0d938f915f0eef9e9772019c22Anna Zaks } 148c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 1494e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 1504e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose } 1514e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose 1524e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { 1534e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // We may need to undo the effects of our pre-call check. 1544e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose switch (Ctor->getOriginExpr()->getConstructionKind()) { 1554e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_Complete: 1564e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_Delegating: 1574e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // No additional work necessary. 1584e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // Note: This will leave behind the actual type of the object for 1594e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // complete constructors, but arguably that's a good thing, since it 1604e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // means the dynamic type info will be correct even for objects 1614e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // constructed with operator new. 1624e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 1634e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_NonVirtualBase: 1644e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose case CXXConstructExpr::CK_VirtualBase: 1654e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) { 1664e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // We just finished a base constructor. Now we can use the subclass's 1674e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose // type when resolving virtual calls. 1684e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose const Decl *D = C.getLocationContext()->getDecl(); 1694e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose recordFixedType(Target, cast<CXXConstructorDecl>(D), C); 1704e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose } 1714e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose return; 1724e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose } 173c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 174c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 175c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 176c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksvoid DynamicTypePropagation::checkPostStmt(const ImplicitCastExpr *CastE, 177c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CheckerContext &C) const { 178c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // We only track dynamic type info for regions. 179c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const MemRegion *ToR = C.getSVal(CastE).getAsRegion(); 180c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (!ToR) 181c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return; 182c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 183c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks switch (CastE->getCastKind()) { 184c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks default: 185c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks break; 186c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks case CK_BitCast: 187c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Only handle ObjCObjects for now. 188c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (const Type *NewTy = getBetterObjCType(CastE, C)) 189d4fe57f7f7a8793227effc1274d70ec44cee9a4fAnna Zaks C.addTransition(C.getState()->setDynamicTypeInfo(ToR, QualType(NewTy,0))); 190c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks break; 191c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks } 192c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return; 193c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks} 194c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 195fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rosevoid DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE, 196fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose CheckerContext &C) const { 197fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose if (NewE->isArray()) 198fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose return; 199fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose 200fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose // We only track dynamic type info for regions. 201fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose const MemRegion *MR = C.getSVal(NewE).getAsRegion(); 202fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose if (!MR) 203fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose return; 204fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose 205fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose C.addTransition(C.getState()->setDynamicTypeInfo(MR, NewE->getType(), 206fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose /*CanBeSubclass=*/false)); 207fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose} 208fbc4444eb2675934b44f3720ef9a5f368ecbeb0aJordan Rose 209c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksconst ObjCObjectType * 210c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna ZaksDynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, 211c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks CheckerContext &C) const { 212c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) { 213c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCObjectType *ObjTy 214c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks = MsgE->getClassReceiver()->getAs<ObjCObjectType>()) 215c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return ObjTy; 216c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 217c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 218c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) { 219c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCObjectType *ObjTy 220c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks = MsgE->getSuperType()->getAs<ObjCObjectType>()) 221c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return ObjTy; 222c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 223c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 224c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const Expr *RecE = MsgE->getInstanceReceiver(); 225c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (!RecE) 226c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return 0; 227c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 228c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks RecE= RecE->IgnoreParenImpCasts(); 229c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) { 230955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks const StackFrameContext *SFCtx = C.getStackFrame(); 231c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // Are we calling [self alloc]? If this is self, get the type of the 232c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // enclosing ObjC class. 233c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (DRE->getDecl() == SFCtx->getSelfDecl()) { 234c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl())) 235c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCObjectType *ObjTy = 236c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl())) 237c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return ObjTy; 238c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 239c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 240c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return 0; 241c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 242c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 243c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// Return a better dynamic type if one can be derived from the cast. 244c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// Compare the current dynamic type of the region and the new type to which we 245c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// are casting. If the new type is lower in the inheritance hierarchy, pick it. 246c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksconst ObjCObjectPointerType * 247c4c647c88ced2e953f15f8987952ede9b96aa969Anna ZaksDynamicTypePropagation::getBetterObjCType(const Expr *CastE, 248c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CheckerContext &C) const { 249c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const MemRegion *ToR = C.getSVal(CastE).getAsRegion(); 250c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks assert(ToR); 251c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 252c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Get the old and new types. 253c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCObjectPointerType *NewTy = 254c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CastE->getType()->getAs<ObjCObjectPointerType>(); 255c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (!NewTy) 256c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return 0; 257c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType(); 258c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (OldDTy.isNull()) { 259c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return NewTy; 260c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks } 261c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCObjectPointerType *OldTy = 262c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks OldDTy->getAs<ObjCObjectPointerType>(); 263c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (!OldTy) 264c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return 0; 265c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 266c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Id the old type is 'id', the new one is more precise. 267c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (OldTy->isObjCIdType() && !NewTy->isObjCIdType()) 268c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return NewTy; 269c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 270c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Return new if it's a subclass of old. 271c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl(); 272c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl(); 273c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (ToI && FromI && FromI->isSuperClassOf(ToI)) 274c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return NewTy; 275c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 276c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return 0; 277c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks} 278c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 279c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksvoid ento::registerDynamicTypePropagation(CheckerManager &mgr) { 280c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks mgr.registerChecker<DynamicTypePropagation>(); 281c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 282