DynamicTypePropagation.cpp revision d4fe57f7f7a8793227effc1274d70ec44cee9a4f
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" 15c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/Checker.h" 16c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/CheckerManager.h" 17c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 18c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 19c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 20c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 21c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks#include "clang/Basic/Builtins.h" 22c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 23c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksusing namespace clang; 24c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksusing namespace ento; 25c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 26c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksnamespace { 27c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksclass DynamicTypePropagation: 28c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks public Checker< check::PostCall, 29c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks check::PostStmt<ImplicitCastExpr> > { 30c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, 31c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks CheckerContext &C) const; 32c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 33c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks /// \brief Return a better dynamic type if one can be derived from the cast. 34c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE, 35c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CheckerContext &C) const; 36c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zakspublic: 37c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks void checkPostCall(const CallEvent &Call, CheckerContext &C) const; 38c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const; 39c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks}; 40c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 41c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 42c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksvoid DynamicTypePropagation::checkPostCall(const CallEvent &Call, 43c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks CheckerContext &C) const { 44c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // We can obtain perfect type info for return values from some calls. 45c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { 46c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 47c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // Get the returned value if it's a region. 48c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks SVal Result = C.getSVal(Call.getOriginExpr()); 49c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const MemRegion *RetReg = Result.getAsRegion(); 50c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (!RetReg) 51c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return; 52c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 53c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks ProgramStateRef State = C.getState(); 54c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 55c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks switch (Msg->getMethodFamily()) { 56c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks default: 57c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks break; 58c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 59c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // We assume that the type of the object returned by alloc and new are the 60c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // pointer to the object of the class specified in the receiver of the 61c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // message. 62c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks case OMF_alloc: 63c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks case OMF_new: { 64c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // Get the type of object that will get created. 65c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const ObjCMessageExpr *MsgE = Msg->getOriginExpr(); 66c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C); 67c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (!ObjTy) 68c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return; 69c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks QualType DynResTy = 70c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0)); 71d4fe57f7f7a8793227effc1274d70ec44cee9a4fAnna Zaks C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy)); 72c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks break; 73c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 74c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks case OMF_init: { 75c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // Assume, the result of the init method has the same dynamic type as 76c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // the receiver and propagate the dynamic type info. 77c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion(); 788ed21ef726be89ef7151b5ff397631379bd8a537Anna Zaks if (!RecReg) 798ed21ef726be89ef7151b5ff397631379bd8a537Anna Zaks return; 80c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks DynamicTypeInfo RecDynType = State->getDynamicTypeInfo(RecReg); 81d4fe57f7f7a8793227effc1274d70ec44cee9a4fAnna Zaks C.addTransition(State->setDynamicTypeInfo(RetReg, RecDynType)); 82c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks break; 83c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 84c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 85c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 86c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 87c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 88c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksvoid DynamicTypePropagation::checkPostStmt(const ImplicitCastExpr *CastE, 89c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CheckerContext &C) const { 90c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // We only track dynamic type info for regions. 91c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const MemRegion *ToR = C.getSVal(CastE).getAsRegion(); 92c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (!ToR) 93c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return; 94c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 95c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks switch (CastE->getCastKind()) { 96c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks default: 97c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks break; 98c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks case CK_BitCast: 99c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Only handle ObjCObjects for now. 100c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (const Type *NewTy = getBetterObjCType(CastE, C)) 101d4fe57f7f7a8793227effc1274d70ec44cee9a4fAnna Zaks C.addTransition(C.getState()->setDynamicTypeInfo(ToR, QualType(NewTy,0))); 102c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks break; 103c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks } 104c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return; 105c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks} 106c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 107c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksconst ObjCObjectType * 108c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna ZaksDynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, 109c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks CheckerContext &C) const { 110c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) { 111c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCObjectType *ObjTy 112c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks = MsgE->getClassReceiver()->getAs<ObjCObjectType>()) 113c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return ObjTy; 114c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 115c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 116c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) { 117c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCObjectType *ObjTy 118c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks = MsgE->getSuperType()->getAs<ObjCObjectType>()) 119c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return ObjTy; 120c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 121c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 122c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const Expr *RecE = MsgE->getInstanceReceiver(); 123c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (!RecE) 124c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return 0; 125c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 126c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks RecE= RecE->IgnoreParenImpCasts(); 127c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) { 128c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks const StackFrameContext *SFCtx = C.getCurrentStackFrame(); 129c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // Are we calling [self alloc]? If this is self, get the type of the 130c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks // enclosing ObjC class. 131c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (DRE->getDecl() == SFCtx->getSelfDecl()) { 132c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl())) 133c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks if (const ObjCObjectType *ObjTy = 134c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl())) 135c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return ObjTy; 136c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 137c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks } 138c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks return 0; 139c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 140c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks 141c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// Return a better dynamic type if one can be derived from the cast. 142c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// Compare the current dynamic type of the region and the new type to which we 143c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// are casting. If the new type is lower in the inheritance hierarchy, pick it. 144c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksconst ObjCObjectPointerType * 145c4c647c88ced2e953f15f8987952ede9b96aa969Anna ZaksDynamicTypePropagation::getBetterObjCType(const Expr *CastE, 146c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CheckerContext &C) const { 147c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const MemRegion *ToR = C.getSVal(CastE).getAsRegion(); 148c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks assert(ToR); 149c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 150c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Get the old and new types. 151c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCObjectPointerType *NewTy = 152c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks CastE->getType()->getAs<ObjCObjectPointerType>(); 153c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (!NewTy) 154c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return 0; 155c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType(); 156c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (OldDTy.isNull()) { 157c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return NewTy; 158c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks } 159c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCObjectPointerType *OldTy = 160c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks OldDTy->getAs<ObjCObjectPointerType>(); 161c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (!OldTy) 162c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return 0; 163c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 164c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Id the old type is 'id', the new one is more precise. 165c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (OldTy->isObjCIdType() && !NewTy->isObjCIdType()) 166c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return NewTy; 167c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 168c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks // Return new if it's a subclass of old. 169c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl(); 170c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl(); 171c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks if (ToI && FromI && FromI->isSuperClassOf(ToI)) 172c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return NewTy; 173c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 174c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks return 0; 175c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks} 176c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks 177c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksvoid ento::registerDynamicTypePropagation(CheckerManager &mgr) { 178c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks mgr.registerChecker<DynamicTypePropagation>(); 179c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks} 180