15a52011cSEugene Zelenko //===- ObjCRuntime.cpp - Objective-C Runtime Handling ---------------------===//
25fb5df9cSJohn McCall //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65fb5df9cSJohn McCall //
75fb5df9cSJohn McCall //===----------------------------------------------------------------------===//
85fb5df9cSJohn McCall //
95fb5df9cSJohn McCall // This file implements the ObjCRuntime class, which represents the
105fb5df9cSJohn McCall // target Objective-C runtime.
115fb5df9cSJohn McCall //
125fb5df9cSJohn McCall //===----------------------------------------------------------------------===//
135a52011cSEugene Zelenko
145fb5df9cSJohn McCall #include "clang/Basic/ObjCRuntime.h"
155a52011cSEugene Zelenko #include "llvm/ADT/StringRef.h"
16d8c6290bSPavel Labath #include "llvm/Support/VersionTuple.h"
175fb5df9cSJohn McCall #include "llvm/Support/raw_ostream.h"
185a52011cSEugene Zelenko #include <cstddef>
195a52011cSEugene Zelenko #include <string>
205fb5df9cSJohn McCall
215fb5df9cSJohn McCall using namespace clang;
225fb5df9cSJohn McCall
getAsString() const235fb5df9cSJohn McCall std::string ObjCRuntime::getAsString() const {
245fb5df9cSJohn McCall std::string Result;
255fb5df9cSJohn McCall {
265fb5df9cSJohn McCall llvm::raw_string_ostream Out(Result);
275fb5df9cSJohn McCall Out << *this;
285fb5df9cSJohn McCall }
295fb5df9cSJohn McCall return Result;
305fb5df9cSJohn McCall }
315fb5df9cSJohn McCall
operator <<(raw_ostream & out,const ObjCRuntime & value)325fb5df9cSJohn McCall raw_ostream &clang::operator<<(raw_ostream &out, const ObjCRuntime &value) {
335fb5df9cSJohn McCall switch (value.getKind()) {
345fb5df9cSJohn McCall case ObjCRuntime::MacOSX: out << "macosx"; break;
355fb5df9cSJohn McCall case ObjCRuntime::FragileMacOSX: out << "macosx-fragile"; break;
365fb5df9cSJohn McCall case ObjCRuntime::iOS: out << "ios"; break;
37756447a6STim Northover case ObjCRuntime::WatchOS: out << "watchos"; break;
38b601c968SDavid Chisnall case ObjCRuntime::GNUstep: out << "gnustep"; break;
39b601c968SDavid Chisnall case ObjCRuntime::GCC: out << "gcc"; break;
40775086e6SJohn McCall case ObjCRuntime::ObjFW: out << "objfw"; break;
415fb5df9cSJohn McCall }
425fb5df9cSJohn McCall if (value.getVersion() > VersionTuple(0)) {
435fb5df9cSJohn McCall out << '-' << value.getVersion();
445fb5df9cSJohn McCall }
455fb5df9cSJohn McCall return out;
465fb5df9cSJohn McCall }
475fb5df9cSJohn McCall
tryParse(StringRef input)485fb5df9cSJohn McCall bool ObjCRuntime::tryParse(StringRef input) {
495fb5df9cSJohn McCall // Look for the last dash.
505fb5df9cSJohn McCall std::size_t dash = input.rfind('-');
515fb5df9cSJohn McCall
5218ac1632SJohn McCall // We permit dashes in the runtime name, and we also permit the
5318ac1632SJohn McCall // version to be omitted, so if we see a dash not followed by a
5418ac1632SJohn McCall // digit then we need to ignore it.
555fb5df9cSJohn McCall if (dash != StringRef::npos && dash + 1 != input.size() &&
565fb5df9cSJohn McCall (input[dash+1] < '0' || input[dash+1] > '9')) {
575fb5df9cSJohn McCall dash = StringRef::npos;
585fb5df9cSJohn McCall }
595fb5df9cSJohn McCall
605fb5df9cSJohn McCall // Everything prior to that must be a valid string name.
615fb5df9cSJohn McCall Kind kind;
625fb5df9cSJohn McCall StringRef runtimeName = input.substr(0, dash);
63314896c9SDavid Chisnall Version = VersionTuple(0);
645fb5df9cSJohn McCall if (runtimeName == "macosx") {
655fb5df9cSJohn McCall kind = ObjCRuntime::MacOSX;
665fb5df9cSJohn McCall } else if (runtimeName == "macosx-fragile") {
675fb5df9cSJohn McCall kind = ObjCRuntime::FragileMacOSX;
685fb5df9cSJohn McCall } else if (runtimeName == "ios") {
695fb5df9cSJohn McCall kind = ObjCRuntime::iOS;
70756447a6STim Northover } else if (runtimeName == "watchos") {
71756447a6STim Northover kind = ObjCRuntime::WatchOS;
72b601c968SDavid Chisnall } else if (runtimeName == "gnustep") {
73314896c9SDavid Chisnall // If no version is specified then default to the most recent one that we
74314896c9SDavid Chisnall // know about.
75314896c9SDavid Chisnall Version = VersionTuple(1, 6);
76b601c968SDavid Chisnall kind = ObjCRuntime::GNUstep;
77b601c968SDavid Chisnall } else if (runtimeName == "gcc") {
78b601c968SDavid Chisnall kind = ObjCRuntime::GCC;
79775086e6SJohn McCall } else if (runtimeName == "objfw") {
80775086e6SJohn McCall kind = ObjCRuntime::ObjFW;
814d6efbb2SBenjamin Kramer Version = VersionTuple(0, 8);
825fb5df9cSJohn McCall } else {
835fb5df9cSJohn McCall return true;
845fb5df9cSJohn McCall }
855fb5df9cSJohn McCall TheKind = kind;
865fb5df9cSJohn McCall
875fb5df9cSJohn McCall if (dash != StringRef::npos) {
885fb5df9cSJohn McCall StringRef verString = input.substr(dash + 1);
895fb5df9cSJohn McCall if (Version.tryParse(verString))
905fb5df9cSJohn McCall return true;
915fb5df9cSJohn McCall }
925fb5df9cSJohn McCall
934d6efbb2SBenjamin Kramer if (kind == ObjCRuntime::ObjFW && Version > VersionTuple(0, 8))
944d6efbb2SBenjamin Kramer Version = VersionTuple(0, 8);
954d6efbb2SBenjamin Kramer
965fb5df9cSJohn McCall return false;
975fb5df9cSJohn McCall }
98