Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// checkAPIUses:
10
//
11
// Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
12
//
13
// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
14
//   with __unsafe_unretained objects.
15
// - Calling -zone gets replaced with 'nil'.
16
//
17
//===----------------------------------------------------------------------===//
18
19
#include "Transforms.h"
20
#include "Internals.h"
21
#include "clang/AST/ASTContext.h"
22
#include "clang/Sema/SemaDiagnostic.h"
23
24
using namespace clang;
25
using namespace arcmt;
26
using namespace trans;
27
28
namespace {
29
30
class APIChecker : public RecursiveASTVisitor<APIChecker> {
31
  MigrationPass &Pass;
32
33
  Selector getReturnValueSel, setReturnValueSel;
34
  Selector getArgumentSel, setArgumentSel;
35
36
  Selector zoneSel;
37
public:
38
85
  APIChecker(MigrationPass &pass) : Pass(pass) {
39
85
    SelectorTable &sels = Pass.Ctx.Selectors;
40
85
    IdentifierTable &ids = Pass.Ctx.Idents;
41
85
    getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
42
85
    setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
43
85
44
85
    IdentifierInfo *selIds[2];
45
85
    selIds[0] = &ids.get("getArgument");
46
85
    selIds[1] = &ids.get("atIndex");
47
85
    getArgumentSel = sels.getSelector(2, selIds);
48
85
    selIds[0] = &ids.get("setArgument");
49
85
    setArgumentSel = sels.getSelector(2, selIds);
50
85
51
85
    zoneSel = sels.getNullarySelector(&ids.get("zone"));
52
85
  }
53
54
495
  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
55
495
    // NSInvocation.
56
495
    if (E->isInstanceMessage() &&
57
495
        
E->getReceiverInterface()417
&&
58
495
        
E->getReceiverInterface()->getName() == "NSInvocation"276
) {
59
16
      StringRef selName;
60
16
      if (E->getSelector() == getReturnValueSel)
61
4
        selName = "getReturnValue";
62
12
      else if (E->getSelector() == setReturnValueSel)
63
4
        selName = "setReturnValue";
64
8
      else if (E->getSelector() == getArgumentSel)
65
4
        selName = "getArgument";
66
4
      else if (E->getSelector() == setArgumentSel)
67
4
        selName = "setArgument";
68
0
      else
69
0
        return true;
70
16
71
16
      Expr *parm = E->getArg(0)->IgnoreParenCasts();
72
16
      QualType pointee = parm->getType()->getPointeeType();
73
16
      if (pointee.isNull())
74
0
        return true;
75
16
76
16
      if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone)
77
8
        Pass.TA.report(parm->getBeginLoc(),
78
8
                       diag::err_arcmt_nsinvocation_ownership,
79
8
                       parm->getSourceRange())
80
8
            << selName;
81
16
82
16
      return true;
83
16
    }
84
479
85
479
    // -zone.
86
479
    if (E->isInstanceMessage() &&
87
479
        
E->getInstanceReceiver()401
&&
88
479
        
E->getSelector() == zoneSel393
&&
89
479
        Pass.TA.hasDiagnostic(diag::err_unavailable,
90
2
                              diag::err_unavailable_message,
91
2
                              E->getSelectorLoc(0))) {
92
2
      // Calling -zone is meaningless in ARC, change it to nil.
93
2
      Transaction Trans(Pass.TA);
94
2
      Pass.TA.clearDiagnostic(diag::err_unavailable,
95
2
                              diag::err_unavailable_message,
96
2
                              E->getSelectorLoc(0));
97
2
      Pass.TA.replace(E->getSourceRange(), getNilString(Pass));
98
2
    }
99
479
    return true;
100
479
  }
101
};
102
103
} // anonymous namespace
104
105
85
void trans::checkAPIUses(MigrationPass &pass) {
106
85
  APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
107
85
}