https://github.com/cyndyishida updated 
https://github.com/llvm/llvm-project/pull/142013

>From a12e45e0b3025126dc112c6f8dd552b2670e88f9 Mon Sep 17 00:00:00 2001
From: Cyndy Ishida <cyndy_ish...@apple.com>
Date: Thu, 29 May 2025 12:19:09 -0700
Subject: [PATCH] [clang][Darwin] Simply deployment version assignment in the
 Driver

To be able to handle all of the ways the platform & deployment version can be 
represented in command line flags, the Darwin toolchain holds a type 
DarwinPlatform to help represent them. This patch simplifies the logic by:

reducing the amount of work done between string & version tuples conversions
renaming variables to reduce confusion about what target triple information is 
being manipulated.
allowing implicit transformation of macOS10.16 -> 11, there are other places in 
the compiler where this happens, and it was a bit confusing that the driver 
didn't do that for the cc1 call.
This is not a major refactor, but more simple & common tweaks across the file, 
in hopes to make it more readable.
---
 .../clang/Basic/DiagnosticDriverKinds.td      |   4 +
 clang/lib/Driver/ToolChains/Darwin.cpp        | 291 ++++++++++--------
 clang/test/Driver/darwin-debug-flags.c        |   2 +-
 clang/test/Driver/darwin-version.c            |   8 +-
 4 files changed, 173 insertions(+), 132 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 4da8f80345ddc..20fb47237c56f 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -206,6 +206,7 @@ def err_drv_cannot_open_randomize_layout_seed_file : Error<
   "cannot read randomize layout seed file '%0'">;
 def err_drv_invalid_version_number : Error<
   "invalid version number in '%0'">;
+def err_drv_missing_version_number : Error<"missing version number in '%0'">;
 def err_drv_kcfi_arity_unsupported_target : Error<
   "target '%0' is unsupported by -fsanitize-kcfi-arity">;
 def err_drv_no_linker_llvm_support : Error<
@@ -478,6 +479,9 @@ def warn_ignoring_ftabstop_value : Warning<
 def warn_drv_overriding_option : Warning<
   "overriding '%0' option with '%1'">,
   InGroup<DiagGroup<"overriding-option">>;
+def warn_drv_overriding_deployment_version
+    : Warning<"overriding deployment version from '%0' to '%1'">,
+      InGroup<DiagGroup<"overriding-deployment-version">>;
 def warn_drv_treating_input_as_cxx : Warning<
   "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
   InGroup<Deprecated>;
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index 26e24ad0ab17c..522393c37a7b1 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1709,24 +1709,21 @@ struct DarwinPlatform {
     Environment = Kind;
     InferSimulatorFromArch = false;
   }
+  const VersionTuple &getOSVersion() const { return ResolvedOSVersion; }
 
-  StringRef getOSVersion() const {
-    if (Kind == OSVersionArg)
-      return Argument->getValue();
-    return OSVersion;
+  VersionTuple getCanonicalOSVersion() const {
+    return llvm::Triple::getCanonicalVersionForOS(getOSFromPlatform(Platform),
+                                                  ResolvedOSVersion);
   }
 
-  void setOSVersion(StringRef S) {
-    assert(Kind == TargetArg && "Unexpected kind!");
-    OSVersion = std::string(S);
-  }
+  void setOSVersion(VersionTuple Version) { ResolvedOSVersion = Version; }
 
-  bool hasOSVersion() const { return HasOSVersion; }
+  bool providedOSVersion() const { return ProvidedOSVersion; }
 
-  VersionTuple getNativeTargetVersion() const {
+  VersionTuple getZipperedOSVersion() const {
     assert(Environment == DarwinEnvironmentKind::MacCatalyst &&
-           "native target version is specified only for Mac Catalyst");
-    return NativeTargetVersion;
+           "zippered target version is specified only for Mac Catalyst");
+    return ZipperedOSVersion;
   }
 
   /// Returns true if the target OS was explicitly specified.
@@ -1766,7 +1763,8 @@ struct DarwinPlatform {
       // DriverKit always explicitly provides a version in the triple.
       return;
     }
-    Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
+    Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt),
+                                  ResolvedOSVersion.getAsString());
     Args.append(Argument);
   }
 
@@ -1782,7 +1780,8 @@ struct DarwinPlatform {
       assert(Argument && "OS version argument not yet inferred");
       return Argument->getAsString(Args);
     case DeploymentTargetEnv:
-      return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
+      return (llvm::Twine(EnvVarName) + "=" + ResolvedOSVersion.getAsString())
+          .str();
     }
     llvm_unreachable("Unsupported Darwin Source Kind");
   }
@@ -1797,13 +1796,13 @@ struct DarwinPlatform {
     case llvm::Triple::MacABI: {
       Environment = DarwinEnvironmentKind::MacCatalyst;
       // The minimum native macOS target for MacCatalyst is macOS 10.15.
-      NativeTargetVersion = VersionTuple(10, 15);
-      if (HasOSVersion && SDKInfo) {
+      ZipperedOSVersion = VersionTuple(10, 15);
+      if (providedOSVersion() && SDKInfo) {
         if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
                 DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
           if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
-                  OSVersion, NativeTargetVersion, std::nullopt)) {
-            NativeTargetVersion = *MacOSVersion;
+                  OSVersion, ZipperedOSVersion, std::nullopt)) {
+            ZipperedOSVersion = *MacOSVersion;
           }
         }
       }
@@ -1813,8 +1812,8 @@ struct DarwinPlatform {
       if (TargetVariantTriple) {
         auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
         if (TargetVariantVersion.getMajor()) {
-          if (TargetVariantVersion < NativeTargetVersion)
-            NativeTargetVersion = TargetVariantVersion;
+          if (TargetVariantVersion < ZipperedOSVersion)
+            ZipperedOSVersion = TargetVariantVersion;
         }
       }
       break;
@@ -1825,14 +1824,12 @@ struct DarwinPlatform {
   }
 
   static DarwinPlatform
-  createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
+  createFromTarget(const llvm::Triple &TT, Arg *A,
                    std::optional<llvm::Triple> TargetVariantTriple,
                    const std::optional<DarwinSDKInfo> &SDKInfo) {
-    DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
-                          A);
+    DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()),
+                          TT.getOSVersion(), A);
     VersionTuple OsVersion = TT.getOSVersion();
-    if (OsVersion.getMajor() == 0)
-      Result.HasOSVersion = false;
     Result.TargetVariantTriple = TargetVariantTriple;
     Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
     return Result;
@@ -1841,38 +1838,40 @@ struct DarwinPlatform {
   createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
                       llvm::Triple::EnvironmentType Environment, Arg *A,
                       const std::optional<DarwinSDKInfo> &SDKInfo) {
-    DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
-                          OSVersion.getAsString(), A);
+    DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS), OSVersion, A);
     Result.InferSimulatorFromArch = false;
     Result.setEnvironment(Environment, OSVersion, SDKInfo);
     return Result;
   }
   static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,
                                            bool IsSimulator) {
-    DarwinPlatform Result{OSVersionArg, Platform, A};
+    DarwinPlatform Result{OSVersionArg, Platform,
+                          getVersionFromString(A->getValue()), A};
     if (IsSimulator)
       Result.Environment = DarwinEnvironmentKind::Simulator;
     return Result;
   }
   static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
                                                   StringRef EnvVarName,
-                                                  StringRef Value) {
-    DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
+                                                  StringRef OSVersion) {
+    DarwinPlatform Result(DeploymentTargetEnv, Platform,
+                          getVersionFromString(OSVersion));
     Result.EnvVarName = EnvVarName;
     return Result;
   }
   static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
                                       StringRef Value,
                                       bool IsSimulator = false) {
-    DarwinPlatform Result(InferredFromSDK, Platform, Value);
+    DarwinPlatform Result(InferredFromSDK, Platform,
+                          getVersionFromString(Value));
     if (IsSimulator)
       Result.Environment = DarwinEnvironmentKind::Simulator;
     Result.InferSimulatorFromArch = false;
     return Result;
   }
   static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
-                                       StringRef Value) {
-    return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
+                                       VersionTuple Version) {
+    return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Version);
   }
 
   /// Constructs an inferred SDKInfo value based on the version inferred from
@@ -1880,22 +1879,27 @@ struct DarwinPlatform {
   /// the platform from the SDKPath.
   DarwinSDKInfo inferSDKInfo() {
     assert(Kind == InferredFromSDK && "can infer SDK info only");
-    llvm::VersionTuple Version;
-    bool IsValid = !Version.tryParse(OSVersion);
-    (void)IsValid;
-    assert(IsValid && "invalid SDK version");
-    return DarwinSDKInfo(
-        Version,
-        /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99),
-        getOSFromPlatform(Platform));
+    return DarwinSDKInfo(ResolvedOSVersion,
+                         /*MaximumDeploymentTarget=*/
+                         VersionTuple(ResolvedOSVersion.getMajor(), 0, 99),
+                         getOSFromPlatform(Platform));
   }
 
 private:
   DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
       : Kind(Kind), Platform(Platform), Argument(Argument) {}
-  DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
-                 Arg *Argument = nullptr)
-      : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}
+  DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform,
+                 VersionTuple Value, Arg *Argument = nullptr)
+      : Kind(Kind), Platform(Platform), ResolvedOSVersion(Value),
+        ProvidedOSVersion(!Value.empty()), Argument(Argument) {}
+
+  static VersionTuple getVersionFromString(const StringRef Input) {
+    llvm::VersionTuple Version;
+    bool IsValid = !Version.tryParse(Input);
+    assert(IsValid && "unable to convert input version to version tuple");
+    (void)IsValid;
+    return Version;
+  }
 
   static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
     switch (OS) {
@@ -1938,11 +1942,22 @@ struct DarwinPlatform {
   SourceKind Kind;
   DarwinPlatformKind Platform;
   DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
-  VersionTuple NativeTargetVersion;
-  std::string OSVersion;
-  bool HasOSVersion = true, InferSimulatorFromArch = true;
+  // When compiling for a zippered target, this means both target &
+  // target variant is set on the command line, ZipperedOSVersion holds the
+  // OSVersion tied to the main target value.
+  VersionTuple ZipperedOSVersion;
+  // We allow multiple ways to set or default the OS
+  // version used for compilation. The ResolvedOSVersion always represents what
+  // will be used.
+  VersionTuple ResolvedOSVersion;
+  // Track whether the OS deployment version was explicitly set on creation.
+  // This can be used for overidding the resolved version or error reporting.
+  bool ProvidedOSVersion = false;
+  bool InferSimulatorFromArch = true;
   Arg *Argument;
   StringRef EnvVarName;
+  // When compiling for a zippered target, this value represents the target
+  // triple encoded in the target variant.
   std::optional<llvm::Triple> TargetVariantTriple;
 };
 
@@ -1960,6 +1975,19 @@ getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
   Arg *WatchOSVersion =
       Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
                       options::OPT_mwatchos_simulator_version_min_EQ);
+
+  auto GetDarwinPlatform =
+      [&](DarwinPlatform::DarwinPlatformKind Platform, Arg *VersionArg,
+          bool IsSimulator) -> std::optional<DarwinPlatform> {
+    if (StringRef(VersionArg->getValue()).empty()) {
+      TheDriver.Diag(diag::err_drv_missing_version_number)
+          << VersionArg->getAsString(Args);
+      return std::nullopt;
+    }
+    return DarwinPlatform::createOSVersionArg(Platform, VersionArg,
+                                              /*IsSimulator=*/IsSimulator);
+  };
+
   if (macOSVersion) {
     if (iOSVersion || TvOSVersion || WatchOSVersion) {
       TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
@@ -1968,30 +1996,29 @@ getDeploymentTargetFromOSVersionArg(DerivedArgList 
&Args,
                          : TvOSVersion ? TvOSVersion : WatchOSVersion)
                  ->getAsString(Args);
     }
-    return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion,
-                                              /*IsSimulator=*/false);
+    return GetDarwinPlatform(Darwin::MacOS, macOSVersion,
+                             /*IsSimulator=*/false);
+
   } 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,
-        iOSVersion->getOption().getID() ==
-            options::OPT_mios_simulator_version_min_EQ);
+    return GetDarwinPlatform(Darwin::IPhoneOS, iOSVersion,
+                             iOSVersion->getOption().getID() ==
+                                 options::OPT_mios_simulator_version_min_EQ);
   } 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,
-        TvOSVersion->getOption().getID() ==
-            options::OPT_mtvos_simulator_version_min_EQ);
+    return GetDarwinPlatform(Darwin::TvOS, TvOSVersion,
+                             TvOSVersion->getOption().getID() ==
+                                 options::OPT_mtvos_simulator_version_min_EQ);
   } else if (WatchOSVersion)
-    return DarwinPlatform::createOSVersionArg(
+    return GetDarwinPlatform(
         Darwin::WatchOS, WatchOSVersion,
         WatchOSVersion->getOption().getID() ==
             options::OPT_mwatchos_simulator_version_min_EQ);
@@ -2125,8 +2152,8 @@ inferDeploymentTargetFromSDK(DerivedArgList &Args,
   return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
 }
 
-std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
-                         const Driver &TheDriver) {
+VersionTuple getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
+                          const Driver &TheDriver) {
   VersionTuple OsVersion;
   llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
   switch (OS) {
@@ -2165,12 +2192,7 @@ std::string getOSVersion(llvm::Triple::OSType OS, const 
llvm::Triple &Triple,
     llvm_unreachable("Unexpected OS type");
     break;
   }
-
-  std::string OSVersion;
-  llvm::raw_string_ostream(OSVersion)
-      << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'
-      << OsVersion.getSubminor().value_or(0);
-  return OSVersion;
+  return OsVersion;
 }
 
 /// Tries to infer the target OS from the -arch.
@@ -2206,7 +2228,7 @@ std::optional<DarwinPlatform> 
getDeploymentTargetFromTargetArg(
   if (Triple.getOS() == llvm::Triple::Darwin ||
       Triple.getOS() == llvm::Triple::UnknownOS)
     return std::nullopt;
-  std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
+  VersionTuple OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
   std::optional<llvm::Triple> TargetVariantTriple;
   for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
     llvm::Triple TVT(A->getValue());
@@ -2232,9 +2254,14 @@ std::optional<DarwinPlatform> 
getDeploymentTargetFromTargetArg(
           << A->getSpelling() << A->getValue();
     }
   }
-  return DarwinPlatform::createFromTarget(Triple, OSVersion,
-                                          Args.getLastArg(options::OPT_target),
-                                          TargetVariantTriple, SDKInfo);
+  DarwinPlatform DP = DarwinPlatform::createFromTarget(
+      Triple, Args.getLastArg(options::OPT_target), TargetVariantTriple,
+      SDKInfo);
+
+  // Override the OSVersion if it doesn't match the one from the triple.
+  if (Triple.getOSVersion() != OSVersion)
+    DP.setOSVersion(OSVersion);
+  return DP;
 }
 
 /// Returns the deployment target that's specified using the -mtargetos option.
@@ -2313,12 +2340,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) 
const {
   SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
 
   // The OS and the version can be specified using the -target argument.
-  std::optional<DarwinPlatform> OSTarget =
+  std::optional<DarwinPlatform> DP =
       getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), 
SDKInfo);
-  if (OSTarget) {
+  if (DP) {
     // Disallow mixing -target and -mtargetos=.
     if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) 
{
-      std::string TargetArgStr = OSTarget->getAsString(Args, Opts);
+      std::string TargetArgStr = DP->getAsString(Args, Opts);
       std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
       getDriver().Diag(diag::err_drv_cannot_mix_options)
           << TargetArgStr << MTargetOSArgStr;
@@ -2330,102 +2357,112 @@ void Darwin::AddDeploymentTarget(DerivedArgList 
&Args) const {
       bool TargetExtra;
       unsigned ArgMajor, ArgMinor, ArgMicro;
       bool ArgExtra;
-      if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
-          (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
-                                     TargetMinor, TargetMicro, TargetExtra) &&
-           Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
-                                     ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
+      if (DP->getPlatform() != OSVersionArgTarget->getPlatform() ||
+          (Driver::GetReleaseVersion(DP->getOSVersion().getAsString(),
+                                     TargetMajor, TargetMinor, TargetMicro,
+                                     TargetExtra) &&
+           Driver::GetReleaseVersion(
+               OSVersionArgTarget->getOSVersion().getAsString(), ArgMajor,
+               ArgMinor, ArgMicro, ArgExtra) &&
            (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
                 VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
             TargetExtra != ArgExtra))) {
         // Select the OS version from the -m<os>-version-min argument when
         // the -target does not include an OS version.
-        if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
-            !OSTarget->hasOSVersion()) {
-          OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
+        if (DP->getPlatform() == OSVersionArgTarget->getPlatform() &&
+            !DP->providedOSVersion()) {
+          DP->setOSVersion(OSVersionArgTarget->getOSVersion());
         } else {
           // Warn about -m<os>-version-min that doesn't match the OS version
           // that's specified in the target.
           std::string OSVersionArg =
               OSVersionArgTarget->getAsString(Args, Opts);
-          std::string TargetArg = OSTarget->getAsString(Args, Opts);
+          std::string TargetArg = DP->getAsString(Args, Opts);
           getDriver().Diag(clang::diag::warn_drv_overriding_option)
               << OSVersionArg << TargetArg;
         }
       }
     }
-  } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
-                                                             SDKInfo))) {
+  } else if ((DP = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
+                                                       SDKInfo))) {
     // The OS target can be specified using the -mtargetos= argument.
     // Disallow mixing -mtargetos= and -m<os>version-min=.
     std::optional<DarwinPlatform> OSVersionArgTarget =
         getDeploymentTargetFromOSVersionArg(Args, getDriver());
     if (OSVersionArgTarget) {
-      std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);
+      std::string MTargetOSArgStr = DP->getAsString(Args, Opts);
       std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, 
Opts);
       getDriver().Diag(diag::err_drv_cannot_mix_options)
           << MTargetOSArgStr << OSVersionArgStr;
     }
   } else {
     // The OS target can be specified using the -m<os>version-min argument.
-    OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
+    DP = getDeploymentTargetFromOSVersionArg(Args, getDriver());
     // If no deployment target was specified on the command line, check for
     // environment defines.
-    if (!OSTarget) {
-      OSTarget =
+    if (!DP) {
+      DP =
           getDeploymentTargetFromEnvironmentVariables(getDriver(), 
getTriple());
-      if (OSTarget) {
+      if (DP) {
         // Don't infer simulator from the arch when the SDK is also specified.
         std::optional<DarwinPlatform> SDKTarget =
             inferDeploymentTargetFromSDK(Args, SDKInfo);
         if (SDKTarget)
-          OSTarget->setEnvironment(SDKTarget->getEnvironment());
+          DP->setEnvironment(SDKTarget->getEnvironment());
       }
     }
     // 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 using SDKSettings.json if it exists.
-    if (!OSTarget) {
-      OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
+    if (!DP) {
+      DP = inferDeploymentTargetFromSDK(Args, SDKInfo);
       /// If the target was successfully constructed from the SDK path, try to
       /// infer the SDK info if the SDK doesn't have it.
-      if (OSTarget && !SDKInfo)
-        SDKInfo = OSTarget->inferSDKInfo();
+      if (DP && !SDKInfo)
+        SDKInfo = DP->inferSDKInfo();
     }
     // 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());
+    if (!DP)
+      DP = inferDeploymentTargetFromArch(Args, *this, getTriple(), 
getDriver());
+  }
+
+  assert(DP && "Unable to infer Darwin variant");
+  // After the deployment OS version has been resolved, set it to the canonical
+  // version before further error detection and converting to a proper target
+  // triple.
+  VersionTuple CanonicalVersion = DP->getCanonicalOSVersion();
+  if (CanonicalVersion != DP->getOSVersion()) {
+    getDriver().Diag(diag::warn_drv_overriding_deployment_version)
+        << DP->getOSVersion().getAsString() << CanonicalVersion.getAsString();
+    DP->setOSVersion(CanonicalVersion);
   }
 
-  assert(OSTarget && "Unable to infer Darwin variant");
-  OSTarget->addOSVersionMinArgument(Args, Opts);
-  DarwinPlatformKind Platform = OSTarget->getPlatform();
+  DP->addOSVersionMinArgument(Args, Opts);
+  DarwinPlatformKind Platform = DP->getPlatform();
 
   unsigned Major, Minor, Micro;
   bool HadExtra;
   // The major version should not be over this number.
   const unsigned MajorVersionLimit = 1000;
+  const std::string DPVersion = DP->getOSVersion().getAsString();
   // Set the tool chain target information.
   if (Platform == MacOS) {
-    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
-                                   Micro, HadExtra) ||
+    if (!Driver::GetReleaseVersion(DPVersion, Major, Minor, Micro, HadExtra) ||
         HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
         Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSTarget->getAsString(Args, Opts);
+          << DP->getAsString(Args, Opts);
   } else if (Platform == IPhoneOS) {
-    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
-                                   Micro, HadExtra) ||
+    if (!Driver::GetReleaseVersion(DPVersion, Major, Minor, Micro, HadExtra) ||
         HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSTarget->getAsString(Args, Opts);
+          << DP->getAsString(Args, Opts);
     ;
-    if (OSTarget->getEnvironment() == MacCatalyst &&
+    if (DP->getEnvironment() == MacCatalyst &&
         (Major < 13 || (Major == 13 && Minor < 1))) {
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSTarget->getAsString(Args, Opts);
+          << DP->getAsString(Args, Opts);
       Major = 13;
       Minor = 1;
       Micro = 0;
@@ -2434,12 +2471,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) 
const {
     // iOS 11.
     if (getTriple().isArch32Bit() && Major >= 11) {
       // If the deployment target is explicitly specified, print a diagnostic.
-      if (OSTarget->isExplicitlySpecified()) {
-        if (OSTarget->getEnvironment() == MacCatalyst)
+      if (DP->isExplicitlySpecified()) {
+        if (DP->getEnvironment() == MacCatalyst)
           getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
         else
           getDriver().Diag(diag::warn_invalid_ios_deployment_target)
-              << OSTarget->getAsString(Args, Opts);
+              << DP->getAsString(Args, Opts);
         // Otherwise, set it to 10.99.99.
       } else {
         Major = 10;
@@ -2448,46 +2485,42 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) 
const {
       }
     }
   } else if (Platform == TvOS) {
-    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
-                                   Micro, HadExtra) ||
+    if (!Driver::GetReleaseVersion(DPVersion, Major, Minor, Micro, HadExtra) ||
         HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSTarget->getAsString(Args, Opts);
+          << DP->getAsString(Args, Opts);
   } else if (Platform == WatchOS) {
-    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
-                                   Micro, HadExtra) ||
+    if (!Driver::GetReleaseVersion(DPVersion, Major, Minor, Micro, HadExtra) ||
         HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSTarget->getAsString(Args, Opts);
+          << DP->getAsString(Args, Opts);
   } else if (Platform == DriverKit) {
-    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
-                                   Micro, HadExtra) ||
+    if (!Driver::GetReleaseVersion(DPVersion, Major, Minor, Micro, HadExtra) ||
         HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
         Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSTarget->getAsString(Args, Opts);
+          << DP->getAsString(Args, Opts);
   } else if (Platform == XROS) {
-    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
-                                   Micro, HadExtra) ||
+    if (!Driver::GetReleaseVersion(DPVersion, Major, Minor, Micro, HadExtra) ||
         HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||
         Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
-          << OSTarget->getAsString(Args, Opts);
+          << DP->getAsString(Args, Opts);
   } else
     llvm_unreachable("unknown kind of Darwin platform");
 
-  DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
+  DarwinEnvironmentKind Environment = DP->getEnvironment();
   // Recognize iOS targets with an x86 architecture as the iOS simulator.
   if (Environment == NativeEnvironment && Platform != MacOS &&
-      Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&
+      Platform != DriverKit && DP->canInferSimulatorFromArch() &&
       getTriple().isX86())
     Environment = Simulator;
 
-  VersionTuple NativeTargetVersion;
+  VersionTuple ZipperedOSVersion;
   if (Environment == MacCatalyst)
-    NativeTargetVersion = OSTarget->getNativeTargetVersion();
-  setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
-  TargetVariantTriple = OSTarget->getTargetVariantTriple();
+    ZipperedOSVersion = DP->getZipperedOSVersion();
+  setTarget(Platform, Environment, Major, Minor, Micro, ZipperedOSVersion);
+  TargetVariantTriple = DP->getTargetVariantTriple();
 
   if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
     StringRef SDK = getSDKName(A->getValue());
diff --git a/clang/test/Driver/darwin-debug-flags.c 
b/clang/test/Driver/darwin-debug-flags.c
index 918ee345658a0..90209bb179bfc 100644
--- a/clang/test/Driver/darwin-debug-flags.c
+++ b/clang/test/Driver/darwin-debug-flags.c
@@ -7,7 +7,7 @@
 // CHECK-SAME:                flags:
 // CHECK-SAME:                -I path\\ with\\ \\\\spaces
 // CHECK-SAME:                -g -Os
-// CHECK-SAME:                -mmacos-version-min=10.7.0
+// CHECK-SAME:                -mmacos-version-min=10.7
 
 int x;
 
diff --git a/clang/test/Driver/darwin-version.c 
b/clang/test/Driver/darwin-version.c
index a00bd832dc802..9b9c6034bb75d 100644
--- a/clang/test/Driver/darwin-version.c
+++ b/clang/test/Driver/darwin-version.c
@@ -86,7 +86,7 @@
 // RUN:   FileCheck --check-prefix=CHECK-VERSION-MISSING %s
 // RUN: not %clang -target x86_64-apple-darwin -mmacos-version-min= -c %s -### 
2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK-VERSION-MISSING %s
-// CHECK-VERSION-MISSING: invalid version number
+// CHECK-VERSION-MISSING: missing version number
 // RUN: %clang -target armv7k-apple-darwin -mwatchos-version-min=2.0 -c %s 
-### 2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK-VERSION-WATCHOS20 %s
 // RUN: %clang -target armv7-apple-darwin -mtvos-version-min=8.3 -c %s -### 
2>&1 | \
@@ -330,9 +330,13 @@
 // RUN:   FileCheck --check-prefix=CHECK-MACOS11 %s
 // RUN: %clang -target x86_64-apple-darwin -mmacos-version-min=11 -c %s -### 
2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK-MACOS11 %s
-
 // CHECK-MACOS11: "x86_64-apple-macosx11.0.0"
 
+// RUN: %clang -target arm64-apple-macosx10.16 -c %s -### 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-IMPLICIT-MACOS11 %s
+// CHECK-IMPLICIT-MACOS11: warning: overriding deployment version
+// CHECK-IMPLICIT-MACOS11: "arm64-apple-macosx11.0.0"
+
 // RUN: %clang -target arm64-apple-macos999 -c %s -### 2>&1 | \
 // RUN:   FileCheck --check-prefix=CHECK-MACOS999 %s
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to