diff options
author | 2020-08-03 14:31:31 +0000 | |
---|---|---|
committer | 2020-08-03 14:31:31 +0000 | |
commit | e5dd70708596ae51455a0ffa086a00c5b29f8583 (patch) | |
tree | 5d676f27b570bacf71e786c3b5cff3e6f6679b59 /gnu/llvm/clang/lib/ARCMigrate/TransAPIUses.cpp | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.tar.xz wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/clang/lib/ARCMigrate/TransAPIUses.cpp')
-rw-r--r-- | gnu/llvm/clang/lib/ARCMigrate/TransAPIUses.cpp | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/gnu/llvm/clang/lib/ARCMigrate/TransAPIUses.cpp b/gnu/llvm/clang/lib/ARCMigrate/TransAPIUses.cpp new file mode 100644 index 00000000000..638850dcf9e --- /dev/null +++ b/gnu/llvm/clang/lib/ARCMigrate/TransAPIUses.cpp @@ -0,0 +1,107 @@ +//===--- 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()); +} |