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