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(C: '-'); |
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(Start: 0, N: 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(Start: dash + 1); |
89 | if (Version.tryParse(string: 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 | |