Path: blob/main/contrib/llvm-project/clang/lib/ARCMigrate/TransAPIUses.cpp
35236 views
//===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// checkAPIUses:9//10// Emits error/fix with some API uses that are obsolete or not safe in ARC mode:11//12// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe13// with __unsafe_unretained objects.14// - Calling -zone gets replaced with 'nil'.15//16//===----------------------------------------------------------------------===//1718#include "Transforms.h"19#include "Internals.h"20#include "clang/AST/ASTContext.h"21#include "clang/Sema/SemaDiagnostic.h"2223using namespace clang;24using namespace arcmt;25using namespace trans;2627namespace {2829class APIChecker : public RecursiveASTVisitor<APIChecker> {30MigrationPass &Pass;3132Selector getReturnValueSel, setReturnValueSel;33Selector getArgumentSel, setArgumentSel;3435Selector zoneSel;36public:37APIChecker(MigrationPass &pass) : Pass(pass) {38SelectorTable &sels = Pass.Ctx.Selectors;39IdentifierTable &ids = Pass.Ctx.Idents;40getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));41setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));4243const IdentifierInfo *selIds[2];44selIds[0] = &ids.get("getArgument");45selIds[1] = &ids.get("atIndex");46getArgumentSel = sels.getSelector(2, selIds);47selIds[0] = &ids.get("setArgument");48setArgumentSel = sels.getSelector(2, selIds);4950zoneSel = sels.getNullarySelector(&ids.get("zone"));51}5253bool VisitObjCMessageExpr(ObjCMessageExpr *E) {54// NSInvocation.55if (E->isInstanceMessage() &&56E->getReceiverInterface() &&57E->getReceiverInterface()->getName() == "NSInvocation") {58StringRef selName;59if (E->getSelector() == getReturnValueSel)60selName = "getReturnValue";61else if (E->getSelector() == setReturnValueSel)62selName = "setReturnValue";63else if (E->getSelector() == getArgumentSel)64selName = "getArgument";65else if (E->getSelector() == setArgumentSel)66selName = "setArgument";67else68return true;6970Expr *parm = E->getArg(0)->IgnoreParenCasts();71QualType pointee = parm->getType()->getPointeeType();72if (pointee.isNull())73return true;7475if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone)76Pass.TA.report(parm->getBeginLoc(),77diag::err_arcmt_nsinvocation_ownership,78parm->getSourceRange())79<< selName;8081return true;82}8384// -zone.85if (E->isInstanceMessage() &&86E->getInstanceReceiver() &&87E->getSelector() == zoneSel &&88Pass.TA.hasDiagnostic(diag::err_unavailable,89diag::err_unavailable_message,90E->getSelectorLoc(0))) {91// Calling -zone is meaningless in ARC, change it to nil.92Transaction Trans(Pass.TA);93Pass.TA.clearDiagnostic(diag::err_unavailable,94diag::err_unavailable_message,95E->getSelectorLoc(0));96Pass.TA.replace(E->getSourceRange(), getNilString(Pass));97}98return true;99}100};101102} // anonymous namespace103104void trans::checkAPIUses(MigrationPass &pass) {105APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());106}107108109