1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- TransGCCalls.cpp - Transformations 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())) {
416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      TA.report(E->getLocStart(), diag::warn_arcmt_nsalloc_realloc,
42651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                E->getSourceRange());
431fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis      return true;
441fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis    }
451fe4203ca05d0a3283efc8a2e8c01ecdf78fbf2eArgyrios Kyrtzidis
46e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
47e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
48e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
4981eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis        if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
5081eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis          return true;
5181eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis
5281eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis        if (FD->getIdentifier() == NSMakeCollectableII) {
53e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis          Transaction Trans(TA);
54e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis          TA.clearDiagnostic(diag::err_unavailable,
55e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                             diag::err_unavailable_message,
560d579b6a3f555c0e37e84e517c81eb9244fef099Argyrios Kyrtzidis                             diag::err_ovl_deleted_call, // ObjC++
57e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                             DRE->getSourceRange());
58e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis          TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
5981eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis
6081eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis        } else if (FD->getIdentifier() == CFMakeCollectableII) {
6181eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis          TA.reportError("CFMakeCollectable will leak the object that it "
6281eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis                         "receives in ARC", DRE->getLocation(),
6381eecde879712729712966b60c0cb1540b41293bArgyrios Kyrtzidis                         DRE->getSourceRange());
64e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis        }
65e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis      }
66e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    }
67e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
68e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis    return true;
69e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  }
70e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis};
71e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
72e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis} // anonymous namespace
73e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis
74e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidisvoid GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
75facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer  GCCollectableCallsChecker(BodyCtx.getMigrationContext())
76e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis                                            .TraverseStmt(BodyCtx.getTopStmt());
77e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis}
78