1//===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// rewriteUnbridgedCasts:
11//
12// A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
13// is from a file-level variable, __bridge cast is used to convert it.
14// For the result of a function call that we know is +1/+0,
15// __bridge/CFBridgingRelease is used.
16//
17//  NSString *str = (NSString *)kUTTypePlainText;
18//  str = b ? kUTTypeRTF : kUTTypePlainText;
19//  NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
20//                                                         _uuid);
21// ---->
22//  NSString *str = (__bridge NSString *)kUTTypePlainText;
23//  str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
24// NSString *_uuidString = (NSString *)
25//            CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
26//
27// For a C pointer to ObjC, for casting 'self', __bridge is used.
28//
29//  CFStringRef str = (CFStringRef)self;
30// ---->
31//  CFStringRef str = (__bridge CFStringRef)self;
32//
33// Uses of Block_copy/Block_release macros are rewritten:
34//
35//  c = Block_copy(b);
36//  Block_release(c);
37// ---->
38//  c = [b copy];
39//  <removed>
40//
41//===----------------------------------------------------------------------===//
42
43#include "Transforms.h"
44#include "Internals.h"
45#include "clang/AST/ASTContext.h"
46#include "clang/AST/Attr.h"
47#include "clang/AST/ParentMap.h"
48#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
49#include "clang/Basic/SourceManager.h"
50#include "clang/Lex/Lexer.h"
51#include "clang/Sema/SemaDiagnostic.h"
52#include "llvm/ADT/SmallString.h"
53
54using namespace clang;
55using namespace arcmt;
56using namespace trans;
57
58namespace {
59
60class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
61  MigrationPass &Pass;
62  IdentifierInfo *SelfII;
63  std::unique_ptr<ParentMap> StmtMap;
64  Decl *ParentD;
65  Stmt *Body;
66  mutable std::unique_ptr<ExprSet> Removables;
67
68public:
69  UnbridgedCastRewriter(MigrationPass &pass)
70    : Pass(pass), ParentD(nullptr), Body(nullptr) {
71    SelfII = &Pass.Ctx.Idents.get("self");
72  }
73
74  void transformBody(Stmt *body, Decl *ParentD) {
75    this->ParentD = ParentD;
76    Body = body;
77    StmtMap.reset(new ParentMap(body));
78    TraverseStmt(body);
79  }
80
81  bool TraverseBlockDecl(BlockDecl *D) {
82    // ParentMap does not enter into a BlockDecl to record its stmts, so use a
83    // new UnbridgedCastRewriter to handle the block.
84    UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D);
85    return true;
86  }
87
88  bool VisitCastExpr(CastExpr *E) {
89    if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
90        E->getCastKind() != CK_BitCast &&
91        E->getCastKind() != CK_AnyPointerToBlockPointerCast)
92      return true;
93
94    QualType castType = E->getType();
95    Expr *castExpr = E->getSubExpr();
96    QualType castExprType = castExpr->getType();
97
98    if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
99      return true;
100
101    bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
102    bool castRetainable = castType->isObjCIndirectLifetimeType();
103    if (exprRetainable == castRetainable) return true;
104
105    if (castExpr->isNullPointerConstant(Pass.Ctx,
106                                        Expr::NPC_ValueDependentIsNull))
107      return true;
108
109    SourceLocation loc = castExpr->getExprLoc();
110    if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
111      return true;
112
113    if (castType->isObjCRetainableType())
114      transformNonObjCToObjCCast(E);
115    else
116      transformObjCToNonObjCCast(E);
117
118    return true;
119  }
120
121private:
122  void transformNonObjCToObjCCast(CastExpr *E) {
123    if (!E) return;
124
125    // Global vars are assumed that are cast as unretained.
126    if (isGlobalVar(E))
127      if (E->getSubExpr()->getType()->isPointerType()) {
128        castToObjCObject(E, /*retained=*/false);
129        return;
130      }
131
132    // If the cast is directly over the result of a Core Foundation function
133    // try to figure out whether it should be cast as retained or unretained.
134    Expr *inner = E->IgnoreParenCasts();
135    if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
136      if (FunctionDecl *FD = callE->getDirectCallee()) {
137        if (FD->hasAttr<CFReturnsRetainedAttr>()) {
138          castToObjCObject(E, /*retained=*/true);
139          return;
140        }
141        if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
142          castToObjCObject(E, /*retained=*/false);
143          return;
144        }
145        if (FD->isGlobal() &&
146            FD->getIdentifier() &&
147            ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
148                                   FD->getIdentifier()->getName())) {
149          StringRef fname = FD->getIdentifier()->getName();
150          if (fname.endswith("Retain") ||
151              fname.find("Create") != StringRef::npos ||
152              fname.find("Copy") != StringRef::npos) {
153            // Do not migrate to couple of bridge transfer casts which
154            // cancel each other out. Leave it unchanged so error gets user
155            // attention instead.
156            if (FD->getName() == "CFRetain" &&
157                FD->getNumParams() == 1 &&
158                FD->getParent()->isTranslationUnit() &&
159                FD->isExternallyVisible()) {
160              Expr *Arg = callE->getArg(0);
161              if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
162                const Expr *sub = ICE->getSubExpr();
163                QualType T = sub->getType();
164                if (T->isObjCObjectPointerType())
165                  return;
166              }
167            }
168            castToObjCObject(E, /*retained=*/true);
169            return;
170          }
171
172          if (fname.find("Get") != StringRef::npos) {
173            castToObjCObject(E, /*retained=*/false);
174            return;
175          }
176        }
177      }
178    }
179
180    // If returning an ivar or a member of an ivar from a +0 method, use
181    // a __bridge cast.
182    Expr *base = inner->IgnoreParenImpCasts();
183    while (isa<MemberExpr>(base))
184      base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
185    if (isa<ObjCIvarRefExpr>(base) &&
186        isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
187      if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
188        if (!method->hasAttr<NSReturnsRetainedAttr>()) {
189          castToObjCObject(E, /*retained=*/false);
190          return;
191        }
192      }
193    }
194  }
195
196  void castToObjCObject(CastExpr *E, bool retained) {
197    rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
198  }
199
200  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
201    Transaction Trans(Pass.TA);
202    rewriteToBridgedCast(E, Kind, Trans);
203  }
204
205  void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
206                            Transaction &Trans) {
207    TransformActions &TA = Pass.TA;
208
209    // We will remove the compiler diagnostic.
210    if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
211                          diag::err_arc_cast_requires_bridge,
212                          E->getLocStart())) {
213      Trans.abort();
214      return;
215    }
216
217    StringRef bridge;
218    switch(Kind) {
219    case OBC_Bridge:
220      bridge = "__bridge "; break;
221    case OBC_BridgeTransfer:
222      bridge = "__bridge_transfer "; break;
223    case OBC_BridgeRetained:
224      bridge = "__bridge_retained "; break;
225    }
226
227    TA.clearDiagnostic(diag::err_arc_mismatched_cast,
228                       diag::err_arc_cast_requires_bridge,
229                       E->getLocStart());
230    if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
231      if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
232        TA.insertAfterToken(CCE->getLParenLoc(), bridge);
233      } else {
234        SourceLocation insertLoc = E->getSubExpr()->getLocStart();
235        SmallString<128> newCast;
236        newCast += '(';
237        newCast += bridge;
238        newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
239        newCast += ')';
240
241        if (isa<ParenExpr>(E->getSubExpr())) {
242          TA.insert(insertLoc, newCast.str());
243        } else {
244          newCast += '(';
245          TA.insert(insertLoc, newCast.str());
246          TA.insertAfterToken(E->getLocEnd(), ")");
247        }
248      }
249    } else {
250      assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained);
251      SmallString<32> BridgeCall;
252
253      Expr *WrapE = E->getSubExpr();
254      SourceLocation InsertLoc = WrapE->getLocStart();
255
256      SourceManager &SM = Pass.Ctx.getSourceManager();
257      char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
258      if (Lexer::isIdentifierBodyChar(PrevChar, Pass.Ctx.getLangOpts()))
259        BridgeCall += ' ';
260
261      if (Kind == OBC_BridgeTransfer)
262        BridgeCall += "CFBridgingRelease";
263      else
264        BridgeCall += "CFBridgingRetain";
265
266      if (isa<ParenExpr>(WrapE)) {
267        TA.insert(InsertLoc, BridgeCall);
268      } else {
269        BridgeCall += '(';
270        TA.insert(InsertLoc, BridgeCall);
271        TA.insertAfterToken(WrapE->getLocEnd(), ")");
272      }
273    }
274  }
275
276  void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
277    Transaction Trans(Pass.TA);
278    Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
279    rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
280  }
281
282  void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
283    SourceManager &SM = Pass.Ctx.getSourceManager();
284    SourceLocation Loc = E->getExprLoc();
285    assert(Loc.isMacroID());
286    SourceLocation MacroBegin, MacroEnd;
287    std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc);
288    SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
289    SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
290    SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
291
292    Outer = SourceRange(MacroBegin, MacroEnd);
293    Inner = SourceRange(InnerBegin, InnerEnd);
294  }
295
296  void rewriteBlockCopyMacro(CastExpr *E) {
297    SourceRange OuterRange, InnerRange;
298    getBlockMacroRanges(E, OuterRange, InnerRange);
299
300    Transaction Trans(Pass.TA);
301    Pass.TA.replace(OuterRange, InnerRange);
302    Pass.TA.insert(InnerRange.getBegin(), "[");
303    Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
304    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
305                            diag::err_arc_cast_requires_bridge,
306                            OuterRange);
307  }
308
309  void removeBlockReleaseMacro(CastExpr *E) {
310    SourceRange OuterRange, InnerRange;
311    getBlockMacroRanges(E, OuterRange, InnerRange);
312
313    Transaction Trans(Pass.TA);
314    Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
315                            diag::err_arc_cast_requires_bridge,
316                            OuterRange);
317    if (!hasSideEffects(E, Pass.Ctx)) {
318      if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
319        return;
320    }
321    Pass.TA.replace(OuterRange, InnerRange);
322  }
323
324  bool tryRemoving(Expr *E) const {
325    if (!Removables) {
326      Removables.reset(new ExprSet);
327      collectRemovables(Body, *Removables);
328    }
329
330    if (Removables->count(E)) {
331      Pass.TA.removeStmt(E);
332      return true;
333    }
334
335    return false;
336  }
337
338  void transformObjCToNonObjCCast(CastExpr *E) {
339    SourceLocation CastLoc = E->getExprLoc();
340    if (CastLoc.isMacroID()) {
341      StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
342                                                    Pass.Ctx.getSourceManager(),
343                                                    Pass.Ctx.getLangOpts());
344      if (MacroName == "Block_copy") {
345        rewriteBlockCopyMacro(E);
346        return;
347      }
348      if (MacroName == "Block_release") {
349        removeBlockReleaseMacro(E);
350        return;
351      }
352    }
353
354    if (isSelf(E->getSubExpr()))
355      return rewriteToBridgedCast(E, OBC_Bridge);
356
357    CallExpr *callE;
358    if (isPassedToCFRetain(E, callE))
359      return rewriteCastForCFRetain(E, callE);
360
361    ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
362    if (family == OMF_retain)
363      return rewriteToBridgedCast(E, OBC_BridgeRetained);
364
365    if (family == OMF_autorelease || family == OMF_release) {
366      std::string err = "it is not safe to cast to '";
367      err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
368      err += "' the result of '";
369      err += family == OMF_autorelease ? "autorelease" : "release";
370      err += "' message; a __bridge cast may result in a pointer to a "
371          "destroyed object and a __bridge_retained may leak the object";
372      Pass.TA.reportError(err, E->getLocStart(),
373                          E->getSubExpr()->getSourceRange());
374      Stmt *parent = E;
375      do {
376        parent = StmtMap->getParentIgnoreParenImpCasts(parent);
377      } while (parent && isa<ExprWithCleanups>(parent));
378
379      if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
380        std::string note = "remove the cast and change return type of function "
381            "to '";
382        note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
383        note += "' to have the object automatically autoreleased";
384        Pass.TA.reportNote(note, retS->getLocStart());
385      }
386    }
387
388    Expr *subExpr = E->getSubExpr();
389
390    // Look through pseudo-object expressions.
391    if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
392      subExpr = pseudo->getResultExpr();
393      assert(subExpr && "no result for pseudo-object of non-void type?");
394    }
395
396    if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
397      if (implCE->getCastKind() == CK_ARCConsumeObject)
398        return rewriteToBridgedCast(E, OBC_BridgeRetained);
399      if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
400        return rewriteToBridgedCast(E, OBC_Bridge);
401    }
402
403    bool isConsumed = false;
404    if (isPassedToCParamWithKnownOwnership(E, isConsumed))
405      return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
406                                                : OBC_Bridge);
407  }
408
409  static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
410    E = E->IgnoreParenCasts();
411    if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
412      return ME->getMethodFamily();
413
414    return OMF_None;
415  }
416
417  bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
418    if ((callE = dyn_cast_or_null<CallExpr>(
419                                     StmtMap->getParentIgnoreParenImpCasts(E))))
420      if (FunctionDecl *
421            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
422        if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
423            FD->getParent()->isTranslationUnit() &&
424            FD->isExternallyVisible())
425          return true;
426
427    return false;
428  }
429
430  bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
431    if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
432                                     StmtMap->getParentIgnoreParenImpCasts(E)))
433      if (FunctionDecl *
434            FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
435        unsigned i = 0;
436        for (unsigned e = callE->getNumArgs(); i != e; ++i) {
437          Expr *arg = callE->getArg(i);
438          if (arg == E || arg->IgnoreParenImpCasts() == E)
439            break;
440        }
441        if (i < callE->getNumArgs() && i < FD->getNumParams()) {
442          ParmVarDecl *PD = FD->getParamDecl(i);
443          if (PD->hasAttr<CFConsumedAttr>()) {
444            isConsumed = true;
445            return true;
446          }
447        }
448      }
449
450    return false;
451  }
452
453  bool isSelf(Expr *E) const {
454    E = E->IgnoreParenLValueCasts();
455    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
456      if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
457        if (IPD->getIdentifier() == SelfII)
458          return true;
459
460    return false;
461  }
462};
463
464} // end anonymous namespace
465
466void trans::rewriteUnbridgedCasts(MigrationPass &pass) {
467  BodyTransform<UnbridgedCastRewriter> trans(pass);
468  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
469}
470