DynamicTypePropagation.cpp revision 55fc873017f10f6f566b182b70f6fc22aefa3464
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,
30c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks                    check::PostStmt<ImplicitCastExpr> > {
31c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
32c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks                                                    CheckerContext &C) const;
33c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
34c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  /// \brief Return a better dynamic type if one can be derived from the cast.
35c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
36c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks                                                 CheckerContext &C) const;
37c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zakspublic:
380ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
39c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
40c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  void checkPostStmt(const ImplicitCastExpr *CastE, CheckerContext &C) const;
41c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks};
42c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks}
43c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
444e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rosestatic void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
454e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose                            CheckerContext &C) {
464e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  assert(Region);
474e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  assert(MD);
484e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
494e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  ASTContext &Ctx = C.getASTContext();
504e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent()));
514e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
524e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  ProgramStateRef State = C.getState();
534e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  State = State->setDynamicTypeInfo(Region, Ty, /*CanBeSubclass=*/false);
544e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  C.addTransition(State);
554e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  return;
564e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose}
574e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
580ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rosevoid DynamicTypePropagation::checkPreCall(const CallEvent &Call,
590ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose                                          CheckerContext &C) const {
604e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
610ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    // C++11 [class.cdtor]p4: When a virtual function is called directly or
620ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    //   indirectly from a constructor or from a destructor, including during
630ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    //   the construction or destruction of the class’s non-static data members,
640ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    //   and the object to which the call applies is the object under
650ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    //   construction or destruction, the function called is the final overrider
660ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    //   in the constructor's or destructor's class and not one overriding it in
670ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    //   a more-derived class.
684e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
694e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    switch (Ctor->getOriginExpr()->getConstructionKind()) {
704e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_Complete:
714e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_Delegating:
724e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      // No additional type info necessary.
734e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      return;
744e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_NonVirtualBase:
754e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_VirtualBase:
764e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion())
774e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose        recordFixedType(Target, Ctor->getDecl(), C);
784e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      return;
794e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    }
804e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
814e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    return;
824e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  }
834e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
844e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  if (const CXXDestructorCall *Dtor = dyn_cast<CXXDestructorCall>(&Call)) {
854e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    // C++11 [class.cdtor]p4 (see above)
86200fa2e70d52ae6d620e81cd45536071fdde70c0Jordan Rose    if (!Dtor->isBaseDestructor())
87200fa2e70d52ae6d620e81cd45536071fdde70c0Jordan Rose      return;
880ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose
890ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion();
900ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    if (!Target)
910ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose      return;
920ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose
93200fa2e70d52ae6d620e81cd45536071fdde70c0Jordan Rose    const Decl *D = Dtor->getDecl();
940ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose    if (!D)
950ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose      return;
960ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose
974e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    recordFixedType(Target, cast<CXXDestructorDecl>(D), C);
984e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    return;
990ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose  }
1000ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose}
1010ad36baedc516005cb6ea97d96327517ebfe5138Jordan Rose
102c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksvoid DynamicTypePropagation::checkPostCall(const CallEvent &Call,
103c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks                                           CheckerContext &C) const {
104c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  // We can obtain perfect type info for return values from some calls.
105c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
106c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
107c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    // Get the returned value if it's a region.
1082f3017f9cbd3774f690c979410bfec38423d03afJordan Rose    const MemRegion *RetReg = Call.getReturnValue().getAsRegion();
109c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    if (!RetReg)
110c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      return;
111c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
112c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    ProgramStateRef State = C.getState();
113c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
114c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    switch (Msg->getMethodFamily()) {
115c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    default:
116c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      break;
117c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
118c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    // We assume that the type of the object returned by alloc and new are the
119c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    // pointer to the object of the class specified in the receiver of the
120c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    // message.
121c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    case OMF_alloc:
122c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    case OMF_new: {
123c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      // Get the type of object that will get created.
124c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      const ObjCMessageExpr *MsgE = Msg->getOriginExpr();
125c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C);
126c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      if (!ObjTy)
127c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks        return;
128c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      QualType DynResTy =
129c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks                 C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0));
13054918ba02ba900c0e0bb4fd3d749b6b1ac4e50a9Anna Zaks      C.addTransition(State->setDynamicTypeInfo(RetReg, DynResTy, false));
131c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      break;
132c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    }
133c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    case OMF_init: {
134c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      // Assume, the result of the init method has the same dynamic type as
135c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      // the receiver and propagate the dynamic type info.
136c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
1378ed21ef726be89ef7151b5ff397631379bd8a537Anna Zaks      if (!RecReg)
1388ed21ef726be89ef7151b5ff397631379bd8a537Anna Zaks        return;
139c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      DynamicTypeInfo RecDynType = State->getDynamicTypeInfo(RecReg);
140d4fe57f7f7a8793227effc1274d70ec44cee9a4fAnna Zaks      C.addTransition(State->setDynamicTypeInfo(RetReg, RecDynType));
141c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      break;
142c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    }
143c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    }
1444e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
1454e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    return;
1464e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  }
1474e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose
1484e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose  if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
1494e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    // We may need to undo the effects of our pre-call check.
1504e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    switch (Ctor->getOriginExpr()->getConstructionKind()) {
1514e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_Complete:
1524e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_Delegating:
1534e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      // No additional work necessary.
1544e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      // Note: This will leave behind the actual type of the object for
1554e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      // complete constructors, but arguably that's a good thing, since it
1564e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      // means the dynamic type info will be correct even for objects
1574e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      // constructed with operator new.
1584e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      return;
1594e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_NonVirtualBase:
1604e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    case CXXConstructExpr::CK_VirtualBase:
1614e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
1624e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose        // We just finished a base constructor. Now we can use the subclass's
1634e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose        // type when resolving virtual calls.
1644e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose        const Decl *D = C.getLocationContext()->getDecl();
1654e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose        recordFixedType(Target, cast<CXXConstructorDecl>(D), C);
1664e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      }
1674e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose      return;
1684e79fdfe22db1c982e8fdf8397fee426a8c57821Jordan Rose    }
169c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  }
170c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks}
171c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
172c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksvoid DynamicTypePropagation::checkPostStmt(const ImplicitCastExpr *CastE,
173c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks                                           CheckerContext &C) const {
174c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  // We only track dynamic type info for regions.
175c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
176c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  if (!ToR)
177c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    return;
178c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
179c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  switch (CastE->getCastKind()) {
180c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  default:
181c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    break;
182c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  case CK_BitCast:
183c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    // Only handle ObjCObjects for now.
184c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    if (const Type *NewTy = getBetterObjCType(CastE, C))
185d4fe57f7f7a8793227effc1274d70ec44cee9a4fAnna Zaks      C.addTransition(C.getState()->setDynamicTypeInfo(ToR, QualType(NewTy,0)));
186c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    break;
187c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  }
188c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  return;
189c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks}
190c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
191c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksconst ObjCObjectType *
192c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna ZaksDynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
193c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks                                                    CheckerContext &C) const {
194c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) {
195c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    if (const ObjCObjectType *ObjTy
196c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks          = MsgE->getClassReceiver()->getAs<ObjCObjectType>())
197c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    return ObjTy;
198c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  }
199c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
200c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) {
201c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    if (const ObjCObjectType *ObjTy
202c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks          = MsgE->getSuperType()->getAs<ObjCObjectType>())
203c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      return ObjTy;
204c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  }
205c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
206c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  const Expr *RecE = MsgE->getInstanceReceiver();
207c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  if (!RecE)
208c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    return 0;
209c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
210c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  RecE= RecE->IgnoreParenImpCasts();
211c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
212955cd444f445bcdbade1cdd3926254c8ee7890d8Anna Zaks    const StackFrameContext *SFCtx = C.getStackFrame();
213c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    // Are we calling [self alloc]? If this is self, get the type of the
214c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    // enclosing ObjC class.
215c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    if (DRE->getDecl() == SFCtx->getSelfDecl()) {
216c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks      if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl()))
217c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks        if (const ObjCObjectType *ObjTy =
218c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks            dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl()))
219c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks          return ObjTy;
220c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks    }
221c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  }
222c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  return 0;
223c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks}
224c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks
225c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// Return a better dynamic type if one can be derived from the cast.
226c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// Compare the current dynamic type of the region and the new type to which we
227c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks// are casting. If the new type is lower in the inheritance hierarchy, pick it.
228c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaksconst ObjCObjectPointerType *
229c4c647c88ced2e953f15f8987952ede9b96aa969Anna ZaksDynamicTypePropagation::getBetterObjCType(const Expr *CastE,
230c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks                                          CheckerContext &C) const {
231c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
232c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  assert(ToR);
233c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
234c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  // Get the old and new types.
235c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  const ObjCObjectPointerType *NewTy =
236c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks      CastE->getType()->getAs<ObjCObjectPointerType>();
237c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  if (!NewTy)
238c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    return 0;
239c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  QualType OldDTy = C.getState()->getDynamicTypeInfo(ToR).getType();
240c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  if (OldDTy.isNull()) {
241c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    return NewTy;
242c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  }
243c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  const ObjCObjectPointerType *OldTy =
244c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    OldDTy->getAs<ObjCObjectPointerType>();
245c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  if (!OldTy)
246c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    return 0;
247c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
248c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  // Id the old type is 'id', the new one is more precise.
249c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  if (OldTy->isObjCIdType() && !NewTy->isObjCIdType())
250c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    return NewTy;
251c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
252c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  // Return new if it's a subclass of old.
253c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl();
254c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl();
255c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  if (ToI && FromI && FromI->isSuperClassOf(ToI))
256c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks    return NewTy;
257c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
258c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks  return 0;
259c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks}
260c4c647c88ced2e953f15f8987952ede9b96aa969Anna Zaks
261c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaksvoid ento::registerDynamicTypePropagation(CheckerManager &mgr) {
262c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks  mgr.registerChecker<DynamicTypePropagation>();
263c7ecc43c33a21b82c49664910b19fcc1f555aa51Anna Zaks}
264