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