DynamicTypePropagation.cpp revision 54918ba02ba900c0e0bb4fd3d749b6b1ac4e50a9
146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//== DynamicTypePropagation.cpp ----------------------------------- -*- C++ -*--=// 246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The LLVM Compiler Infrastructure 446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// License. See LICENSE.TXT for details. 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===// 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This checker defines the rules for dynamic type gathering and propagation. 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// 1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===// 1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "ClangSACheckers.h" 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "clang/Basic/Builtins.h" 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using namespace clang; 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using namespace ento; 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace { 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class DynamicTypePropagation: 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public Checker< check::PostCall, 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) check::PostStmt<ImplicitCastExpr> > { 3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CheckerContext &C) const; 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) /// \brief Return a better dynamic type if one can be derived from the cast. 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE, 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CheckerContext &C) const; 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)public: 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void checkPostCall(const CallEvent &Call, CheckerContext &C) const; 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const; 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void DynamicTypePropagation::checkPostCall(const CallEvent &Call, 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CheckerContext &C) const { 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // We can obtain perfect type info for return values from some calls. 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) { 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Get the returned value if it's a region. 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SVal Result = C.getSVal(Call.getOriginExpr()); 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const MemRegion *RetReg = Result.getAsRegion(); 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!RetReg) 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ProgramStateRef State = C.getState(); 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) switch (Msg->getMethodFamily()) { 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) default: 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) break; 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // We assume that the type of the object returned by alloc and new are the 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // pointer to the object of the class specified in the receiver of the 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // message. 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) case OMF_alloc: 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) case OMF_new: { 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Get the type of object that will get created. 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCMessageExpr *MsgE = Msg->getOriginExpr(); 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C); 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!ObjTy) 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) QualType DynResTy = 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0)); 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy, false)); 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) break; 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) case OMF_init: { 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Assume, the result of the init method has the same dynamic type as 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // the receiver and propagate the dynamic type info. 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion(); 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!RecReg) 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DynamicTypeInfo RecDynType = State->getDynamicTypeInfo(RecReg); 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) C.addTransition(State->setDynamicTypeInfo(RetReg, RecDynType)); 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) break; 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DynamicTypePropagation::checkPostStmt(const ImplicitCastExpr *CastE, 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CheckerContext &C) const { 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // We only track dynamic type info for regions. 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const MemRegion *ToR = C.getSVal(CastE).getAsRegion(); 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!ToR) 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (CastE->getCastKind()) { 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default: 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case CK_BitCast: 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Only handle ObjCObjects for now. 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (const Type *NewTy = getBetterObjCType(CastE, C)) 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci C.addTransition(C.getState()->setDynamicTypeInfo(ToR, QualType(NewTy,0))); 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const ObjCObjectType * 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)DynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE, 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CheckerContext &C) const { 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) { 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const ObjCObjectType *ObjTy 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) = MsgE->getClassReceiver()->getAs<ObjCObjectType>()) 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return ObjTy; 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) { 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const ObjCObjectType *ObjTy 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) = MsgE->getSuperType()->getAs<ObjCObjectType>()) 11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return ObjTy; 12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Expr *RecE = MsgE->getInstanceReceiver(); 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!RecE) 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return 0; 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RecE= RecE->IgnoreParenImpCasts(); 12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) { 12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const StackFrameContext *SFCtx = C.getCurrentStackFrame(); 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Are we calling [self alloc]? If this is self, get the type of the 13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // enclosing ObjC class. 13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (DRE->getDecl() == SFCtx->getSelfDecl()) { 13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl())) 13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (const ObjCObjectType *ObjTy = 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl())) 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return ObjTy; 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return 0; 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Return a better dynamic type if one can be derived from the cast. 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Compare the current dynamic type of the region and the new type to which we 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// are casting. If the new type is lower in the inheritance hierarchy, pick it. 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst ObjCObjectPointerType * 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)DynamicTypePropagation::getBetterObjCType(const Expr *CastE, 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CheckerContext &C) const { 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const MemRegion *ToR = C.getSVal(CastE).getAsRegion(); 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) assert(ToR); 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Get the old and new types. 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCObjectPointerType *NewTy = 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CastE->getType()->getAs<ObjCObjectPointerType>(); 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!NewTy) 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return 0; 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType(); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (OldDTy.isNull()) { 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return NewTy; 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCObjectPointerType *OldTy = 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) OldDTy->getAs<ObjCObjectPointerType>(); 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!OldTy) 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return 0; 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Id the old type is 'id', the new one is more precise. 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (OldTy->isObjCIdType() && !NewTy->isObjCIdType()) 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return NewTy; 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Return new if it's a subclass of old. 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl(); 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl(); 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (ToI && FromI && FromI->isSuperClassOf(ToI)) 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return NewTy; 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return 0; 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ento::registerDynamicTypePropagation(CheckerManager &mgr) { 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) mgr.registerChecker<DynamicTypePropagation>(); 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)