File indexing completed on 2026-05-10 08:36:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H
0015 #define LLVM_CLANG_BASIC_OBJCRUNTIME_H
0016
0017 #include "clang/Basic/LLVM.h"
0018 #include "llvm/ADT/StringRef.h"
0019 #include "llvm/Support/ErrorHandling.h"
0020 #include "llvm/Support/HashBuilder.h"
0021 #include "llvm/Support/VersionTuple.h"
0022 #include "llvm/TargetParser/Triple.h"
0023 #include <string>
0024
0025 namespace clang {
0026
0027
0028 class ObjCRuntime {
0029 public:
0030
0031 enum Kind {
0032
0033
0034
0035 MacOSX,
0036
0037
0038
0039
0040 FragileMacOSX,
0041
0042
0043
0044
0045 iOS,
0046
0047
0048
0049 WatchOS,
0050
0051
0052
0053 GCC,
0054
0055
0056 GNUstep,
0057
0058
0059 ObjFW
0060 };
0061
0062 private:
0063 Kind TheKind = MacOSX;
0064 VersionTuple Version;
0065
0066 public:
0067
0068 ObjCRuntime() = default;
0069 ObjCRuntime(Kind kind, const VersionTuple &version)
0070 : TheKind(kind), Version(version) {}
0071
0072 void set(Kind kind, VersionTuple version) {
0073 TheKind = kind;
0074 Version = version;
0075 }
0076
0077 Kind getKind() const { return TheKind; }
0078 const VersionTuple &getVersion() const { return Version; }
0079
0080
0081
0082 bool isNonFragile() const {
0083 switch (getKind()) {
0084 case FragileMacOSX: return false;
0085 case GCC: return false;
0086 case MacOSX: return true;
0087 case GNUstep: return true;
0088 case ObjFW: return true;
0089 case iOS: return true;
0090 case WatchOS: return true;
0091 }
0092 llvm_unreachable("bad kind");
0093 }
0094
0095
0096
0097 bool isFragile() const { return !isNonFragile(); }
0098
0099
0100 bool isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch) {
0101
0102
0103 if (getKind() == GNUstep) {
0104 switch (Arch) {
0105 case llvm::Triple::arm:
0106 case llvm::Triple::x86:
0107 case llvm::Triple::x86_64:
0108 return !(getVersion() >= VersionTuple(1, 6));
0109 case llvm::Triple::aarch64:
0110 case llvm::Triple::mips64:
0111 return !(getVersion() >= VersionTuple(1, 9));
0112 case llvm::Triple::riscv64:
0113 return !(getVersion() >= VersionTuple(2, 2));
0114 default:
0115 return true;
0116 }
0117 } else if ((getKind() == MacOSX) && isNonFragile() &&
0118 (getVersion() >= VersionTuple(10, 0)) &&
0119 (getVersion() < VersionTuple(10, 6)))
0120 return Arch != llvm::Triple::x86_64;
0121
0122
0123 return true;
0124 }
0125
0126
0127 bool isGNUFamily() const {
0128 switch (getKind()) {
0129 case FragileMacOSX:
0130 case MacOSX:
0131 case iOS:
0132 case WatchOS:
0133 return false;
0134 case GCC:
0135 case GNUstep:
0136 case ObjFW:
0137 return true;
0138 }
0139 llvm_unreachable("bad kind");
0140 }
0141
0142
0143 bool isNeXTFamily() const {
0144
0145
0146 return !isGNUFamily();
0147 }
0148
0149
0150 bool allowsARC() const {
0151 switch (getKind()) {
0152 case FragileMacOSX:
0153
0154 return getVersion() >= VersionTuple(10, 7);
0155 case MacOSX: return true;
0156 case iOS: return true;
0157 case WatchOS: return true;
0158 case GCC: return false;
0159 case GNUstep: return true;
0160 case ObjFW: return true;
0161 }
0162 llvm_unreachable("bad kind");
0163 }
0164
0165
0166
0167
0168
0169
0170 bool hasNativeARC() const {
0171 switch (getKind()) {
0172 case FragileMacOSX: return getVersion() >= VersionTuple(10, 7);
0173 case MacOSX: return getVersion() >= VersionTuple(10, 7);
0174 case iOS: return getVersion() >= VersionTuple(5);
0175 case WatchOS: return true;
0176
0177 case GCC: return false;
0178 case GNUstep: return getVersion() >= VersionTuple(1, 6);
0179 case ObjFW: return true;
0180 }
0181 llvm_unreachable("bad kind");
0182 }
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 bool shouldUseARCFunctionsForRetainRelease() const {
0202 switch (getKind()) {
0203 case FragileMacOSX:
0204 return false;
0205 case MacOSX:
0206 return getVersion() >= VersionTuple(10, 10);
0207 case iOS:
0208 return getVersion() >= VersionTuple(8);
0209 case WatchOS:
0210 return true;
0211 case GCC:
0212 return false;
0213 case GNUstep:
0214
0215
0216
0217
0218
0219
0220 return (getVersion() >= VersionTuple(2, 2));
0221 case ObjFW:
0222 return false;
0223 }
0224 llvm_unreachable("bad kind");
0225 }
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 bool shouldUseRuntimeFunctionsForAlloc() const {
0244 switch (getKind()) {
0245 case FragileMacOSX:
0246 return false;
0247 case MacOSX:
0248 return getVersion() >= VersionTuple(10, 10);
0249 case iOS:
0250 return getVersion() >= VersionTuple(8);
0251 case WatchOS:
0252 return true;
0253
0254 case GCC:
0255 return false;
0256 case GNUstep:
0257 return getVersion() >= VersionTuple(2, 2);
0258 case ObjFW:
0259 return false;
0260 }
0261 llvm_unreachable("bad kind");
0262 }
0263
0264
0265
0266
0267 bool shouldUseRuntimeFunctionForCombinedAllocInit() const {
0268 switch (getKind()) {
0269 case MacOSX:
0270 return getVersion() >= VersionTuple(10, 14, 4);
0271 case iOS:
0272 return getVersion() >= VersionTuple(12, 2);
0273 case WatchOS:
0274 return getVersion() >= VersionTuple(5, 2);
0275 case GNUstep:
0276 return getVersion() >= VersionTuple(2, 2);
0277 default:
0278 return false;
0279 }
0280 }
0281
0282
0283 bool hasOptimizedSetter() const {
0284 switch (getKind()) {
0285 case MacOSX:
0286 return getVersion() >= VersionTuple(10, 8);
0287 case iOS:
0288 return (getVersion() >= VersionTuple(6));
0289 case WatchOS:
0290 return true;
0291 case GNUstep:
0292 return getVersion() >= VersionTuple(1, 7);
0293 default:
0294 return false;
0295 }
0296 }
0297
0298
0299 bool allowsWeak() const {
0300 return hasNativeWeak();
0301 }
0302
0303
0304
0305 bool hasNativeWeak() const {
0306
0307
0308 return hasNativeARC();
0309 }
0310
0311
0312
0313
0314 bool hasSubscripting() const {
0315 switch (getKind()) {
0316 case FragileMacOSX: return false;
0317 case MacOSX: return getVersion() >= VersionTuple(10, 11);
0318 case iOS: return getVersion() >= VersionTuple(9);
0319 case WatchOS: return true;
0320
0321
0322
0323
0324 case GCC: return true;
0325 case GNUstep: return true;
0326 case ObjFW: return true;
0327 }
0328 llvm_unreachable("bad kind");
0329 }
0330
0331
0332 bool allowsSizeofAlignof() const {
0333 return isFragile();
0334 }
0335
0336
0337
0338
0339
0340 bool allowsPointerArithmetic() const {
0341 switch (getKind()) {
0342 case FragileMacOSX:
0343 case GCC:
0344 return true;
0345 case MacOSX:
0346 case iOS:
0347 case WatchOS:
0348 case GNUstep:
0349 case ObjFW:
0350 return false;
0351 }
0352 llvm_unreachable("bad kind");
0353 }
0354
0355
0356 bool isSubscriptPointerArithmetic() const {
0357 return allowsPointerArithmetic();
0358 }
0359
0360
0361
0362
0363
0364 bool hasTerminate() const {
0365 switch (getKind()) {
0366 case FragileMacOSX: return getVersion() >= VersionTuple(10, 8);
0367 case MacOSX: return getVersion() >= VersionTuple(10, 8);
0368 case iOS: return getVersion() >= VersionTuple(5);
0369 case WatchOS: return true;
0370 case GCC: return false;
0371 case GNUstep: return false;
0372 case ObjFW: return false;
0373 }
0374 llvm_unreachable("bad kind");
0375 }
0376
0377
0378 bool hasWeakClassImport() const {
0379 switch (getKind()) {
0380 case MacOSX: return true;
0381 case iOS: return true;
0382 case WatchOS: return true;
0383 case FragileMacOSX: return false;
0384 case GCC: return true;
0385 case GNUstep: return true;
0386 case ObjFW: return true;
0387 }
0388 llvm_unreachable("bad kind");
0389 }
0390
0391
0392 bool hasUnwindExceptions() const {
0393 switch (getKind()) {
0394 case MacOSX: return true;
0395 case iOS: return true;
0396 case WatchOS: return true;
0397 case FragileMacOSX: return false;
0398 case GCC: return true;
0399 case GNUstep: return true;
0400 case ObjFW: return true;
0401 }
0402 llvm_unreachable("bad kind");
0403 }
0404
0405 bool hasAtomicCopyHelper() const {
0406 switch (getKind()) {
0407 case FragileMacOSX:
0408 case MacOSX:
0409 case iOS:
0410 case WatchOS:
0411 return true;
0412 case GNUstep:
0413 return getVersion() >= VersionTuple(1, 7);
0414 default: return false;
0415 }
0416 }
0417
0418
0419 bool hasARCUnsafeClaimAutoreleasedReturnValue() const {
0420 switch (getKind()) {
0421 case MacOSX:
0422 case FragileMacOSX:
0423 return getVersion() >= VersionTuple(10, 11);
0424 case iOS:
0425 return getVersion() >= VersionTuple(9);
0426 case WatchOS:
0427 return getVersion() >= VersionTuple(2);
0428 case GNUstep:
0429 return false;
0430 default:
0431 return false;
0432 }
0433 }
0434
0435
0436 bool hasEmptyCollections() const {
0437 switch (getKind()) {
0438 default:
0439 return false;
0440 case MacOSX:
0441 return getVersion() >= VersionTuple(10, 11);
0442 case iOS:
0443 return getVersion() >= VersionTuple(9);
0444 case WatchOS:
0445 return getVersion() >= VersionTuple(2);
0446 }
0447 }
0448
0449
0450
0451 bool allowsClassStubs() const {
0452 switch (getKind()) {
0453 case FragileMacOSX:
0454 case GCC:
0455 case GNUstep:
0456 case ObjFW:
0457 return false;
0458 case MacOSX:
0459 case iOS:
0460 case WatchOS:
0461 return true;
0462 }
0463 llvm_unreachable("bad kind");
0464 }
0465
0466
0467 bool allowsDirectDispatch() const {
0468 switch (getKind()) {
0469 case FragileMacOSX: return false;
0470 case MacOSX: return true;
0471 case iOS: return true;
0472 case WatchOS: return true;
0473 case GCC: return false;
0474 case GNUstep:
0475 return (getVersion() >= VersionTuple(2, 2));
0476 case ObjFW: return false;
0477 }
0478 llvm_unreachable("bad kind");
0479 }
0480
0481
0482
0483
0484
0485 bool tryParse(StringRef input);
0486
0487 std::string getAsString() const;
0488
0489 friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) {
0490 return left.getKind() == right.getKind() &&
0491 left.getVersion() == right.getVersion();
0492 }
0493
0494 friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) {
0495 return !(left == right);
0496 }
0497
0498 friend llvm::hash_code hash_value(const ObjCRuntime &OCR) {
0499 return llvm::hash_combine(OCR.getKind(), OCR.getVersion());
0500 }
0501
0502 template <typename HasherT, llvm::endianness Endianness>
0503 friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
0504 const ObjCRuntime &OCR) {
0505 HBuilder.add(OCR.getKind(), OCR.getVersion());
0506 }
0507 };
0508
0509 raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
0510
0511 }
0512
0513 #endif