1accaf19bc1129c0273ec50dba52318e60bc29103Benjamin Kramer//===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===// 2fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// 3fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// The LLVM Compiler Infrastructure 4fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// 5fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source 6fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// License. See LICENSE.TXT for details. 7fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// 8fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis//===----------------------------------------------------------------------===// 9fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// 10fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// checkAPIUses: 11fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// 1218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis// Emits error/fix with some API uses that are obsolete or not safe in ARC mode: 13fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// 14fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe 15fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// with __unsafe_unretained objects. 1618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis// - Calling -zone gets replaced with 'nil'. 17fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis// 18fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis//===----------------------------------------------------------------------===// 19fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 20fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis#include "Transforms.h" 21fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis#include "Internals.h" 22471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h" 2318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis#include "clang/Sema/SemaDiagnostic.h" 24fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 25fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidisusing namespace clang; 26fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidisusing namespace arcmt; 27fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidisusing namespace trans; 28fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 29fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidisnamespace { 30fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 31fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidisclass APIChecker : public RecursiveASTVisitor<APIChecker> { 32fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis MigrationPass &Pass; 3305fdf9bc3f5089db291484e4ad9880aa432db9f4Argyrios Kyrtzidis 34fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis Selector getReturnValueSel, setReturnValueSel; 35fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis Selector getArgumentSel, setArgumentSel; 36fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 3718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Selector zoneSel; 38fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidispublic: 39fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis APIChecker(MigrationPass &pass) : Pass(pass) { 40fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis SelectorTable &sels = Pass.Ctx.Selectors; 41fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis IdentifierTable &ids = Pass.Ctx.Idents; 42fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue")); 43fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue")); 44fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 45fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis IdentifierInfo *selIds[2]; 46fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis selIds[0] = &ids.get("getArgument"); 47fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis selIds[1] = &ids.get("atIndex"); 48fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis getArgumentSel = sels.getSelector(2, selIds); 49fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis selIds[0] = &ids.get("setArgument"); 50fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis setArgumentSel = sels.getSelector(2, selIds); 5105fdf9bc3f5089db291484e4ad9880aa432db9f4Argyrios Kyrtzidis 5218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis zoneSel = sels.getNullarySelector(&ids.get("zone")); 53fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis } 54fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 55fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 5618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis // NSInvocation. 57fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis if (E->isInstanceMessage() && 58fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis E->getReceiverInterface() && 59fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis E->getReceiverInterface()->getName() == "NSInvocation") { 60fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis StringRef selName; 61fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis if (E->getSelector() == getReturnValueSel) 62fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis selName = "getReturnValue"; 63fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis else if (E->getSelector() == setReturnValueSel) 64fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis selName = "setReturnValue"; 65fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis else if (E->getSelector() == getArgumentSel) 66fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis selName = "getArgument"; 67fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis else if (E->getSelector() == setArgumentSel) 68fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis selName = "setArgument"; 69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else 70fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis return true; 71fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 72fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis Expr *parm = E->getArg(0)->IgnoreParenCasts(); 73fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis QualType pointee = parm->getType()->getPointeeType(); 74fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis if (pointee.isNull()) 75fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis return true; 76fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone) 78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Pass.TA.report(parm->getLocStart(), 79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag::err_arcmt_nsinvocation_ownership, 80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines parm->getSourceRange()) 81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << selName; 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 83fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis return true; 84fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis } 85fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 8618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis // -zone. 8718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis if (E->isInstanceMessage() && 8818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis E->getInstanceReceiver() && 8918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis E->getSelector() == zoneSel && 9018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.hasDiagnostic(diag::err_unavailable, 9118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis diag::err_unavailable_message, 92f4d02398936c0fdc9fe981348519fbc323f24ad0Argyrios Kyrtzidis E->getSelectorLoc(0))) { 9318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis // Calling -zone is meaningless in ARC, change it to nil. 9418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Transaction Trans(Pass.TA); 9518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.clearDiagnostic(diag::err_unavailable, 9618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis diag::err_unavailable_message, 97f4d02398936c0fdc9fe981348519fbc323f24ad0Argyrios Kyrtzidis E->getSelectorLoc(0)); 9818fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis Pass.TA.replace(E->getSourceRange(), getNilString(Pass.Ctx)); 9918fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis } 100fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis return true; 101fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis } 102fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis}; 103fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 104fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis} // anonymous namespace 105fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis 106fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidisvoid trans::checkAPIUses(MigrationPass &pass) { 107fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 108fd10398c10ffdcbdeb1e3e299c74d70e689f503cArgyrios Kyrtzidis} 109