1 //===- ObjCRuntime.cpp - Objective-C Runtime Handling ---------------------===// 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 // This file implements the ObjCRuntime class, which represents the 10 // target Objective-C runtime. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Basic/ObjCRuntime.h" 15 #include "llvm/ADT/StringRef.h" 16 #include "llvm/Support/VersionTuple.h" 17 #include "llvm/Support/raw_ostream.h" 18 #include <cstddef> 19 #include <string> 20 21 using namespace clang; 22 23 std::string ObjCRuntime::getAsString() const { 24 std::string Result; 25 { 26 llvm::raw_string_ostream Out(Result); 27 Out << *this; 28 } 29 return Result; 30 } 31 32 raw_ostream &clang::operator<<(raw_ostream &out, const ObjCRuntime &value) { 33 switch (value.getKind()) { 34 case ObjCRuntime::MacOSX: out << "macosx"; break; 35 case ObjCRuntime::FragileMacOSX: out << "macosx-fragile"; break; 36 case ObjCRuntime::iOS: out << "ios"; break; 37 case ObjCRuntime::WatchOS: out << "watchos"; break; 38 case ObjCRuntime::GNUstep: out << "gnustep"; break; 39 case ObjCRuntime::GCC: out << "gcc"; break; 40 case ObjCRuntime::ObjFW: out << "objfw"; break; 41 } 42 if (value.getVersion() > VersionTuple(0)) { 43 out << '-' << value.getVersion(); 44 } 45 return out; 46 } 47 48 bool ObjCRuntime::tryParse(StringRef input) { 49 // Look for the last dash. 50 std::size_t dash = input.rfind('-'); 51 52 // We permit dashes in the runtime name, and we also permit the 53 // version to be omitted, so if we see a dash not followed by a 54 // digit then we need to ignore it. 55 if (dash != StringRef::npos && dash + 1 != input.size() && 56 (input[dash+1] < '0' || input[dash+1] > '9')) { 57 dash = StringRef::npos; 58 } 59 60 // Everything prior to that must be a valid string name. 61 Kind kind; 62 StringRef runtimeName = input.substr(0, dash); 63 Version = VersionTuple(0); 64 if (runtimeName == "macosx") { 65 kind = ObjCRuntime::MacOSX; 66 } else if (runtimeName == "macosx-fragile") { 67 kind = ObjCRuntime::FragileMacOSX; 68 } else if (runtimeName == "ios") { 69 kind = ObjCRuntime::iOS; 70 } else if (runtimeName == "watchos") { 71 kind = ObjCRuntime::WatchOS; 72 } else if (runtimeName == "gnustep") { 73 // If no version is specified then default to the most recent one that we 74 // know about. 75 Version = VersionTuple(1, 6); 76 kind = ObjCRuntime::GNUstep; 77 } else if (runtimeName == "gcc") { 78 kind = ObjCRuntime::GCC; 79 } else if (runtimeName == "objfw") { 80 kind = ObjCRuntime::ObjFW; 81 Version = VersionTuple(0, 8); 82 } else { 83 return true; 84 } 85 TheKind = kind; 86 87 if (dash != StringRef::npos) { 88 StringRef verString = input.substr(dash + 1); 89 if (Version.tryParse(verString)) 90 return true; 91 } 92 93 if (kind == ObjCRuntime::ObjFW && Version > VersionTuple(0, 8)) 94 Version = VersionTuple(0, 8); 95 96 return false; 97 } 98