Home | History | Annotate | Line # | Download | only in Basic
      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