mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-05 12:51:16 +00:00
42aa21222d
This starts to switch ARCMT to use proper diagnostic messages. The old use was based on incorrect example code from the documentation. The logic of the previous report() functions has been retained to support any external consumers that might be intercepting diagnostic messages through the old interface. Note that the change in test/Misc/warning-flags.c isn't a new warning without a flag, rather one that was previously invisible to the test. Adding a flag might be a good idea though. llvm-svn: 200124
109 lines
3.5 KiB
C++
109 lines
3.5 KiB
C++
//===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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->getLocStart(),
|
|
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.Ctx));
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
void trans::checkAPIUses(MigrationPass &pass) {
|
|
APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
|
|
}
|