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