Support watchOS and tvOS driver options

This patch should add support for almost all command-line options and
driver tinkering necessary to produce a correct "clang -cc1"
invocation for watchOS and tvOS.

llvm-svn: 251706
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index fb5d38a..603273f 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2225,6 +2225,8 @@
     case llvm::Triple::Darwin:
     case llvm::Triple::MacOSX:
     case llvm::Triple::IOS:
+    case llvm::Triple::TvOS:
+    case llvm::Triple::WatchOS:
       TC = new toolchains::DarwinClang(*this, Target, Args);
       break;
     case llvm::Triple::DragonFly:
diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp
index dbd85c0..d7b0ad1 100644
--- a/clang/lib/Driver/ToolChains.cpp
+++ b/clang/lib/Driver/ToolChains.cpp
@@ -67,6 +67,10 @@
 
 /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
 ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
+  if (isTargetWatchOSBased())
+    // FIXME: not quite iOS because of version mismatch. Choose something for
+    // now.
+    return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
   if (isTargetIOSBased())
     return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
   if (isNonFragile)
@@ -76,7 +80,9 @@
 
 /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
 bool Darwin::hasBlocksRuntime() const {
-  if (isTargetIOSBased())
+  if (isTargetWatchOSBased())
+    return true;
+  else if (isTargetIOSBased())
     return !isIPhoneOSVersionLT(3, 2);
   else {
     assert(isTargetMacOS() && "unexpected darwin target");
@@ -178,7 +184,14 @@
     return Triple.getTriple();
 
   SmallString<16> Str;
-  Str += isTargetIOSBased() ? "ios" : "macosx";
+  if (isTargetWatchOSBased())
+    Str += "watchos";
+  else if (isTargetTvOSBased())
+    Str += "tvos";
+  else if (isTargetIOSBased())
+    Str += "ios";
+  else
+    Str += "macosx";
   Str += getTargetVersion().getAsString();
   Triple.setOSName(Str);
 
@@ -217,16 +230,17 @@
     : Darwin(D, Triple, Args) {}
 
 void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
-  // For iOS, 64-bit, promote certain warnings to errors.
-  if (!isTargetMacOS() && getTriple().isArch64Bit()) {
+  // For modern targets, promote certain warnings to errors.
+  if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
     // Always enable -Wdeprecated-objc-isa-usage and promote it
     // to an error.
     CC1Args.push_back("-Wdeprecated-objc-isa-usage");
     CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
 
-    // Also error about implicit function declarations, as that
-    // can impact calling conventions.
-    CC1Args.push_back("-Werror=implicit-function-declaration");
+    // For iOS and watchOS, also error about implicit function declarations,
+    // as that can impact calling conventions.
+    if (!isTargetMacOS())
+      CC1Args.push_back("-Werror=implicit-function-declaration");
   }
 }
 
@@ -254,7 +268,15 @@
   llvm::sys::path::remove_filename(P); // 'bin'
   llvm::sys::path::append(P, "lib", "arc", "libarclite_");
   // Mash in the platform.
-  if (isTargetIOSSimulator())
+  if (isTargetWatchOSSimulator())
+    P += "watchsimulator";
+  else if (isTargetWatchOS())
+    P += "watchos";
+  else if (isTargetTvOSSimulator())
+    P += "appletvsimulator";
+  else if (isTargetTvOS())
+    P += "appletvos";
+  else if (isTargetIOSSimulator())
     P += "iphonesimulator";
   else if (isTargetIPhoneOS())
     P += "iphoneos";
@@ -321,6 +343,7 @@
     // Sanitizer runtime libraries requires C++.
     AddCXXStdlibLibArgs(Args, CmdArgs);
   }
+  // ASan is not supported on watchOS.
   assert(isTargetMacOS() || isTargetIOSSimulator());
   StringRef OS = isTargetMacOS() ? "osx" : "iossim";
   AddLinkRuntimeLib(
@@ -374,7 +397,13 @@
   CmdArgs.push_back("-lSystem");
 
   // Select the dynamic runtime library and the target specific static library.
-  if (isTargetIOSBased()) {
+  if (isTargetWatchOSBased()) {
+    // We currently always need a static runtime library for watchOS.
+    AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.watchos.a");
+  } else if (isTargetTvOSBased()) {
+    // We currently always need a static runtime library for tvOS.
+    AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.tvos.a");
+  } else if (isTargetIOSBased()) {
     // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
     // it never went into the SDK.
     // Linking against libgcc_s.1 isn't needed for iOS 5.0+
@@ -435,25 +464,46 @@
 
   Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
   Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
+  Arg *TvOSVersion = Args.getLastArg(options::OPT_mtvos_version_min_EQ);
+  Arg *WatchOSVersion = Args.getLastArg(options::OPT_mwatchos_version_min_EQ);
 
-  if (OSXVersion && iOSVersion) {
+  if (OSXVersion && (iOSVersion || TvOSVersion || WatchOSVersion)) {
     getDriver().Diag(diag::err_drv_argument_not_allowed_with)
-        << OSXVersion->getAsString(Args) << iOSVersion->getAsString(Args);
-    iOSVersion = nullptr;
-  } else if (!OSXVersion && !iOSVersion) {
+        << 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 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 (iOSTarget.empty() && OSXTarget.empty() &&
+    if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() &&
         Args.hasArg(options::OPT_isysroot)) {
       if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
         StringRef isysroot = A->getValue();
@@ -473,6 +523,12 @@
               iOSTarget = Version;
             else if (SDK.startswith("MacOSX"))
               OSXTarget = Version;
+            else if (SDK.startswith("WatchOS") ||
+                     SDK.startswith("WatchSimulator"))
+              WatchOSTarget = Version;
+            else if (SDK.startswith("AppleTVOS") ||
+                     SDK.startswith("AppleTVSimulator"))
+              TvOSTarget = Version;
           }
         }
       }
@@ -480,7 +536,8 @@
 
     // If no OSX or iOS target has been specified, try to guess platform
     // from arch name and compute the version from the triple.
-    if (OSXTarget.empty() && iOSTarget.empty()) {
+    if (OSXTarget.empty() && iOSTarget.empty() && TvOSTarget.empty() &&
+        WatchOSTarget.empty()) {
       StringRef MachOArchName = getMachOArchName(Args);
       unsigned Major, Minor, Micro;
       if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
@@ -488,6 +545,10 @@
         getTriple().getiOSVersion(Major, Minor, Micro);
         llvm::raw_string_ostream(iOSTarget) << Major << '.' << Minor << '.'
                                             << Micro;
+      } else if (MachOArchName == "armv7k") {
+        getTriple().getWatchOSVersion(Major, Minor, Micro);
+        llvm::raw_string_ostream(WatchOSTarget) << Major << '.' << Minor << '.'
+                                                << Micro;
       } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
                  MachOArchName != "armv7em") {
         if (!getTriple().getMacOSXVersion(Major, Minor, Micro)) {
@@ -499,15 +560,32 @@
       }
     }
 
+    // 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");
+    }
+
+    // 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";
+    }
+
     // Allow conflicts among OSX and iOS for historical reasons, but choose the
     // default platform.
-    if (!OSXTarget.empty() && !iOSTarget.empty()) {
+    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 = "";
+        iOSTarget = WatchOSTarget = TvOSTarget = "";
     }
 
     if (!OSXTarget.empty()) {
@@ -518,6 +596,14 @@
       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);
     }
   }
 
@@ -526,6 +612,10 @@
     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");
 
@@ -533,7 +623,8 @@
   unsigned Major, Minor, Micro;
   bool HadExtra;
   if (Platform == MacOS) {
-    assert(!iOSVersion && "Unknown target platform!");
+    assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) &&
+           "Unknown target platform!");
     if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro,
                                    HadExtra) ||
         HadExtra || Major != 10 || Minor >= 100 || Micro >= 100)
@@ -546,6 +637,18 @@
         HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
           << iOSVersion->getAsString(Args);
+  } else if (Platform == TvOS) {
+    if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor,
+                                   Micro, HadExtra) || HadExtra ||
+        Major >= 10 || Minor >= 100 || Micro >= 100)
+      getDriver().Diag(diag::err_drv_invalid_version_number)
+          << TvOSVersion->getAsString(Args);
+  } else if (Platform == WatchOS) {
+    if (!Driver::GetReleaseVersion(WatchOSVersion->getValue(), Major, Minor,
+                                   Micro, HadExtra) || HadExtra ||
+        Major >= 10 || Minor >= 100 || Micro >= 100)
+      getDriver().Diag(diag::err_drv_invalid_version_number)
+          << WatchOSVersion->getAsString(Args);
   } else
     llvm_unreachable("unknown kind of Darwin platform");
 
@@ -553,6 +656,12 @@
   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;
 
   setTarget(Platform, Major, Minor, Micro);
 }
@@ -613,7 +722,11 @@
   llvm::sys::path::append(P, "lib", "darwin");
 
   // Use the newer cc_kext for iOS ARM after 6.0.
-  if (isTargetIPhoneOS()) {
+  if (isTargetWatchOS()) {
+    llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
+  } else if (isTargetTvOS()) {
+    llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
+  } else if (isTargetIPhoneOS()) {
     llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
   } else {
     llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
@@ -874,8 +987,9 @@
   // FIXME: It would be far better to avoid inserting those -static arguments,
   // but we can't check the deployment target in the translation code until
   // it is set here.
-  if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0)) {
-    for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie;) {
+  if (isTargetWatchOSBased() ||
+      (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
+    for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
       Arg *A = *it;
       ++it;
       if (A->getOption().getID() != options::OPT_mkernel &&
@@ -891,7 +1005,8 @@
 
   // Default to use libc++ on OS X 10.9+ and iOS 7+.
   if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
-       (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0))) &&
+       (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
+       isTargetWatchOSBased()) &&
       !Args.getLastArg(options::OPT_stdlib_EQ))
     DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ),
                       "libc++");
@@ -948,7 +1063,15 @@
                                ArgStringList &CmdArgs) const {
   VersionTuple TargetVersion = getTargetVersion();
 
-  if (isTargetIOSSimulator())
+  if (isTargetWatchOS())
+    CmdArgs.push_back("-watchos_version_min");
+  else if (isTargetWatchOSSimulator())
+    CmdArgs.push_back("-watchos_simulator_version_min");
+  else if (isTargetTvOS())
+    CmdArgs.push_back("-tvos_version_min");
+  else if (isTargetTvOSSimulator())
+    CmdArgs.push_back("-tvos_simulator_version_min");
+  else if (isTargetIOSSimulator())
     CmdArgs.push_back("-ios_simulator_version_min");
   else if (isTargetIOSBased())
     CmdArgs.push_back("-iphoneos_version_min");
@@ -965,7 +1088,9 @@
   // Derived from startfile spec.
   if (Args.hasArg(options::OPT_dynamiclib)) {
     // Derived from darwin_dylib1 spec.
-    if (isTargetIOSSimulator()) {
+    if (isTargetWatchOSBased()) {
+      ; // watchOS does not need dylib1.o.
+    } else if (isTargetIOSSimulator()) {
       ; // iOS simulator does not need dylib1.o.
     } else if (isTargetIPhoneOS()) {
       if (isIPhoneOSVersionLT(3, 1))
@@ -980,7 +1105,9 @@
     if (Args.hasArg(options::OPT_bundle)) {
       if (!Args.hasArg(options::OPT_static)) {
         // Derived from darwin_bundle1 spec.
-        if (isTargetIOSSimulator()) {
+        if (isTargetWatchOSBased()) {
+          ; // watchOS does not need bundle1.o.
+        } else if (isTargetIOSSimulator()) {
           ; // iOS simulator does not need bundle1.o.
         } else if (isTargetIPhoneOS()) {
           if (isIPhoneOSVersionLT(3, 1))
@@ -1015,7 +1142,9 @@
           CmdArgs.push_back("-lcrt0.o");
         } else {
           // Derived from darwin_crt1 spec.
-          if (isTargetIOSSimulator()) {
+          if (isTargetWatchOSBased()) {
+            ; // watchOS does not need crt1.o.
+          } else if (isTargetIOSSimulator()) {
             ; // iOS simulator does not need crt1.o.
           } else if (isTargetIPhoneOS()) {
             if (getArch() == llvm::Triple::aarch64)
@@ -1040,6 +1169,7 @@
   }
 
   if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) &&
+      !isTargetWatchOS() &&
       isMacosxVersionLT(10, 5)) {
     const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
     CmdArgs.push_back(Str);
@@ -1049,7 +1179,8 @@
 bool Darwin::SupportsObjCGC() const { return isTargetMacOS(); }
 
 void Darwin::CheckObjCARC() const {
-  if (isTargetIOSBased() || (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
+  if (isTargetIOSBased() || isTargetWatchOSBased() ||
+      (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
     return;
   getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
 }
diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h
index 4d25a3b..d884032 100644
--- a/clang/lib/Driver/ToolChains.h
+++ b/clang/lib/Driver/ToolChains.h
@@ -354,7 +354,15 @@
   // the argument translation business.
   mutable bool TargetInitialized;
 
-  enum DarwinPlatformKind { MacOS, IPhoneOS, IPhoneOSSimulator };
+  enum DarwinPlatformKind {
+    MacOS,
+    IPhoneOS,
+    IPhoneOSSimulator,
+    TvOS,
+    TvOSSimulator,
+    WatchOS,
+    WatchOSSimulator
+  };
 
   mutable DarwinPlatformKind TargetPlatform;
 
@@ -382,7 +390,8 @@
                               llvm::opt::ArgStringList &CmdArgs) const override;
 
   bool isKernelStatic() const override {
-    return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0);
+    return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
+            !isTargetWatchOS());
   }
 
   void addProfileRTLibs(const llvm::opt::ArgList &Args,
@@ -411,12 +420,13 @@
 
   bool isTargetIPhoneOS() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == IPhoneOS;
+    return TargetPlatform == IPhoneOS || TargetPlatform == TvOS;
   }
 
   bool isTargetIOSSimulator() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetPlatform == IPhoneOSSimulator;
+    return TargetPlatform == IPhoneOSSimulator ||
+           TargetPlatform == TvOSSimulator;
   }
 
   bool isTargetIOSBased() const {
@@ -424,6 +434,36 @@
     return isTargetIPhoneOS() || isTargetIOSSimulator();
   }
 
+  bool isTargetTvOS() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetPlatform == TvOS;
+  }
+
+  bool isTargetTvOSSimulator() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetPlatform == TvOSSimulator;
+  }
+
+  bool isTargetTvOSBased() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetPlatform == TvOS || TargetPlatform == TvOSSimulator;
+  }
+
+  bool isTargetWatchOS() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetPlatform == WatchOS;
+  }
+
+  bool isTargetWatchOSSimulator() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetPlatform == WatchOSSimulator;
+  }
+
+  bool isTargetWatchOSBased() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetPlatform == WatchOS || TargetPlatform == WatchOSSimulator;
+  }
+
   bool isTargetMacOS() const {
     assert(TargetInitialized && "Target not initialized!");
     return TargetPlatform == MacOS;
@@ -474,7 +514,7 @@
   unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
     // Stack protectors default to on for user code on 10.5,
     // and for everything in 10.6 and beyond
-    if (isTargetIOSBased())
+    if (isTargetIOSBased() || isTargetWatchOSBased())
       return 1;
     else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
       return 1;
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 3e4cb31..29b100e 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -3128,7 +3128,8 @@
 
   // This kernel flags are a trump-card: they will disable PIC/PIE
   // generation, independent of the argument order.
-  if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)))
+  if (KernelOrKext && ((!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
+                       !Triple.isWatchOS()))
     PIC = PIE = false;
 
   if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
@@ -6232,7 +6233,11 @@
       // extract arch from default cpu of the Triple
       ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch));
   } else {
-    ArchKind = llvm::ARM::parseCPUArch(CPU);
+    // FIXME: horrible hack to get around the fact that Cortex-A7 is only an
+    // armv7k triple if it's actually been specified via "-arch armv7k".
+    ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")
+                          ? llvm::ARM::AK_ARMV7K
+                          : llvm::ARM::parseCPUArch(CPU);
   }
   if (ArchKind == llvm::ARM::AK_INVALID)
     return "";
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index d2e54ee..1459083 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -522,7 +522,8 @@
 
 static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
   return (triple.getVendor() == llvm::Triple::Apple &&
-          (triple.isiOS() || !triple.isMacOSXVersionLT(10,5)));
+          (triple.isiOS() || triple.isWatchOS() ||
+           !triple.isMacOSXVersionLT(10,5)));
 }
 
 void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,