r320235 - [driver][darwin] Refactor the target selection code, NFC

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 8 18:27:11 PST 2017


Author: arphaman
Date: Fri Dec  8 18:27:11 2017
New Revision: 320235

URL: http://llvm.org/viewvc/llvm-project?rev=320235&view=rev
Log:
[driver][darwin] Refactor the target selection code, NFC

The simulator variant of Darwin's platforms is removed in favor of a new
environment field.
The code that selects the platform and the version is split into 4 different
functions instead of being all in one function.
This is an NFC commit, although it slightly improves the
"invalid version number" diagnostic by displaying the environment variable
instead of -m<os>-version-min if the OS version was derived from the
environment.

rdar://35813850

Differential Revision: https://reviews.llvm.org/D41035

Modified:
    cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
    cfe/trunk/lib/Driver/ToolChains/Darwin.h
    cfe/trunk/test/Driver/darwin-version.c

Modified: cfe/trunk/lib/Driver/ToolChains/Darwin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Darwin.cpp?rev=320235&r1=320234&r2=320235&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/Darwin.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains/Darwin.cpp Fri Dec  8 18:27:11 2017
@@ -941,13 +941,10 @@ StringRef Darwin::getPlatformFamily() co
     case DarwinPlatformKind::MacOS:
       return "MacOSX";
     case DarwinPlatformKind::IPhoneOS:
-    case DarwinPlatformKind::IPhoneOSSimulator:
       return "iPhone";
     case DarwinPlatformKind::TvOS:
-    case DarwinPlatformKind::TvOSSimulator:
       return "AppleTV";
     case DarwinPlatformKind::WatchOS:
-    case DarwinPlatformKind::WatchOSSimulator:
       return "Watch";
   }
   llvm_unreachable("Unsupported platform");
@@ -971,17 +968,11 @@ StringRef Darwin::getOSLibraryNameSuffix
   case DarwinPlatformKind::MacOS:
     return "osx";
   case DarwinPlatformKind::IPhoneOS:
-    return "ios";
-  case DarwinPlatformKind::IPhoneOSSimulator:
-    return "iossim";
+    return TargetEnvironment == NativeEnvironment ? "ios" : "iossim";
   case DarwinPlatformKind::TvOS:
-    return "tvos";
-  case DarwinPlatformKind::TvOSSimulator:
-    return "tvossim";
+    return TargetEnvironment == NativeEnvironment ? "tvos" : "tvossim";
   case DarwinPlatformKind::WatchOS:
-    return "watchos";
-  case DarwinPlatformKind::WatchOSSimulator:
-    return "watchossim";
+    return TargetEnvironment == NativeEnvironment ? "watchos" : "watchossim";
   }
   llvm_unreachable("Unsupported platform");
 }
@@ -1172,28 +1163,131 @@ static std::string getSystemOrSDKMacOSVe
   return MacOSSDKVersion;
 }
 
-void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
-  const OptTable &Opts = getDriver().getOpts();
+namespace {
 
-  // Support allowing the SDKROOT environment variable used by xcrun and other
-  // Xcode tools to define the default sysroot, by making it the default for
-  // isysroot.
-  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
-    // Warn if the path does not exist.
-    if (!getVFS().exists(A->getValue()))
-      getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
-  } else {
-    if (char *env = ::getenv("SDKROOT")) {
-      // We only use this value as the default if it is an absolute path,
-      // exists, and it is not the root path.
-      if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
-          StringRef(env) != "/") {
-        Args.append(Args.MakeSeparateArg(
-            nullptr, Opts.getOption(options::OPT_isysroot), env));
-      }
+/// The Darwin OS that was selected or inferred from arguments / environment.
+struct DarwinPlatform {
+  enum SourceKind {
+    /// The OS was specified using the -target argument.
+    TargetArg,
+    /// The OS was specified using the -m<os>-version-min argument.
+    OSVersionArg,
+    /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
+    DeploymentTargetEnv,
+    /// The OS was inferred from the SDK.
+    InferredFromSDK,
+    /// The OS was inferred from the -arch.
+    InferredFromArch
+  };
+
+  using DarwinPlatformKind = Darwin::DarwinPlatformKind;
+
+  DarwinPlatformKind getPlatform() const { return Platform; }
+
+  StringRef getOSVersion() const {
+    if (Kind == OSVersionArg)
+      return Argument->getValue();
+    return OSVersion;
+  }
+
+  /// Returns true if the target OS was explicitly specified.
+  bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
+
+  /// Adds the -m<os>-version-min argument to the compiler invocation.
+  void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
+    if (Argument)
+      return;
+    assert(Kind != TargetArg && Kind != OSVersionArg && "Invalid kind");
+    options::ID Opt;
+    switch (Platform) {
+    case DarwinPlatformKind::MacOS:
+      Opt = options::OPT_mmacosx_version_min_EQ;
+      break;
+    case DarwinPlatformKind::IPhoneOS:
+      Opt = options::OPT_miphoneos_version_min_EQ;
+      break;
+    case DarwinPlatformKind::TvOS:
+      Opt = options::OPT_mtvos_version_min_EQ;
+      break;
+    case DarwinPlatformKind::WatchOS:
+      Opt = options::OPT_mwatchos_version_min_EQ;
+      break;
+    }
+    Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
+    Args.append(Argument);
+  }
+
+  /// Returns the OS version with the argument / environment variable that
+  /// specified it.
+  std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
+    switch (Kind) {
+    case TargetArg:
+    case OSVersionArg:
+    case InferredFromSDK:
+    case InferredFromArch:
+      assert(Argument && "OS version argument not yet inferred");
+      return Argument->getAsString(Args);
+    case DeploymentTargetEnv:
+      return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
+    }
+  }
+
+  static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
+                                           Arg *A) {
+    return DarwinPlatform(OSVersionArg, Platform, A);
+  }
+  static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
+                                                  StringRef EnvVarName,
+                                                  StringRef Value) {
+    DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
+    Result.EnvVarName = EnvVarName;
+    return Result;
+  }
+  static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
+                                      StringRef Value) {
+    return DarwinPlatform(InferredFromSDK, Platform, Value);
+  }
+  static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
+                                       StringRef Value) {
+    DarwinPlatformKind Platform;
+    switch (OS) {
+    case llvm::Triple::Darwin:
+    case llvm::Triple::MacOSX:
+      Platform = DarwinPlatformKind::MacOS;
+      break;
+    case llvm::Triple::IOS:
+      Platform = DarwinPlatformKind::IPhoneOS;
+      break;
+    case llvm::Triple::TvOS:
+      Platform = DarwinPlatformKind::TvOS;
+      break;
+    case llvm::Triple::WatchOS:
+      Platform = DarwinPlatformKind::WatchOS;
+      break;
+    default:
+      llvm_unreachable("Unable to infer Darwin variant");
     }
+    return DarwinPlatform(InferredFromArch, Platform, Value);
   }
 
+private:
+  DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
+      : Kind(Kind), Platform(Platform), Argument(Argument) {}
+  DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value)
+      : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(nullptr) {}
+
+  SourceKind Kind;
+  DarwinPlatformKind Platform;
+  std::string OSVersion;
+  Arg *Argument;
+  StringRef EnvVarName;
+};
+
+/// Returns the deployment target that's specified using the -m<os>-version-min
+/// argument.
+Optional<DarwinPlatform>
+getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
+                                    const Driver &TheDriver) {
   Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
   Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ,
                                     options::OPT_mios_simulator_version_min_EQ);
@@ -1203,224 +1297,249 @@ void Darwin::AddDeploymentTarget(Derived
   Arg *WatchOSVersion =
       Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
                       options::OPT_mwatchos_simulator_version_min_EQ);
+  if (OSXVersion) {
+    if (iOSVersion || TvOSVersion || WatchOSVersion) {
+      TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
+          << OSXVersion->getAsString(Args)
+          << (iOSVersion ? iOSVersion
+                         : TvOSVersion ? TvOSVersion : WatchOSVersion)
+                 ->getAsString(Args);
+    }
+    return DarwinPlatform::createOSVersionArg(Darwin::MacOS, OSXVersion);
+  } else if (iOSVersion) {
+    if (TvOSVersion || WatchOSVersion) {
+      TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
+          << iOSVersion->getAsString(Args)
+          << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
+    }
+    return DarwinPlatform::createOSVersionArg(Darwin::IPhoneOS, iOSVersion);
+  } else if (TvOSVersion) {
+    if (WatchOSVersion) {
+      TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
+          << TvOSVersion->getAsString(Args)
+          << WatchOSVersion->getAsString(Args);
+    }
+    return DarwinPlatform::createOSVersionArg(Darwin::TvOS, TvOSVersion);
+  } else if (WatchOSVersion)
+    return DarwinPlatform::createOSVersionArg(Darwin::WatchOS, WatchOSVersion);
+  return None;
+}
+
+/// Returns the deployment target that's specified using the
+/// OS_DEPLOYMENT_TARGET environment variable.
+Optional<DarwinPlatform>
+getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
+                                            const llvm::Triple &Triple) {
+  std::string Targets[Darwin::LastDarwinPlatform + 1];
+  const char *EnvVars[] = {
+      "MACOSX_DEPLOYMENT_TARGET",
+      "IPHONEOS_DEPLOYMENT_TARGET",
+      "TVOS_DEPLOYMENT_TARGET",
+      "WATCHOS_DEPLOYMENT_TARGET",
+  };
+  static_assert(llvm::array_lengthof(EnvVars) == Darwin::LastDarwinPlatform + 1,
+                "Missing platform");
+  for (const auto &I : llvm::enumerate(llvm::makeArrayRef(EnvVars))) {
+    if (char *Env = ::getenv(I.value()))
+      Targets[I.index()] = Env;
+  }
+
+  // Do not allow conflicts with the watchOS target.
+  if (!Targets[Darwin::WatchOS].empty() &&
+      (!Targets[Darwin::IPhoneOS].empty() || !Targets[Darwin::TvOS].empty())) {
+    TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
+        << "WATCHOS_DEPLOYMENT_TARGET"
+        << (!Targets[Darwin::IPhoneOS].empty() ? "IPHONEOS_DEPLOYMENT_TARGET"
+                                               : "TVOS_DEPLOYMENT_TARGET");
+  }
 
-  unsigned Major, Minor, Micro;
-  bool HadExtra;
+  // Do not allow conflicts with the tvOS target.
+  if (!Targets[Darwin::TvOS].empty() && !Targets[Darwin::IPhoneOS].empty()) {
+    TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
+        << "TVOS_DEPLOYMENT_TARGET"
+        << "IPHONEOS_DEPLOYMENT_TARGET";
+  }
 
-  // The iOS deployment target that is explicitly specified via a command line
-  // option or an environment variable.
-  std::string ExplicitIOSDeploymentTargetStr;
-
-  if (iOSVersion)
-    ExplicitIOSDeploymentTargetStr = iOSVersion->getAsString(Args);
-
-  if (OSXVersion && (iOSVersion || TvOSVersion || WatchOSVersion)) {
-    getDriver().Diag(diag::err_drv_argument_not_allowed_with)
-        << OSXVersion->getAsString(Args)
-        << (iOSVersion ? iOSVersion :
-            TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
-    iOSVersion = TvOSVersion = WatchOSVersion = nullptr;
-  } else if (iOSVersion && (TvOSVersion || WatchOSVersion)) {
-    getDriver().Diag(diag::err_drv_argument_not_allowed_with)
-        << iOSVersion->getAsString(Args)
-        << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
-    TvOSVersion = WatchOSVersion = nullptr;
-  } else if (TvOSVersion && WatchOSVersion) {
-     getDriver().Diag(diag::err_drv_argument_not_allowed_with)
-        << TvOSVersion->getAsString(Args)
-        << WatchOSVersion->getAsString(Args);
-    WatchOSVersion = nullptr;
-  } else if (!OSXVersion && !iOSVersion && !TvOSVersion && !WatchOSVersion) {
-    // If no deployment target was specified on the command line, check for
-    // environment defines.
-    std::string OSXTarget;
-    std::string iOSTarget;
-    std::string TvOSTarget;
-    std::string WatchOSTarget;
-
-    if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET"))
-      OSXTarget = env;
-    if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"))
-      iOSTarget = env;
-    if (char *env = ::getenv("TVOS_DEPLOYMENT_TARGET"))
-      TvOSTarget = env;
-    if (char *env = ::getenv("WATCHOS_DEPLOYMENT_TARGET"))
-      WatchOSTarget = env;
-
-    if (!iOSTarget.empty())
-      ExplicitIOSDeploymentTargetStr =
-          std::string("IPHONEOS_DEPLOYMENT_TARGET=") + iOSTarget;
-
-    // If there is no command-line argument to specify the Target version and
-    // no environment variable defined, see if we can set the default based
-    // on -isysroot.
-    if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() &&
-        TvOSTarget.empty() && Args.hasArg(options::OPT_isysroot)) {
-      if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
-        StringRef isysroot = A->getValue();
-        StringRef SDK = getSDKName(isysroot);
-        if (SDK.size() > 0) {
-          // Slice the version number out.
-          // Version number is between the first and the last number.
-          size_t StartVer = SDK.find_first_of("0123456789");
-          size_t EndVer = SDK.find_last_of("0123456789");
-          if (StartVer != StringRef::npos && EndVer > StartVer) {
-            StringRef Version = SDK.slice(StartVer, EndVer + 1);
-            if (SDK.startswith("iPhoneOS") ||
-                SDK.startswith("iPhoneSimulator"))
-              iOSTarget = Version;
-            else if (SDK.startswith("MacOSX"))
-              OSXTarget = getSystemOrSDKMacOSVersion(Version);
-            else if (SDK.startswith("WatchOS") ||
-                     SDK.startswith("WatchSimulator"))
-              WatchOSTarget = Version;
-            else if (SDK.startswith("AppleTVOS") ||
-                     SDK.startswith("AppleTVSimulator"))
-              TvOSTarget = Version;
-          }
-        }
-      }
-    }
+  // Allow conflicts among OSX and iOS for historical reasons, but choose the
+  // default platform.
+  if (!Targets[Darwin::MacOS].empty() &&
+      (!Targets[Darwin::IPhoneOS].empty() ||
+       !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty())) {
+    if (Triple.getArch() == llvm::Triple::arm ||
+        Triple.getArch() == llvm::Triple::aarch64 ||
+        Triple.getArch() == llvm::Triple::thumb)
+      Targets[Darwin::MacOS] = "";
+    else
+      Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
+          Targets[Darwin::TvOS] = "";
+  }
 
-    // If no OS targets have been specified, try to guess platform from -target
-    // or arch name and compute the version from the triple.
-    if (OSXTarget.empty() && iOSTarget.empty() && TvOSTarget.empty() &&
-        WatchOSTarget.empty()) {
-      llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
-
-      // Set the OSTy based on -target if -arch isn't present.
-      if (Args.hasArg(options::OPT_target) && !Args.hasArg(options::OPT_arch)) {
-        OSTy = getTriple().getOS();
-      } else {
-        StringRef MachOArchName = getMachOArchName(Args);
-        if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
-            MachOArchName == "arm64")
-          OSTy = llvm::Triple::IOS;
-        else if (MachOArchName == "armv7k")
-          OSTy = llvm::Triple::WatchOS;
-        else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
-                 MachOArchName != "armv7em")
-          OSTy = llvm::Triple::MacOSX;
-      }
+  for (const auto &Target : llvm::enumerate(llvm::makeArrayRef(Targets))) {
+    if (!Target.value().empty())
+      return DarwinPlatform::createDeploymentTargetEnv(
+          (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
+          Target.value());
+  }
+  return None;
+}
+
+/// Tries to infer the deployment target from the SDK specified by -isysroot
+/// (or SDKROOT).
+Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
+  const Arg *A = Args.getLastArg(options::OPT_isysroot);
+  if (!A)
+    return None;
+  StringRef isysroot = A->getValue();
+  StringRef SDK = Darwin::getSDKName(isysroot);
+  if (!SDK.size())
+    return None;
+  // Slice the version number out.
+  // Version number is between the first and the last number.
+  size_t StartVer = SDK.find_first_of("0123456789");
+  size_t EndVer = SDK.find_last_of("0123456789");
+  if (StartVer != StringRef::npos && EndVer > StartVer) {
+    StringRef Version = SDK.slice(StartVer, EndVer + 1);
+    if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
+      return DarwinPlatform::createFromSDK(Darwin::IPhoneOS, Version);
+    else if (SDK.startswith("MacOSX"))
+      return DarwinPlatform::createFromSDK(Darwin::MacOS,
+                                           getSystemOrSDKMacOSVersion(Version));
+    else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
+      return DarwinPlatform::createFromSDK(Darwin::WatchOS, Version);
+    else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
+      return DarwinPlatform::createFromSDK(Darwin::TvOS, Version);
+  }
+  return None;
+}
 
+std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
+                         const Driver &TheDriver) {
+  unsigned Major, Minor, Micro;
+  switch (OS) {
+  case llvm::Triple::Darwin:
+  case llvm::Triple::MacOSX:
+    if (!Triple.getMacOSXVersion(Major, Minor, Micro))
+      TheDriver.Diag(diag::err_drv_invalid_darwin_version)
+          << Triple.getOSName();
+    break;
+  case llvm::Triple::IOS:
+    Triple.getiOSVersion(Major, Minor, Micro);
+    break;
+  case llvm::Triple::TvOS:
+    Triple.getOSVersion(Major, Minor, Micro);
+    break;
+  case llvm::Triple::WatchOS:
+    Triple.getWatchOSVersion(Major, Minor, Micro);
+    break;
+  default:
+    llvm_unreachable("Unexpected OS type");
+    break;
+  }
 
-      if (OSTy != llvm::Triple::UnknownOS) {
-        unsigned Major, Minor, Micro;
-        std::string *OSTarget;
-
-        switch (OSTy) {
-        case llvm::Triple::Darwin:
-        case llvm::Triple::MacOSX:
-          if (!getTriple().getMacOSXVersion(Major, Minor, Micro))
-            getDriver().Diag(diag::err_drv_invalid_darwin_version)
-                << getTriple().getOSName();
-          OSTarget = &OSXTarget;
-          break;
-        case llvm::Triple::IOS:
-          getTriple().getiOSVersion(Major, Minor, Micro);
-          OSTarget = &iOSTarget;
-          break;
-        case llvm::Triple::TvOS:
-          getTriple().getOSVersion(Major, Minor, Micro);
-          OSTarget = &TvOSTarget;
-          break;
-        case llvm::Triple::WatchOS:
-          getTriple().getWatchOSVersion(Major, Minor, Micro);
-          OSTarget = &WatchOSTarget;
-          break;
-        default:
-          llvm_unreachable("Unexpected OS type");
-          break;
-        }
+  std::string OSVersion;
+  llvm::raw_string_ostream(OSVersion) << Major << '.' << Minor << '.' << Micro;
+  return OSVersion;
+}
 
-        llvm::raw_string_ostream(*OSTarget) << Major << '.' << Minor << '.'
-                                            << Micro;
-      }
-    }
+/// Tries to infer the target OS from the -arch.
+Optional<DarwinPlatform>
+inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
+                              const llvm::Triple &Triple,
+                              const Driver &TheDriver) {
+  llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
+
+  // Set the OSTy based on -target if -arch isn't present.
+  if (Args.hasArg(options::OPT_target) && !Args.hasArg(options::OPT_arch)) {
+    OSTy = Triple.getOS();
+  } else {
+    StringRef MachOArchName = Toolchain.getMachOArchName(Args);
+    if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
+        MachOArchName == "arm64")
+      OSTy = llvm::Triple::IOS;
+    else if (MachOArchName == "armv7k")
+      OSTy = llvm::Triple::WatchOS;
+    else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
+             MachOArchName != "armv7em")
+      OSTy = llvm::Triple::MacOSX;
+  }
+
+  if (OSTy == llvm::Triple::UnknownOS)
+    return None;
+  return DarwinPlatform::createFromArch(OSTy,
+                                        getOSVersion(OSTy, Triple, TheDriver));
+}
 
-    // Do not allow conflicts with the watchOS target.
-    if (!WatchOSTarget.empty() && (!iOSTarget.empty() || !TvOSTarget.empty())) {
-      getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
-        << "WATCHOS_DEPLOYMENT_TARGET"
-        << (!iOSTarget.empty() ? "IPHONEOS_DEPLOYMENT_TARGET" :
-            "TVOS_DEPLOYMENT_TARGET");
-    }
+} // namespace
 
-    // Do not allow conflicts with the tvOS target.
-    if (!TvOSTarget.empty() && !iOSTarget.empty()) {
-      getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
-        << "TVOS_DEPLOYMENT_TARGET"
-        << "IPHONEOS_DEPLOYMENT_TARGET";
-    }
+void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
+  const OptTable &Opts = getDriver().getOpts();
 
-    // Allow conflicts among OSX and iOS for historical reasons, but choose the
-    // default platform.
-    if (!OSXTarget.empty() && (!iOSTarget.empty() ||
-                               !WatchOSTarget.empty() ||
-                               !TvOSTarget.empty())) {
-      if (getTriple().getArch() == llvm::Triple::arm ||
-          getTriple().getArch() == llvm::Triple::aarch64 ||
-          getTriple().getArch() == llvm::Triple::thumb)
-        OSXTarget = "";
-      else
-        iOSTarget = WatchOSTarget = TvOSTarget = "";
-    }
-
-    if (!OSXTarget.empty()) {
-      const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
-      OSXVersion = Args.MakeJoinedArg(nullptr, O, OSXTarget);
-      Args.append(OSXVersion);
-    } else if (!iOSTarget.empty()) {
-      const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
-      iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget);
-      Args.append(iOSVersion);
-    } else if (!TvOSTarget.empty()) {
-      const Option O = Opts.getOption(options::OPT_mtvos_version_min_EQ);
-      TvOSVersion = Args.MakeJoinedArg(nullptr, O, TvOSTarget);
-      Args.append(TvOSVersion);
-    } else if (!WatchOSTarget.empty()) {
-      const Option O = Opts.getOption(options::OPT_mwatchos_version_min_EQ);
-      WatchOSVersion = Args.MakeJoinedArg(nullptr, O, WatchOSTarget);
-      Args.append(WatchOSVersion);
+  // Support allowing the SDKROOT environment variable used by xcrun and other
+  // Xcode tools to define the default sysroot, by making it the default for
+  // isysroot.
+  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+    // Warn if the path does not exist.
+    if (!getVFS().exists(A->getValue()))
+      getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
+  } else {
+    if (char *env = ::getenv("SDKROOT")) {
+      // We only use this value as the default if it is an absolute path,
+      // exists, and it is not the root path.
+      if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
+          StringRef(env) != "/") {
+        Args.append(Args.MakeSeparateArg(
+            nullptr, Opts.getOption(options::OPT_isysroot), env));
+      }
     }
   }
 
-  DarwinPlatformKind Platform;
-  if (OSXVersion)
-    Platform = MacOS;
-  else if (iOSVersion)
-    Platform = IPhoneOS;
-  else if (TvOSVersion)
-    Platform = TvOS;
-  else if (WatchOSVersion)
-    Platform = WatchOS;
-  else
-    llvm_unreachable("Unable to infer Darwin variant");
+  // The OS target can be specified using the -m<os>version-min argument.
+  Optional<DarwinPlatform> OSTarget =
+      getDeploymentTargetFromOSVersionArg(Args, getDriver());
+  // If no deployment target was specified on the command line, check for
+  // environment defines.
+  if (!OSTarget)
+    OSTarget =
+        getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
+  // If there is no command-line argument to specify the Target version and
+  // no environment variable defined, see if we can set the default based
+  // on -isysroot.
+  if (!OSTarget)
+    OSTarget = inferDeploymentTargetFromSDK(Args);
+  // If no OS targets have been specified, try to guess platform from -target
+  // or arch name and compute the version from the triple.
+  if (!OSTarget)
+    OSTarget =
+        inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
+
+  assert(OSTarget && "Unable to infer Darwin variant");
+  OSTarget->addOSVersionMinArgument(Args, Opts);
+  DarwinPlatformKind Platform = OSTarget->getPlatform();
 
+  unsigned Major, Minor, Micro;
+  bool HadExtra;
   // Set the tool chain target information.
   if (Platform == MacOS) {
-    assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) &&
-           "Unknown target platform!");
-    if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro,
-                                   HadExtra) ||
+    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+                                   Micro, HadExtra) ||
         HadExtra || Major != 10 || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSXVersion->getAsString(Args);
+          << OSTarget->getAsString(Args, Opts);
   } else if (Platform == IPhoneOS) {
-    assert(iOSVersion && "Unknown target platform!");
-    if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro,
-                                   HadExtra) ||
+    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+                                   Micro, HadExtra) ||
         HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << iOSVersion->getAsString(Args);
+          << OSTarget->getAsString(Args, Opts);
+    ;
     // For 32-bit targets, the deployment target for iOS has to be earlier than
     // iOS 11.
     if (getTriple().isArch32Bit() && Major >= 11) {
       // If the deployment target is explicitly specified, print a diagnostic.
-      if (!ExplicitIOSDeploymentTargetStr.empty()) {
+      if (OSTarget->isExplicitlySpecified()) {
         getDriver().Diag(diag::warn_invalid_ios_deployment_target)
-            << ExplicitIOSDeploymentTargetStr;
-      // Otherwise, set it to 10.99.99.
+            << OSTarget->getAsString(Args, Opts);
+        // Otherwise, set it to 10.99.99.
       } else {
         Major = 10;
         Minor = 99;
@@ -1428,32 +1547,27 @@ void Darwin::AddDeploymentTarget(Derived
       }
     }
   } else if (Platform == TvOS) {
-    if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor,
-                                   Micro, HadExtra) || HadExtra ||
-        Major >= 100 || Minor >= 100 || Micro >= 100)
+    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+                                   Micro, HadExtra) ||
+        HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << TvOSVersion->getAsString(Args);
+          << OSTarget->getAsString(Args, Opts);
   } else if (Platform == WatchOS) {
-    if (!Driver::GetReleaseVersion(WatchOSVersion->getValue(), Major, Minor,
-                                   Micro, HadExtra) || HadExtra ||
-        Major >= 10 || Minor >= 100 || Micro >= 100)
+    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+                                   Micro, HadExtra) ||
+        HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << WatchOSVersion->getAsString(Args);
+          << OSTarget->getAsString(Args, Opts);
   } else
     llvm_unreachable("unknown kind of Darwin platform");
 
+  DarwinEnvironmentKind Environment = NativeEnvironment;
   // Recognize iOS targets with an x86 architecture as the iOS simulator.
-  if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
-                     getTriple().getArch() == llvm::Triple::x86_64))
-    Platform = IPhoneOSSimulator;
-  if (TvOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
-                      getTriple().getArch() == llvm::Triple::x86_64))
-    Platform = TvOSSimulator;
-  if (WatchOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
-                         getTriple().getArch() == llvm::Triple::x86_64))
-    Platform = WatchOSSimulator;
+  if (Platform != MacOS && (getTriple().getArch() == llvm::Triple::x86 ||
+                            getTriple().getArch() == llvm::Triple::x86_64))
+    Environment = Simulator;
 
-  setTarget(Platform, Major, Minor, Micro);
+  setTarget(Platform, Environment, Major, Minor, Micro);
 
   if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
     StringRef SDK = getSDKName(A->getValue());
@@ -1777,15 +1891,12 @@ bool Darwin::isAlignedAllocationUnavaila
     OS = llvm::Triple::MacOSX;
     break;
   case IPhoneOS:
-  case IPhoneOSSimulator:
     OS = llvm::Triple::IOS;
     break;
-  case TvOS:
-  case TvOSSimulator: // Earlier than 11.0.
+  case TvOS: // Earlier than 11.0.
     OS = llvm::Triple::TvOS;
     break;
-  case WatchOS:
-  case WatchOSSimulator: // Earlier than 4.0.
+  case WatchOS: // Earlier than 4.0.
     OS = llvm::Triple::WatchOS;
     break;
   }

Modified: cfe/trunk/lib/Driver/ToolChains/Darwin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Darwin.h?rev=320235&r1=320234&r2=320235&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/Darwin.h (original)
+++ cfe/trunk/lib/Driver/ToolChains/Darwin.h Fri Dec  8 18:27:11 2017
@@ -268,14 +268,17 @@ public:
   enum DarwinPlatformKind {
     MacOS,
     IPhoneOS,
-    IPhoneOSSimulator,
     TvOS,
-    TvOSSimulator,
     WatchOS,
-    WatchOSSimulator
+    LastDarwinPlatform = WatchOS
+  };
+  enum DarwinEnvironmentKind {
+    NativeEnvironment,
+    Simulator,
   };
 
   mutable DarwinPlatformKind TargetPlatform;
+  mutable DarwinEnvironmentKind TargetEnvironment;
 
   /// The OS version we are targeting.
   mutable VersionTuple TargetVersion;
@@ -317,32 +320,34 @@ protected:
 
   // FIXME: Eliminate these ...Target functions and derive separate tool chains
   // for these targets and put version in constructor.
-  void setTarget(DarwinPlatformKind Platform, unsigned Major, unsigned Minor,
-                 unsigned Micro) const {
+  void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
+                 unsigned Major, unsigned Minor, unsigned Micro) const {
     // FIXME: For now, allow reinitialization as long as values don't
     // change. This will go away when we move away from argument translation.
     if (TargetInitialized && TargetPlatform == Platform &&
+        TargetEnvironment == Environment &&
         TargetVersion == VersionTuple(Major, Minor, Micro))
       return;
 
     assert(!TargetInitialized && "Target already initialized!");
     TargetInitialized = true;
     TargetPlatform = Platform;
+    TargetEnvironment = Environment;
     TargetVersion = VersionTuple(Major, Minor, Micro);
-    if (Platform == IPhoneOSSimulator || Platform == TvOSSimulator ||
-        Platform == WatchOSSimulator)
+    if (Environment == Simulator)
       const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
   }
 
   bool isTargetIPhoneOS() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == IPhoneOS || TargetPlatform == TvOS;
+    return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
+           TargetEnvironment == NativeEnvironment;
   }
 
   bool isTargetIOSSimulator() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == IPhoneOSSimulator ||
-           TargetPlatform == TvOSSimulator;
+    return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
+           TargetEnvironment == Simulator;
   }
 
   bool isTargetIOSBased() const {
@@ -352,32 +357,32 @@ protected:
 
   bool isTargetTvOS() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == TvOS;
+    return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
   }
 
   bool isTargetTvOSSimulator() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == TvOSSimulator;
+    return TargetPlatform == TvOS && TargetEnvironment == Simulator;
   }
 
   bool isTargetTvOSBased() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == TvOS || TargetPlatform == TvOSSimulator;
+    return TargetPlatform == TvOS;
   }
 
   bool isTargetWatchOS() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == WatchOS;
+    return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
   }
 
   bool isTargetWatchOSSimulator() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == WatchOSSimulator;
+    return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
   }
 
   bool isTargetWatchOSBased() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == WatchOS || TargetPlatform == WatchOSSimulator;
+    return TargetPlatform == WatchOS;
   }
 
   bool isTargetMacOS() const {
@@ -413,10 +418,11 @@ protected:
                              Action::OffloadKind DeviceOffloadKind) const override;
 
   StringRef getPlatformFamily() const;
-  static StringRef getSDKName(StringRef isysroot);
   StringRef getOSLibraryNameSuffix() const;
 
 public:
+  static StringRef getSDKName(StringRef isysroot);
+
   /// }
   /// @name ToolChain Implementation
   /// {

Modified: cfe/trunk/test/Driver/darwin-version.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/darwin-version.c?rev=320235&r1=320234&r2=320235&view=diff
==============================================================================
--- cfe/trunk/test/Driver/darwin-version.c (original)
+++ cfe/trunk/test/Driver/darwin-version.c Fri Dec  8 18:27:11 2017
@@ -139,3 +139,8 @@
 // RUN: %clang -target x86_64-apple-watchos4.0 -c %s -### 2>&1 | \
 // RUN: FileCheck --check-prefix=CHECK-VERSION-WATCHOS-TARGET %s
 // CHECK-VERSION-WATCHOS-TARGET: "x86_64-apple-watchos4.0.0-simulator"
+
+// RUN: env MACOSX_DEPLOYMENT_TARGET=1000.1000 \
+// RUN:   %clang -c %s -### 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-VERSION-INVALID-ENV %s
+// CHECK-VERSION-INVALID-ENV: invalid version number in 'MACOSX_DEPLOYMENT_TARGET=1000.1000'




More information about the cfe-commits mailing list