1e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===--- TransGCCalls.cpp - Tranformations to ARC mode --------------------===//
2e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//
3e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
4e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//
5e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
6e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis// License. See LICENSE.TXT for details.
7e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//
8e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
9e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
10e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis#include "Transforms.h"
11e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis#include "Internals.h"
12471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h"
13e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis#include "clang/Sema/SemaDiagnostic.h"
14e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
15e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisusing namespace clang;
16e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisusing namespace arcmt;
17e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisusing namespace trans;
18e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
19e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisnamespace {
20e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
21e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisclass GCCollectableCallsChecker :
22e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                         public RecursiveASTVisitor<GCCollectableCallsChecker> {
23e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  MigrationContext &MigrateCtx;
24e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  IdentifierInfo *NSMakeCollectableII;
2581eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis  IdentifierInfo *CFMakeCollectableII;
26e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
27e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidispublic:
28facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer  GCCollectableCallsChecker(MigrationContext &ctx)
29facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer    : MigrateCtx(ctx) {
30f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
3181eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis    NSMakeCollectableII = &Ids.get("NSMakeCollectable");
3281eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis    CFMakeCollectableII = &Ids.get("CFMakeCollectable");
33e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  }
34e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
35f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
36f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
37e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  bool VisitCallExpr(CallExpr *E) {
38f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    TransformActions &TA = MigrateCtx.Pass.TA;
3981eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis
401fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
41b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian      if (MigrateCtx.Pass.noNSAllocReallocError())
42b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian        TA.reportWarning("call returns pointer to GC managed memory; "
43b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian                       "it will become unmanaged in ARC",
44b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian                       E->getLocStart(), E->getSourceRange());
45b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian      else
46b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian        TA.reportError("call returns pointer to GC managed memory; "
47b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian                       "it will become unmanaged in ARC",
48b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396Fariborz Jahanian                       E->getLocStart(), E->getSourceRange());
491fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      return true;
501fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    }
511fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
52e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
53e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
54e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
5581eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis        if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
5681eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis          return true;
5781eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis
5881eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis        if (FD->getIdentifier() == NSMakeCollectableII) {
59e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis          Transaction Trans(TA);
60e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis          TA.clearDiagnostic(diag::err_unavailable,
61e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                             diag::err_unavailable_message,
620d579b6a3f555c0e37e84e517c81eb9244fef099Argyrios Kyrtzidis                             diag::err_ovl_deleted_call, // ObjC++
63e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                             DRE->getSourceRange());
64e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis          TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
6581eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis
6681eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis        } else if (FD->getIdentifier() == CFMakeCollectableII) {
6781eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis          TA.reportError("CFMakeCollectable will leak the object that it "
6881eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis                         "receives in ARC", DRE->getLocation(),
6981eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis                         DRE->getSourceRange());
70e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis        }
71e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      }
72e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    }
73e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
74e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    return true;
75e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  }
76e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis};
77e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
78e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis} // anonymous namespace
79e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
80e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisvoid GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
81facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer  GCCollectableCallsChecker(BodyCtx.getMigrationContext())
82e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                                            .TraverseStmt(BodyCtx.getTopStmt());
83e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
84