123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- //===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // checkAPIUses:
- //
- // Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
- //
- // - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
- // with __unsafe_unretained objects.
- // - Calling -zone gets replaced with 'nil'.
- //
- //===----------------------------------------------------------------------===//
- #include "Transforms.h"
- #include "Internals.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/Sema/SemaDiagnostic.h"
- using namespace clang;
- using namespace arcmt;
- using namespace trans;
- namespace {
- class APIChecker : public RecursiveASTVisitor<APIChecker> {
- MigrationPass &Pass;
- Selector getReturnValueSel, setReturnValueSel;
- Selector getArgumentSel, setArgumentSel;
- Selector zoneSel;
- public:
- APIChecker(MigrationPass &pass) : Pass(pass) {
- SelectorTable &sels = Pass.Ctx.Selectors;
- IdentifierTable &ids = Pass.Ctx.Idents;
- getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
- setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
- IdentifierInfo *selIds[2];
- selIds[0] = &ids.get("getArgument");
- selIds[1] = &ids.get("atIndex");
- getArgumentSel = sels.getSelector(2, selIds);
- selIds[0] = &ids.get("setArgument");
- setArgumentSel = sels.getSelector(2, selIds);
- zoneSel = sels.getNullarySelector(&ids.get("zone"));
- }
- bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- // NSInvocation.
- if (E->isInstanceMessage() &&
- E->getReceiverInterface() &&
- E->getReceiverInterface()->getName() == "NSInvocation") {
- StringRef selName;
- if (E->getSelector() == getReturnValueSel)
- selName = "getReturnValue";
- else if (E->getSelector() == setReturnValueSel)
- selName = "setReturnValue";
- else if (E->getSelector() == getArgumentSel)
- selName = "getArgument";
- else if (E->getSelector() == setArgumentSel)
- selName = "setArgument";
- else
- return true;
- Expr *parm = E->getArg(0)->IgnoreParenCasts();
- QualType pointee = parm->getType()->getPointeeType();
- if (pointee.isNull())
- return true;
- if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone)
- Pass.TA.report(parm->getBeginLoc(),
- diag::err_arcmt_nsinvocation_ownership,
- parm->getSourceRange())
- << selName;
- return true;
- }
- // -zone.
- if (E->isInstanceMessage() &&
- E->getInstanceReceiver() &&
- E->getSelector() == zoneSel &&
- Pass.TA.hasDiagnostic(diag::err_unavailable,
- diag::err_unavailable_message,
- E->getSelectorLoc(0))) {
- // Calling -zone is meaningless in ARC, change it to nil.
- Transaction Trans(Pass.TA);
- Pass.TA.clearDiagnostic(diag::err_unavailable,
- diag::err_unavailable_message,
- E->getSelectorLoc(0));
- Pass.TA.replace(E->getSourceRange(), getNilString(Pass));
- }
- return true;
- }
- };
- } // anonymous namespace
- void trans::checkAPIUses(MigrationPass &pass) {
- APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
- }
|