Coverage Report

Created: 2018-07-22 10:17

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
Line
Count
Source (jump to first uncovered line)
1
//===- ObjCRuntime.h - Objective-C Runtime Configuration --------*- C++ -*-===//
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
/// \file
11
/// Defines types useful for describing an Objective-C runtime.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H
16
#define LLVM_CLANG_BASIC_OBJCRUNTIME_H
17
18
#include "clang/Basic/LLVM.h"
19
#include "llvm/ADT/StringRef.h"
20
#include "llvm/ADT/Triple.h"
21
#include "llvm/Support/ErrorHandling.h"
22
#include "llvm/Support/VersionTuple.h"
23
#include <string>
24
25
namespace clang {
26
27
/// The basic abstraction for the target Objective-C runtime.
28
class ObjCRuntime {
29
public:
30
  /// The basic Objective-C runtimes that we know about.
31
  enum Kind {
32
    /// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS
33
    /// X platforms that use the non-fragile ABI; the version is a
34
    /// release of that OS.
35
    MacOSX,
36
37
    /// 'macosx-fragile' is the Apple-provided NeXT-derived runtime on
38
    /// Mac OS X platforms that use the fragile ABI; the version is a
39
    /// release of that OS.
40
    FragileMacOSX,
41
42
    /// 'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS
43
    /// simulator;  it is always non-fragile.  The version is a release
44
    /// version of iOS.
45
    iOS,
46
47
    /// 'watchos' is a variant of iOS for Apple's watchOS. The version
48
    /// is a release version of watchOS.
49
    WatchOS,
50
51
    /// 'gcc' is the Objective-C runtime shipped with GCC, implementing a
52
    /// fragile Objective-C ABI
53
    GCC,
54
55
    /// 'gnustep' is the modern non-fragile GNUstep runtime.
56
    GNUstep,
57
58
    /// 'objfw' is the Objective-C runtime included in ObjFW
59
    ObjFW
60
  };
61
62
private:
63
  Kind TheKind = MacOSX;
64
  VersionTuple Version;
65
66
public:
67
  /// A bogus initialization of the runtime.
68
983k
  ObjCRuntime() = default;
69
  ObjCRuntime(Kind kind, const VersionTuple &version)
70
29.9k
      : TheKind(kind), Version(version) {}
71
72
0
  void set(Kind kind, VersionTuple version) {
73
0
    TheKind = kind;
74
0
    Version = version;
75
0
  }
76
77
5.06M
  Kind getKind() const { return TheKind; }
78
73.2k
  const VersionTuple &getVersion() const { return Version; }
79
80
  /// Does this runtime follow the set of implied behaviors for a
81
  /// "non-fragile" ABI?
82
3.37M
  bool isNonFragile() const {
83
3.37M
    switch (getKind()) {
84
3.37M
    
case FragileMacOSX: return false2.38k
;
85
3.37M
    
case GCC: return false6.95k
;
86
3.37M
    
case MacOSX: return true3.31M
;
87
3.37M
    
case GNUstep: return true1.70k
;
88
3.37M
    
case ObjFW: return true80
;
89
3.37M
    
case iOS: return true48.0k
;
90
3.37M
    
case WatchOS: return true56
;
91
0
    }
92
0
    llvm_unreachable("bad kind");
93
0
  }
94
95
  /// The inverse of isNonFragile():  does this runtime follow the set of
96
  /// implied behaviors for a "fragile" ABI?
97
157k
  bool isFragile() const { return !isNonFragile(); }
98
99
  /// The default dispatch mechanism to use for the specified architecture
100
17.9k
  bool isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch) {
101
17.9k
    // The GNUstep runtime uses a newer dispatch method by default from
102
17.9k
    // version 1.6 onwards
103
17.9k
    if (getKind() == GNUstep && 
getVersion() >= VersionTuple(1, 6)1.35k
) {
104
1
      if (Arch == llvm::Triple::arm ||
105
1
          Arch == llvm::Triple::x86 ||
106
1
          Arch == llvm::Triple::x86_64)
107
1
        return false;
108
17.9k
    }
109
17.9k
    else if ((getKind() ==  MacOSX) && 
isNonFragile()6.82k
&&
110
17.9k
             
(getVersion() >= VersionTuple(10, 0))6.82k
&&
111
17.9k
             
(getVersion() < VersionTuple(10, 6))6.81k
)
112
605
        return Arch != llvm::Triple::x86_64;
113
17.3k
    // Except for deployment target of 10.5 or less,
114
17.3k
    // Mac runtimes use legacy dispatch everywhere now.
115
17.3k
    return true;
116
17.3k
  }
117
118
  /// Is this runtime basically of the GNU family of runtimes?
119
6.58k
  bool isGNUFamily() const {
120
6.58k
    switch (getKind()) {
121
6.58k
    case FragileMacOSX:
122
6.42k
    case MacOSX:
123
6.42k
    case iOS:
124
6.42k
    case WatchOS:
125
6.42k
      return false;
126
6.42k
    case GCC:
127
166
    case GNUstep:
128
166
    case ObjFW:
129
166
      return true;
130
0
    }
131
0
    llvm_unreachable("bad kind");
132
0
  }
133
134
  /// Is this runtime basically of the NeXT family of runtimes?
135
6.15k
  bool isNeXTFamily() const {
136
6.15k
    // For now, this is just the inverse of isGNUFamily(), but that's
137
6.15k
    // not inherently true.
138
6.15k
    return !isGNUFamily();
139
6.15k
  }
140
141
  /// Does this runtime allow ARC at all?
142
362
  bool allowsARC() const {
143
362
    switch (getKind()) {
144
362
    case FragileMacOSX:
145
7
      // No stub library for the fragile runtime.
146
7
      return getVersion() >= VersionTuple(10, 7);
147
362
    
case MacOSX: return true331
;
148
362
    
case iOS: return true21
;
149
362
    
case WatchOS: return true2
;
150
362
    
case GCC: return false0
;
151
362
    
case GNUstep: return true1
;
152
362
    
case ObjFW: return true0
;
153
0
    }
154
0
    llvm_unreachable("bad kind");
155
0
  }
156
157
  /// Does this runtime natively provide the ARC entrypoints? 
158
  ///
159
  /// ARC cannot be directly supported on a platform that does not provide
160
  /// these entrypoints, although it may be supportable via a stub
161
  /// library.
162
3.80k
  bool hasNativeARC() const {
163
3.80k
    switch (getKind()) {
164
3.80k
    
case FragileMacOSX: return getVersion() >= VersionTuple(10, 7)316
;
165
3.80k
    
case MacOSX: return getVersion() >= VersionTuple(10, 7)3.19k
;
166
3.80k
    
case iOS: return getVersion() >= VersionTuple(5)148
;
167
3.80k
    
case WatchOS: return true17
;
168
3.80k
169
3.80k
    
case GCC: return false31
;
170
3.80k
    
case GNUstep: return getVersion() >= VersionTuple(1, 6)74
;
171
3.80k
    
case ObjFW: return true24
;
172
0
    }
173
0
    llvm_unreachable("bad kind");
174
0
  }
175
176
  /// Does this runtime supports optimized setter entrypoints?
177
82
  bool hasOptimizedSetter() const {
178
82
    switch (getKind()) {
179
82
      case MacOSX:
180
66
        return getVersion() >= VersionTuple(10, 8);
181
82
      case iOS:
182
12
        return (getVersion() >= VersionTuple(6));
183
82
      case WatchOS:
184
0
        return true;
185
82
      case GNUstep:
186
4
        return getVersion() >= VersionTuple(1, 7);
187
82
      default:
188
0
        return false;
189
82
    }
190
82
  }
191
192
  /// Does this runtime allow the use of __weak?
193
3.25k
  bool allowsWeak() const {
194
3.25k
    return hasNativeWeak();
195
3.25k
  }
196
197
  /// Does this runtime natively provide ARC-compliant 'weak'
198
  /// entrypoints?
199
3.25k
  bool hasNativeWeak() const {
200
3.25k
    // Right now, this is always equivalent to whether the runtime
201
3.25k
    // natively supports ARC decision.
202
3.25k
    return hasNativeARC();
203
3.25k
  }
204
205
  /// Does this runtime directly support the subscripting methods?
206
  ///
207
  /// This is really a property of the library, not the runtime.
208
3
  bool hasSubscripting() const {
209
3
    switch (getKind()) {
210
3
    
case FragileMacOSX: return false0
;
211
3
    case MacOSX: return getVersion() >= VersionTuple(10, 11);
212
3
    
case iOS: return getVersion() >= VersionTuple(9)0
;
213
3
    
case WatchOS: return true0
;
214
3
215
3
    // This is really a lie, because some implementations and versions
216
3
    // of the runtime do not support ARC.  Probably -fgnu-runtime
217
3
    // should imply a "maximal" runtime or something?
218
3
    
case GCC: return true0
;
219
3
    
case GNUstep: return true0
;
220
3
    
case ObjFW: return true0
;
221
0
    }
222
0
    llvm_unreachable("bad kind");
223
0
  }
224
225
  /// Does this runtime allow sizeof or alignof on object types?
226
146k
  bool allowsSizeofAlignof() const {
227
146k
    return isFragile();
228
146k
  }
229
230
  /// Does this runtime allow pointer arithmetic on objects?
231
  ///
232
  /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic()
233
  /// yields true) [].
234
279
  bool allowsPointerArithmetic() const {
235
279
    switch (getKind()) {
236
279
    case FragileMacOSX:
237
22
    case GCC:
238
22
      return true;
239
257
    case MacOSX:
240
257
    case iOS:
241
257
    case WatchOS:
242
257
    case GNUstep:
243
257
    case ObjFW:
244
257
      return false;
245
0
    }
246
0
    llvm_unreachable("bad kind");
247
0
  }
248
249
  /// Is subscripting pointer arithmetic?
250
263
  bool isSubscriptPointerArithmetic() const {
251
263
    return allowsPointerArithmetic();
252
263
  }
253
254
  /// Does this runtime provide an objc_terminate function?
255
  ///
256
  /// This is used in handlers for exceptions during the unwind process;
257
  /// without it, abort() must be used in pure ObjC files.
258
12
  bool hasTerminate() const {
259
12
    switch (getKind()) {
260
12
    
case FragileMacOSX: return getVersion() >= VersionTuple(10, 8)2
;
261
12
    
case MacOSX: return getVersion() >= VersionTuple(10, 8)1
;
262
12
    
case iOS: return getVersion() >= VersionTuple(5)9
;
263
12
    
case WatchOS: return true0
;
264
12
    
case GCC: return false0
;
265
12
    
case GNUstep: return false0
;
266
12
    
case ObjFW: return false0
;
267
0
    }
268
0
    llvm_unreachable("bad kind");
269
0
  }
270
271
  /// Does this runtime support weakly importing classes?
272
1.58M
  bool hasWeakClassImport() const {
273
1.58M
    switch (getKind()) {
274
1.58M
    
case MacOSX: return true1.56M
;
275
1.58M
    
case iOS: return true15.8k
;
276
1.58M
    
case WatchOS: return true33
;
277
1.58M
    
case FragileMacOSX: return false146
;
278
1.58M
    
case GCC: return true12
;
279
1.58M
    
case GNUstep: return true6
;
280
1.58M
    
case ObjFW: return true12
;
281
0
    }
282
0
    llvm_unreachable("bad kind");
283
0
  }
284
285
  /// Does this runtime use zero-cost exceptions?
286
317
  bool hasUnwindExceptions() const {
287
317
    switch (getKind()) {
288
317
    
case MacOSX: return true73
;
289
317
    
case iOS: return true202
;
290
317
    
case WatchOS: return true3
;
291
317
    
case FragileMacOSX: return false10
;
292
317
    
case GCC: return true10
;
293
317
    
case GNUstep: return true12
;
294
317
    
case ObjFW: return true7
;
295
0
    }
296
0
    llvm_unreachable("bad kind");
297
0
  }
298
299
59
  bool hasAtomicCopyHelper() const {
300
59
    switch (getKind()) {
301
59
    case FragileMacOSX:
302
55
    case MacOSX:
303
55
    case iOS:
304
55
    case WatchOS:
305
55
      return true;
306
55
    case GNUstep:
307
4
      return getVersion() >= VersionTuple(1, 7);
308
55
    
default: return false0
;
309
59
    }
310
59
  }
311
312
  /// Is objc_unsafeClaimAutoreleasedReturnValue available?
313
55
  bool hasARCUnsafeClaimAutoreleasedReturnValue() const {
314
55
    switch (getKind()) {
315
55
    case MacOSX:
316
23
    case FragileMacOSX:
317
23
      return getVersion() >= VersionTuple(10, 11);
318
32
    case iOS:
319
32
      return getVersion() >= VersionTuple(9);
320
23
    case WatchOS:
321
0
      return getVersion() >= VersionTuple(2);
322
23
    case GNUstep:
323
0
      return false;
324
23
    default:
325
0
      return false;
326
55
    }
327
55
  }
328
329
  /// Are the empty collection symbols available?
330
50
  bool hasEmptyCollections() const {
331
50
    switch (getKind()) {
332
50
    default:
333
0
      return false;
334
50
    case MacOSX:
335
26
      return getVersion() >= VersionTuple(10, 11);
336
50
    case iOS:
337
16
      return getVersion() >= VersionTuple(9);
338
50
    case WatchOS:
339
8
      return getVersion() >= VersionTuple(2);
340
50
    }
341
50
  }
342
343
  /// Try to parse an Objective-C runtime specification from the given
344
  /// string.
345
  ///
346
  /// \return true on error.
347
  bool tryParse(StringRef input);
348
349
  std::string getAsString() const;
350
351
3.94k
  friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) {
352
3.94k
    return left.getKind() == right.getKind() &&
353
3.94k
           left.getVersion() == right.getVersion();
354
3.94k
  }
355
356
3.94k
  friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) {
357
3.94k
    return !(left == right);
358
3.94k
  }
359
};
360
361
raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
362
363
} // namespace clang
364
365
#endif // LLVM_CLANG_BASIC_OBJCRUNTIME_H