clang  3.9.0svn
TransAPIUses.cpp
Go to the documentation of this file.
1 //===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // checkAPIUses:
11 //
12 // Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
13 //
14 // - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
15 // with __unsafe_unretained objects.
16 // - Calling -zone gets replaced with 'nil'.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "Transforms.h"
21 #include "Internals.h"
22 #include "clang/AST/ASTContext.h"
24 
25 using namespace clang;
26 using namespace arcmt;
27 using namespace trans;
28 
29 namespace {
30 
31 class APIChecker : public RecursiveASTVisitor<APIChecker> {
32  MigrationPass &Pass;
33 
34  Selector getReturnValueSel, setReturnValueSel;
35  Selector getArgumentSel, setArgumentSel;
36 
37  Selector zoneSel;
38 public:
39  APIChecker(MigrationPass &pass) : Pass(pass) {
40  SelectorTable &sels = Pass.Ctx.Selectors;
41  IdentifierTable &ids = Pass.Ctx.Idents;
42  getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
43  setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
44 
45  IdentifierInfo *selIds[2];
46  selIds[0] = &ids.get("getArgument");
47  selIds[1] = &ids.get("atIndex");
48  getArgumentSel = sels.getSelector(2, selIds);
49  selIds[0] = &ids.get("setArgument");
50  setArgumentSel = sels.getSelector(2, selIds);
51 
52  zoneSel = sels.getNullarySelector(&ids.get("zone"));
53  }
54 
55  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
56  // NSInvocation.
57  if (E->isInstanceMessage() &&
58  E->getReceiverInterface() &&
59  E->getReceiverInterface()->getName() == "NSInvocation") {
60  StringRef selName;
61  if (E->getSelector() == getReturnValueSel)
62  selName = "getReturnValue";
63  else if (E->getSelector() == setReturnValueSel)
64  selName = "setReturnValue";
65  else if (E->getSelector() == getArgumentSel)
66  selName = "getArgument";
67  else if (E->getSelector() == setArgumentSel)
68  selName = "setArgument";
69  else
70  return true;
71 
72  Expr *parm = E->getArg(0)->IgnoreParenCasts();
73  QualType pointee = parm->getType()->getPointeeType();
74  if (pointee.isNull())
75  return true;
76 
78  Pass.TA.report(parm->getLocStart(),
79  diag::err_arcmt_nsinvocation_ownership,
80  parm->getSourceRange())
81  << selName;
82 
83  return true;
84  }
85 
86  // -zone.
87  if (E->isInstanceMessage() &&
88  E->getInstanceReceiver() &&
89  E->getSelector() == zoneSel &&
90  Pass.TA.hasDiagnostic(diag::err_unavailable,
91  diag::err_unavailable_message,
92  E->getSelectorLoc(0))) {
93  // Calling -zone is meaningless in ARC, change it to nil.
94  Transaction Trans(Pass.TA);
95  Pass.TA.clearDiagnostic(diag::err_unavailable,
96  diag::err_unavailable_message,
97  E->getSelectorLoc(0));
98  Pass.TA.replace(E->getSourceRange(), getNilString(Pass));
99  }
100  return true;
101  }
102 };
103 
104 } // anonymous namespace
105 
107  APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
108 }
Defines the clang::ASTContext interface.
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:237
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
Definition: Type.h:598
Selector getUnarySelector(IdentifierInfo *ID)
One of these records is kept for each identifier that is lexed.
This table allows us to fully hide how we implement multi-keyword caching.
DiagnosticBuilder report(SourceLocation loc, unsigned diagId, SourceRange range=SourceRange())
IdentifierTable & Idents
Definition: ASTContext.h:455
Selector getNullarySelector(IdentifierInfo *ID)
Selector getSelector() const
Definition: ExprObjC.cpp:306
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2326
A class that does preorder depth-first traversal on the entire Clang AST and visits each node...
This object can be modified without requiring retains or releases.
Definition: Type.h:138
StringRef getNilString(MigrationPass &Pass)
Returns "nil" or "0" if &#39;nil&#39; macro is not actually defined.
Definition: Transforms.cpp:214
bool isInstanceMessage() const
Determine whether this is an instance message to either a computed object or to super.
Definition: ExprObjC.h:1143
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: Type.h:1009
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:415
Expr - This represents one expression.
Definition: Expr.h:105
Implements an efficient mapping from strings to IdentifierInfo nodes.
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:879
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:327
void checkAPIUses(MigrationPass &pass)
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:860
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: ExprObjC.h:1290
SelectorTable & Selectors
Definition: ASTContext.h:456
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1155
QualType getType() const
Definition: Expr.h:126
Dataflow Directional Tag Classes.
SourceLocation getSelectorLoc(unsigned Index) const
Definition: ExprObjC.h:1318
Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV)
Can create any sort of selector.
void replace(SourceRange range, StringRef text)
TransformActions & TA
Definition: Internals.h:151
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:665
bool hasDiagnostic(unsigned ID, SourceRange range)
Definition: Internals.h:88