xref: /minix3/external/bsd/llvm/dist/clang/lib/ARCMigrate/TransAPIUses.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // checkAPIUses:
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc // Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
13f4a2713aSLionel Sambuc //
14f4a2713aSLionel Sambuc // - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
15f4a2713aSLionel Sambuc //   with __unsafe_unretained objects.
16f4a2713aSLionel Sambuc // - Calling -zone gets replaced with 'nil'.
17f4a2713aSLionel Sambuc //
18f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
19f4a2713aSLionel Sambuc 
20f4a2713aSLionel Sambuc #include "Transforms.h"
21f4a2713aSLionel Sambuc #include "Internals.h"
22f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
23f4a2713aSLionel Sambuc #include "clang/Sema/SemaDiagnostic.h"
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc using namespace clang;
26f4a2713aSLionel Sambuc using namespace arcmt;
27f4a2713aSLionel Sambuc using namespace trans;
28f4a2713aSLionel Sambuc 
29f4a2713aSLionel Sambuc namespace {
30f4a2713aSLionel Sambuc 
31f4a2713aSLionel Sambuc class APIChecker : public RecursiveASTVisitor<APIChecker> {
32f4a2713aSLionel Sambuc   MigrationPass &Pass;
33f4a2713aSLionel Sambuc 
34f4a2713aSLionel Sambuc   Selector getReturnValueSel, setReturnValueSel;
35f4a2713aSLionel Sambuc   Selector getArgumentSel, setArgumentSel;
36f4a2713aSLionel Sambuc 
37f4a2713aSLionel Sambuc   Selector zoneSel;
38f4a2713aSLionel Sambuc public:
APIChecker(MigrationPass & pass)39f4a2713aSLionel Sambuc   APIChecker(MigrationPass &pass) : Pass(pass) {
40f4a2713aSLionel Sambuc     SelectorTable &sels = Pass.Ctx.Selectors;
41f4a2713aSLionel Sambuc     IdentifierTable &ids = Pass.Ctx.Idents;
42f4a2713aSLionel Sambuc     getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
43f4a2713aSLionel Sambuc     setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
44f4a2713aSLionel Sambuc 
45f4a2713aSLionel Sambuc     IdentifierInfo *selIds[2];
46f4a2713aSLionel Sambuc     selIds[0] = &ids.get("getArgument");
47f4a2713aSLionel Sambuc     selIds[1] = &ids.get("atIndex");
48f4a2713aSLionel Sambuc     getArgumentSel = sels.getSelector(2, selIds);
49f4a2713aSLionel Sambuc     selIds[0] = &ids.get("setArgument");
50f4a2713aSLionel Sambuc     setArgumentSel = sels.getSelector(2, selIds);
51f4a2713aSLionel Sambuc 
52f4a2713aSLionel Sambuc     zoneSel = sels.getNullarySelector(&ids.get("zone"));
53f4a2713aSLionel Sambuc   }
54f4a2713aSLionel Sambuc 
VisitObjCMessageExpr(ObjCMessageExpr * E)55f4a2713aSLionel Sambuc   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
56f4a2713aSLionel Sambuc     // NSInvocation.
57f4a2713aSLionel Sambuc     if (E->isInstanceMessage() &&
58f4a2713aSLionel Sambuc         E->getReceiverInterface() &&
59f4a2713aSLionel Sambuc         E->getReceiverInterface()->getName() == "NSInvocation") {
60f4a2713aSLionel Sambuc       StringRef selName;
61f4a2713aSLionel Sambuc       if (E->getSelector() == getReturnValueSel)
62f4a2713aSLionel Sambuc         selName = "getReturnValue";
63f4a2713aSLionel Sambuc       else if (E->getSelector() == setReturnValueSel)
64f4a2713aSLionel Sambuc         selName = "setReturnValue";
65f4a2713aSLionel Sambuc       else if (E->getSelector() == getArgumentSel)
66f4a2713aSLionel Sambuc         selName = "getArgument";
67f4a2713aSLionel Sambuc       else if (E->getSelector() == setArgumentSel)
68f4a2713aSLionel Sambuc         selName = "setArgument";
69*0a6a1f1dSLionel Sambuc       else
70f4a2713aSLionel Sambuc         return true;
71f4a2713aSLionel Sambuc 
72f4a2713aSLionel Sambuc       Expr *parm = E->getArg(0)->IgnoreParenCasts();
73f4a2713aSLionel Sambuc       QualType pointee = parm->getType()->getPointeeType();
74f4a2713aSLionel Sambuc       if (pointee.isNull())
75f4a2713aSLionel Sambuc         return true;
76f4a2713aSLionel Sambuc 
77*0a6a1f1dSLionel Sambuc       if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone)
78*0a6a1f1dSLionel Sambuc         Pass.TA.report(parm->getLocStart(),
79*0a6a1f1dSLionel Sambuc                        diag::err_arcmt_nsinvocation_ownership,
80*0a6a1f1dSLionel Sambuc                        parm->getSourceRange())
81*0a6a1f1dSLionel Sambuc             << selName;
82*0a6a1f1dSLionel Sambuc 
83f4a2713aSLionel Sambuc       return true;
84f4a2713aSLionel Sambuc     }
85f4a2713aSLionel Sambuc 
86f4a2713aSLionel Sambuc     // -zone.
87f4a2713aSLionel Sambuc     if (E->isInstanceMessage() &&
88f4a2713aSLionel Sambuc         E->getInstanceReceiver() &&
89f4a2713aSLionel Sambuc         E->getSelector() == zoneSel &&
90f4a2713aSLionel Sambuc         Pass.TA.hasDiagnostic(diag::err_unavailable,
91f4a2713aSLionel Sambuc                               diag::err_unavailable_message,
92f4a2713aSLionel Sambuc                               E->getSelectorLoc(0))) {
93f4a2713aSLionel Sambuc       // Calling -zone is meaningless in ARC, change it to nil.
94f4a2713aSLionel Sambuc       Transaction Trans(Pass.TA);
95f4a2713aSLionel Sambuc       Pass.TA.clearDiagnostic(diag::err_unavailable,
96f4a2713aSLionel Sambuc                               diag::err_unavailable_message,
97f4a2713aSLionel Sambuc                               E->getSelectorLoc(0));
98f4a2713aSLionel Sambuc       Pass.TA.replace(E->getSourceRange(), getNilString(Pass.Ctx));
99f4a2713aSLionel Sambuc     }
100f4a2713aSLionel Sambuc     return true;
101f4a2713aSLionel Sambuc   }
102f4a2713aSLionel Sambuc };
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc } // anonymous namespace
105f4a2713aSLionel Sambuc 
checkAPIUses(MigrationPass & pass)106f4a2713aSLionel Sambuc void trans::checkAPIUses(MigrationPass &pass) {
107f4a2713aSLionel Sambuc   APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
108f4a2713aSLionel Sambuc }
109