Update aosp/master clang for rebase to r233350

Change-Id: I12d4823f10bc9e445b8b86e7721b71f98d1df442
diff --git a/lib/Driver/CrossWindowsToolChain.cpp b/lib/Driver/CrossWindowsToolChain.cpp
index 03fe41b..82456e7 100644
--- a/lib/Driver/CrossWindowsToolChain.cpp
+++ b/lib/Driver/CrossWindowsToolChain.cpp
@@ -60,7 +60,7 @@
   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
     SmallString<128> ResourceDir(D.ResourceDir);
     llvm::sys::path::append(ResourceDir, "include");
-    addSystemInclude(DriverArgs, CC1Args, ResourceDir.str());
+    addSystemInclude(DriverArgs, CC1Args, ResourceDir);
   }
   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
 }
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 61aaa97..0e99c58 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -57,7 +57,7 @@
       CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
       CCCUsePCH(true), SuppressMissingInputWarning(false) {
 
-  Name = llvm::sys::path::stem(ClangExecutable);
+  Name = llvm::sys::path::filename(ClangExecutable);
   Dir  = llvm::sys::path::parent_path(ClangExecutable);
 
   // Compute the path to the resource directory.
@@ -551,6 +551,9 @@
     Diag(clang::diag::note_drv_command_failed_diag_msg)
         << "Error generating run script: " + Script + " " + EC.message();
   } else {
+    ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n"
+             << "# Original command: ";
+    Cmd.Print(ScriptOS, "\n", /*Quote=*/true);
     Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);
     Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
   }
@@ -976,7 +979,7 @@
 
   SmallString<64> Path(Value);
   if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) {
-    if (!llvm::sys::path::is_absolute(Path.str())) {
+    if (!llvm::sys::path::is_absolute(Path)) {
       SmallString<64> Directory(WorkDir->getValue());
       llvm::sys::path::append(Directory, Value);
       Path.assign(Directory);
@@ -989,7 +992,7 @@
   if (D.IsCLMode() && llvm::sys::Process::FindInEnvPath("LIB", Value))
     return true;
 
-  D.Diag(clang::diag::err_drv_no_such_file) << Path.str();
+  D.Diag(clang::diag::err_drv_no_such_file) << Path;
   return false;
 }
 
@@ -2027,6 +2030,9 @@
   ToolChain *&TC = ToolChains[Target.str()];
   if (!TC) {
     switch (Target.getOS()) {
+    case llvm::Triple::CloudABI:
+      TC = new toolchains::CloudABI(*this, Target, Args);
+      break;
     case llvm::Triple::Darwin:
     case llvm::Triple::MacOSX:
     case llvm::Triple::IOS:
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index 66434cf..6d18a41 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -34,7 +34,7 @@
       Executable(_Executable), Arguments(_Arguments),
       ResponseFile(nullptr) {}
 
-static int skipArgs(const char *Flag) {
+static int skipArgs(const char *Flag, bool HaveCrashVFS) {
   // These flags are all of the form -Flag <Arg> and are treated as two
   // arguments.  Therefore, we need to skip the flag and the next argument.
   bool Res = llvm::StringSwitch<bool>(Flag)
@@ -43,9 +43,11 @@
     .Cases("-fdebug-compilation-dir", "-idirafter", true)
     .Cases("-include", "-include-pch", "-internal-isystem", true)
     .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
-    .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true)
+    .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
     .Cases("-resource-dir", "-serialize-diagnostic-file", true)
     .Cases("-dwarf-debug-flags", "-ivfsoverlay", true)
+    // Some include flags shouldn't be skipped if we have a crash VFS
+    .Case("-isysroot", !HaveCrashVFS)
     .Default(false);
 
   // Match found.
@@ -164,11 +166,12 @@
       if (StringRef(Args[I]).equals("-main-file-name"))
         MainFilename = Args[I + 1];
 
+  bool HaveCrashVFS = CrashInfo && !CrashInfo->VFSPath.empty();
   for (size_t i = 0, e = Args.size(); i < e; ++i) {
     const char *const Arg = Args[i];
 
     if (CrashInfo) {
-      if (int Skip = skipArgs(Arg)) {
+      if (int Skip = skipArgs(Arg, HaveCrashVFS)) {
         i += Skip - 1;
         continue;
       } else if (llvm::sys::path::filename(Arg) == MainFilename &&
@@ -185,7 +188,7 @@
     PrintArg(OS, Arg, Quote);
   }
 
-  if (CrashInfo && !CrashInfo->VFSPath.empty()) {
+  if (CrashInfo && HaveCrashVFS) {
     OS << ' ';
     PrintArg(OS, "-ivfsoverlay", Quote);
     OS << ' ';
diff --git a/lib/Driver/MSVCToolChain.cpp b/lib/Driver/MSVCToolChain.cpp
index 874e540..7739cb0 100644
--- a/lib/Driver/MSVCToolChain.cpp
+++ b/lib/Driver/MSVCToolChain.cpp
@@ -424,7 +424,7 @@
                                                   const char *subfolder) const {
   llvm::SmallString<128> path(folder);
   llvm::sys::path::append(path, subfolder);
-  addSystemInclude(DriverArgs, CC1Args, path.str());
+  addSystemInclude(DriverArgs, CC1Args, path);
 }
 
 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -435,7 +435,7 @@
   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
     SmallString<128> P(getDriver().ResourceDir);
     llvm::sys::path::append(P, "include");
-    addSystemInclude(DriverArgs, CC1Args, P.str());
+    addSystemInclude(DriverArgs, CC1Args, P);
   }
 
   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
diff --git a/lib/Driver/Multilib.cpp b/lib/Driver/Multilib.cpp
index 1f5d62f..8acda67 100644
--- a/lib/Driver/Multilib.cpp
+++ b/lib/Driver/Multilib.cpp
@@ -151,41 +151,23 @@
 }
 
 MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2) {
-  std::vector<Multilib> Ms;
-  Ms.push_back(M1);
-  Ms.push_back(M2);
-  return Either(Ms);
+  return Either({M1, M2});
 }
 
 MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                  const Multilib &M3) {
-  std::vector<Multilib> Ms;
-  Ms.push_back(M1);
-  Ms.push_back(M2);
-  Ms.push_back(M3);
-  return Either(Ms);
+  return Either({M1, M2, M3});
 }
 
 MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                  const Multilib &M3, const Multilib &M4) {
-  std::vector<Multilib> Ms;
-  Ms.push_back(M1);
-  Ms.push_back(M2);
-  Ms.push_back(M3);
-  Ms.push_back(M4);
-  return Either(Ms);
+  return Either({M1, M2, M3, M4});
 }
 
 MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
                                  const Multilib &M3, const Multilib &M4,
                                  const Multilib &M5) {
-  std::vector<Multilib> Ms;
-  Ms.push_back(M1);
-  Ms.push_back(M2);
-  Ms.push_back(M3);
-  Ms.push_back(M4);
-  Ms.push_back(M5);
-  return Either(Ms);
+  return Either({M1, M2, M3, M4, M5});
 }
 
 static Multilib compose(const Multilib &Base, const Multilib &New) {
@@ -197,7 +179,7 @@
   llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),
                           New.includeSuffix());
 
-  Multilib Composed(GCCSuffix.str(), OSSuffix.str(), IncludeSuffix.str());
+  Multilib Composed(GCCSuffix, OSSuffix, IncludeSuffix);
 
   Multilib::flags_list &Flags = Composed.flags();
 
@@ -207,8 +189,7 @@
   return Composed;
 }
 
-MultilibSet &
-MultilibSet::Either(const std::vector<Multilib> &MultilibSegments) {
+MultilibSet &MultilibSet::Either(ArrayRef<Multilib> MultilibSegments) {
   multilib_list Composed;
 
   if (Multilibs.empty())
@@ -229,30 +210,23 @@
   return *this;
 }
 
-MultilibSet &MultilibSet::FilterOut(const MultilibSet::FilterCallback &F) {
+MultilibSet &MultilibSet::FilterOut(FilterCallback F) {
   filterInPlace(F, Multilibs);
   return *this;
 }
 
-MultilibSet &MultilibSet::FilterOut(std::string Regex) {
-  class REFilter : public MultilibSet::FilterCallback {
-    mutable llvm::Regex R;
+MultilibSet &MultilibSet::FilterOut(const char *Regex) {
+  llvm::Regex R(Regex);
+#ifndef NDEBUG
+  std::string Error;
+  if (!R.isValid(Error)) {
+    llvm::errs() << Error;
+    llvm_unreachable("Invalid regex!");
+  }
+#endif
 
-  public:
-    REFilter(std::string Regex) : R(Regex) {}
-    bool operator()(const Multilib &M) const override {
-      std::string Error;
-      if (!R.isValid(Error)) {
-        llvm::errs() << Error;
-        assert(false);
-        return false;
-      }
-      return R.match(M.gccSuffix());
-    }
-  };
-
-  REFilter REF(Regex);
-  filterInPlace(REF, Multilibs);
+  filterInPlace([&R](const Multilib &M) { return R.match(M.gccSuffix()); },
+                Multilibs);
   return *this;
 }
 
@@ -262,38 +236,29 @@
   Multilibs.insert(Multilibs.end(), Other.begin(), Other.end());
 }
 
+static bool isFlagEnabled(StringRef Flag) {
+  char Indicator = Flag.front();
+  assert(Indicator == '+' || Indicator == '-');
+  return Indicator == '+';
+}
+
 bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
-  class FilterFlagsMismatch : public MultilibSet::FilterCallback {
-    llvm::StringMap<bool> FlagSet;
+  llvm::StringMap<bool> FlagSet;
 
-  public:
-    FilterFlagsMismatch(const std::vector<std::string> &Flags) {
-      // Stuff all of the flags into the FlagSet such that a true mappend
-      // indicates the flag was enabled, and a false mappend indicates the
-      // flag was disabled
-      for (StringRef Flag : Flags)
-        FlagSet[Flag.substr(1)] = isFlagEnabled(Flag);
-    }
-    bool operator()(const Multilib &M) const override {
-      for (StringRef Flag : M.flags()) {
-        llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
-        if (SI != FlagSet.end())
-          if (SI->getValue() != isFlagEnabled(Flag))
-            return true;
-      }
-      return false;
-    }
-  private:
-    bool isFlagEnabled(StringRef Flag) const {
-      char Indicator = Flag.front();
-      assert(Indicator == '+' || Indicator == '-');
-      return Indicator == '+';
-    }
-  };
+  // Stuff all of the flags into the FlagSet such that a true mappend indicates
+  // the flag was enabled, and a false mappend indicates the flag was disabled.
+  for (StringRef Flag : Flags)
+    FlagSet[Flag.substr(1)] = isFlagEnabled(Flag);
 
-  FilterFlagsMismatch FlagsMismatch(Flags);
-
-  multilib_list Filtered = filterCopy(FlagsMismatch, Multilibs);
+  multilib_list Filtered = filterCopy([&FlagSet](const Multilib &M) {
+    for (StringRef Flag : M.flags()) {
+      llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
+      if (SI != FlagSet.end())
+        if (SI->getValue() != isFlagEnabled(Flag))
+          return true;
+    }
+    return false;
+  }, Multilibs);
 
   if (Filtered.size() == 0) {
     return false;
@@ -313,19 +278,15 @@
     OS << M << "\n";
 }
 
-MultilibSet::multilib_list
-MultilibSet::filterCopy(const MultilibSet::FilterCallback &F,
-                        const multilib_list &Ms) {
+MultilibSet::multilib_list MultilibSet::filterCopy(FilterCallback F,
+                                                   const multilib_list &Ms) {
   multilib_list Copy(Ms);
   filterInPlace(F, Copy);
   return Copy;
 }
 
-void MultilibSet::filterInPlace(const MultilibSet::FilterCallback &F,
-                                multilib_list &Ms) {
-  Ms.erase(std::remove_if(Ms.begin(), Ms.end(),
-                          [&F](const Multilib &M) { return F(M); }),
-           Ms.end());
+void MultilibSet::filterInPlace(FilterCallback F, multilib_list &Ms) {
+  Ms.erase(std::remove_if(Ms.begin(), Ms.end(), F), Ms.end());
 }
 
 raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 11b9288..fb907a7 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -24,7 +24,7 @@
 namespace {
 /// Assign ordinals to possible values of -fsanitize= flag.
 /// We use the ordinal values as bit positions within \c SanitizeKind.
-enum SanitizeOrdinal {
+enum SanitizeOrdinal : uint64_t {
 #define SANITIZER(NAME, ID) SO_##ID,
 #define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
 #include "clang/Basic/Sanitizers.def"
@@ -35,26 +35,26 @@
 /// 1) set of sanitizers each sanitizer group expands into.
 /// 2) set of sanitizers sharing a specific property (e.g.
 ///    all sanitizers with zero-base shadow).
-enum SanitizeKind {
-#define SANITIZER(NAME, ID) ID = 1 << SO_##ID,
+enum SanitizeKind : uint64_t {
+#define SANITIZER(NAME, ID) ID = 1ULL << SO_##ID,
 #define SANITIZER_GROUP(NAME, ID, ALIAS)                                       \
-ID = ALIAS, ID##Group = 1 << SO_##ID##Group,
+  ID = ALIAS, ID##Group = 1ULL << SO_##ID##Group,
 #include "clang/Basic/Sanitizers.def"
   NeedsUbsanRt = Undefined | Integer,
   NotAllowedWithTrap = Vptr,
   RequiresPIE = Memory | DataFlow,
   NeedsUnwindTables = Address | Thread | Memory | DataFlow,
-  SupportsCoverage = Address | Memory | Leak | Undefined | Integer,
+  SupportsCoverage = Address | Memory | Leak | Undefined | Integer | DataFlow,
   RecoverableByDefault = Undefined | Integer,
   Unrecoverable = Address | Unreachable | Return,
   LegacyFsanitizeRecoverMask = Undefined | Integer,
-  NeedsLTO = CFIVptr,
+  NeedsLTO = CFIDerivedCast | CFIUnrelatedCast | CFIVptr,
 };
 }
 
 /// Returns true if set of \p Sanitizers contain at least one sanitizer from
 /// \p Kinds.
-static bool hasOneOf(const clang::SanitizerSet &Sanitizers, unsigned Kinds) {
+static bool hasOneOf(const clang::SanitizerSet &Sanitizers, uint64_t Kinds) {
 #define SANITIZER(NAME, ID)                                                    \
   if (Sanitizers.has(clang::SanitizerKind::ID) && (Kinds & ID))                \
     return true;
@@ -63,14 +63,14 @@
 }
 
 /// Adds all sanitizers from \p Kinds to \p Sanitizers.
-static void addAllOf(clang::SanitizerSet &Sanitizers, unsigned Kinds) {
+static void addAllOf(clang::SanitizerSet &Sanitizers, uint64_t Kinds) {
 #define SANITIZER(NAME, ID) \
   if (Kinds & ID) \
     Sanitizers.set(clang::SanitizerKind::ID, true);
 #include "clang/Basic/Sanitizers.def"
 }
 
-static unsigned toSanitizeKind(clang::SanitizerKind K) {
+static uint64_t toSanitizeKind(clang::SanitizerKind K) {
 #define SANITIZER(NAME, ID) \
   if (K == clang::SanitizerKind::ID) \
     return ID;
@@ -81,11 +81,11 @@
 /// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
 /// Returns a member of the \c SanitizeKind enumeration, or \c 0
 /// if \p Value is not known.
-static unsigned parseValue(const char *Value);
+static uint64_t parseValue(const char *Value);
 
 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
 /// invalid components. Returns OR of members of \c SanitizeKind enumeration.
-static unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
+static uint64_t parseArgValues(const Driver &D, const llvm::opt::Arg *A,
                                bool DiagnoseErrors);
 
 /// Produce an argument string from ArgList \p Args, which shows how it
@@ -94,7 +94,7 @@
 /// would produce "-fsanitize=vptr".
 static std::string lastArgumentForMask(const Driver &D,
                                        const llvm::opt::ArgList &Args,
-                                       unsigned Mask);
+                                       uint64_t Mask);
 
 static std::string lastArgumentForKind(const Driver &D,
                                        const llvm::opt::ArgList &Args,
@@ -106,7 +106,7 @@
 /// a value in \p Mask. For instance, the argument
 /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
 /// "-fsanitize=alignment".
-static std::string describeSanitizeArg(const llvm::opt::Arg *A, unsigned Mask);
+static std::string describeSanitizeArg(const llvm::opt::Arg *A, uint64_t Mask);
 
 /// Produce a string containing comma-separated names of sanitizers in \p
 /// Sanitizers set.
@@ -114,9 +114,9 @@
 
 /// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
 /// this group enables.
-static unsigned expandGroups(unsigned Kinds);
+static uint64_t expandGroups(uint64_t Kinds);
 
-static unsigned getToolchainUnsupportedKinds(const ToolChain &TC) {
+static uint64_t getToolchainUnsupportedKinds(const ToolChain &TC) {
   bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
   bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
   bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
@@ -124,7 +124,7 @@
   bool IsMIPS64 = TC.getTriple().getArch() == llvm::Triple::mips64 ||
                   TC.getTriple().getArch() == llvm::Triple::mips64el;
 
-  unsigned Unsupported = 0;
+  uint64_t Unsupported = 0;
   if (!(IsLinux && (IsX86_64 || IsMIPS64))) {
     Unsupported |= Memory | DataFlow;
   }
@@ -137,6 +137,27 @@
   return Unsupported;
 }
 
+static bool getDefaultBlacklist(const Driver &D, uint64_t Kinds,
+                                std::string &BLPath) {
+  const char *BlacklistFile = nullptr;
+  if (Kinds & SanitizeKind::Address)
+    BlacklistFile = "asan_blacklist.txt";
+  else if (Kinds & SanitizeKind::Memory)
+    BlacklistFile = "msan_blacklist.txt";
+  else if (Kinds & SanitizeKind::Thread)
+    BlacklistFile = "tsan_blacklist.txt";
+  else if (Kinds & SanitizeKind::DataFlow)
+    BlacklistFile = "dfsan_abilist.txt";
+
+  if (BlacklistFile) {
+    clang::SmallString<64> Path(D.ResourceDir);
+    llvm::sys::path::append(Path, BlacklistFile);
+    BLPath = Path.str();
+    return true;
+  }
+  return false;
+}
+
 bool SanitizerArgs::needsUbsanRt() const {
   return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt);
 }
@@ -150,7 +171,7 @@
 }
 
 bool SanitizerArgs::needsLTO() const {
-  return hasOneOf(Sanitizers, CFIVptr);
+  return hasOneOf(Sanitizers, NeedsLTO);
 }
 
 void SanitizerArgs::clear() {
@@ -169,13 +190,13 @@
 SanitizerArgs::SanitizerArgs(const ToolChain &TC,
                              const llvm::opt::ArgList &Args) {
   clear();
-  unsigned AllRemove = 0;  // During the loop below, the accumulated set of
+  uint64_t AllRemove = 0;  // During the loop below, the accumulated set of
                            // sanitizers disabled by the current sanitizer
                            // argument or any argument after it.
-  unsigned DiagnosedKinds = 0;  // All Kinds we have diagnosed up to now.
+  uint64_t DiagnosedKinds = 0;  // All Kinds we have diagnosed up to now.
                                 // Used to deduplicate diagnostics.
-  unsigned Kinds = 0;
-  unsigned NotSupported = getToolchainUnsupportedKinds(TC);
+  uint64_t Kinds = 0;
+  uint64_t NotSupported = getToolchainUnsupportedKinds(TC);
   ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
 
   const Driver &D = TC.getDriver();
@@ -184,14 +205,14 @@
     const auto *Arg = *I;
     if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
       Arg->claim();
-      unsigned Add = parseArgValues(D, Arg, true);
+      uint64_t Add = parseArgValues(D, Arg, true);
 
       // Avoid diagnosing any sanitizer which is disabled later.
       Add &= ~AllRemove;
       // At this point we have not expanded groups, so any unsupported
       // sanitizers in Add are those which have been explicitly enabled.
       // Diagnose them.
-      if (unsigned KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
+      if (uint64_t KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
         // Only diagnose the new kinds.
         std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
         D.Diag(diag::err_drv_unsupported_opt_for_target)
@@ -232,38 +253,73 @@
       Kinds |= Add;
     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
       Arg->claim();
-      unsigned Remove = parseArgValues(D, Arg, true);
+      uint64_t Remove = parseArgValues(D, Arg, true);
       AllRemove |= expandGroups(Remove);
     }
   }
-  addAllOf(Sanitizers, Kinds);
 
   // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
   // is disabled.
-  if (Sanitizers.has(SanitizerKind::Vptr) &&
+  if ((Kinds & SanitizeKind::Vptr) &&
       (RTTIMode == ToolChain::RM_DisabledImplicitly ||
        RTTIMode == ToolChain::RM_DisabledExplicitly)) {
     Kinds &= ~SanitizeKind::Vptr;
-    Sanitizers.set(SanitizerKind::Vptr, 0);
   }
 
+  // Warn about undefined sanitizer options that require runtime support.
+  UbsanTrapOnError =
+    Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+                 options::OPT_fno_sanitize_undefined_trap_on_error, false);
+  if (UbsanTrapOnError && (Kinds & SanitizeKind::NotAllowedWithTrap)) {
+    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+        << lastArgumentForMask(D, Args, NotAllowedWithTrap)
+        << "-fsanitize-undefined-trap-on-error";
+    Kinds &= ~SanitizeKind::NotAllowedWithTrap;
+  }
+
+  // Warn about incompatible groups of sanitizers.
+  std::pair<uint64_t, uint64_t> IncompatibleGroups[] = {
+      std::make_pair(SanitizeKind::Address, SanitizeKind::Thread),
+      std::make_pair(SanitizeKind::Address, SanitizeKind::Memory),
+      std::make_pair(SanitizeKind::Thread, SanitizeKind::Memory),
+      std::make_pair(SanitizeKind::Leak, SanitizeKind::Thread),
+      std::make_pair(SanitizeKind::Leak, SanitizeKind::Memory),
+      std::make_pair(SanitizeKind::NeedsUbsanRt, SanitizeKind::Thread),
+      std::make_pair(SanitizeKind::NeedsUbsanRt, SanitizeKind::Memory)};
+  for (auto G : IncompatibleGroups) {
+    uint64_t Group = G.first;
+    if (Kinds & Group) {
+      if (uint64_t Incompatible = Kinds & G.second) {
+        D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+            << lastArgumentForMask(D, Args, Group)
+            << lastArgumentForMask(D, Args, Incompatible);
+        Kinds &= ~Incompatible;
+      }
+    }
+  }
+  // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
+  // -fsanitize=address. Perhaps it should print an error, or perhaps
+  // -f(-no)sanitize=leak should change whether leak detection is enabled by
+  // default in ASan?
+
   // Parse -f(no-)?sanitize-recover flags.
-  unsigned RecoverableKinds = RecoverableByDefault;
-  unsigned DiagnosedUnrecoverableKinds = 0;
+  uint64_t RecoverableKinds = RecoverableByDefault;
+  uint64_t DiagnosedUnrecoverableKinds = 0;
   for (const auto *Arg : Args) {
+    const char *DeprecatedReplacement = nullptr;
     if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
-      // FIXME: Add deprecation notice, and then remove this flag.
+      DeprecatedReplacement = "-fsanitize-recover=undefined,integer";
       RecoverableKinds |= expandGroups(LegacyFsanitizeRecoverMask);
       Arg->claim();
     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
-      // FIXME: Add deprecation notice, and then remove this flag.
+      DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer";
       RecoverableKinds &= ~expandGroups(LegacyFsanitizeRecoverMask);
       Arg->claim();
     } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
-      unsigned Add = parseArgValues(D, Arg, true);
+      uint64_t Add = parseArgValues(D, Arg, true);
       // Report error if user explicitly tries to recover from unrecoverable
       // sanitizer.
-      if (unsigned KindsToDiagnose =
+      if (uint64_t KindsToDiagnose =
               Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
         SanitizerSet SetToDiagnose;
         addAllOf(SetToDiagnose, KindsToDiagnose);
@@ -277,57 +333,19 @@
       RecoverableKinds &= ~expandGroups(parseArgValues(D, Arg, true));
       Arg->claim();
     }
+    if (DeprecatedReplacement) {
+      D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
+                                            << DeprecatedReplacement;
+    }
   }
   RecoverableKinds &= Kinds;
   RecoverableKinds &= ~Unrecoverable;
-  addAllOf(RecoverableSanitizers, RecoverableKinds);
-
-  UbsanTrapOnError =
-    Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
-                 options::OPT_fno_sanitize_undefined_trap_on_error, false);
-
-  // Warn about undefined sanitizer options that require runtime support.
-  if (UbsanTrapOnError && hasOneOf(Sanitizers, NotAllowedWithTrap)) {
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForMask(D, Args, NotAllowedWithTrap)
-      << "-fsanitize-undefined-trap-on-error";
-  }
-
-  // Check for incompatible sanitizers.
-  bool NeedsAsan = Sanitizers.has(SanitizerKind::Address);
-  bool NeedsTsan = Sanitizers.has(SanitizerKind::Thread);
-  bool NeedsMsan = Sanitizers.has(SanitizerKind::Memory);
-  bool NeedsLsan = Sanitizers.has(SanitizerKind::Leak);
-  if (NeedsAsan && NeedsTsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Address)
-      << lastArgumentForKind(D, Args, SanitizerKind::Thread);
-  if (NeedsAsan && NeedsMsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Address)
-      << lastArgumentForKind(D, Args, SanitizerKind::Memory);
-  if (NeedsTsan && NeedsMsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Thread)
-      << lastArgumentForKind(D, Args, SanitizerKind::Memory);
-  if (NeedsLsan && NeedsTsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Leak)
-      << lastArgumentForKind(D, Args, SanitizerKind::Thread);
-  if (NeedsLsan && NeedsMsan)
-    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
-      << lastArgumentForKind(D, Args, SanitizerKind::Leak)
-      << lastArgumentForKind(D, Args, SanitizerKind::Memory);
-  // FIXME: Currently -fsanitize=leak is silently ignored in the presence of
-  // -fsanitize=address. Perhaps it should print an error, or perhaps
-  // -f(-no)sanitize=leak should change whether leak detection is enabled by
-  // default in ASan?
 
   // Setup blacklist files.
   // Add default blacklist from resource directory.
   {
     std::string BLPath;
-    if (getDefaultBlacklist(D, BLPath) && llvm::sys::fs::exists(BLPath))
+    if (getDefaultBlacklist(D, Kinds, BLPath) && llvm::sys::fs::exists(BLPath))
       BlacklistFiles.push_back(BLPath);
   }
   // Parse -f(no-)sanitize-blacklist options.
@@ -354,7 +372,7 @@
   }
 
   // Parse -f[no-]sanitize-memory-track-origins[=level] options.
-  if (NeedsMsan) {
+  if (Kinds & SanitizeKind::Memory) {
     if (Arg *A =
             Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
                             options::OPT_fsanitize_memory_track_origins,
@@ -375,7 +393,7 @@
   }
 
   // Parse -fsanitize-coverage=N. Currently one of asan/msan/lsan is required.
-  if (hasOneOf(Sanitizers, SupportsCoverage)) {
+  if (Kinds & SanitizeKind::SupportsCoverage) {
     if (Arg *A = Args.getLastArg(options::OPT_fsanitize_coverage)) {
       StringRef S = A->getValue();
       // Legal values are 0..4.
@@ -385,7 +403,7 @@
     }
   }
 
-  if (NeedsAsan) {
+  if (Kinds & SanitizeKind::Address) {
     AsanSharedRuntime =
         Args.hasArg(options::OPT_shared_libasan) ||
         (TC.getTriple().getEnvironment() == llvm::Triple::Android);
@@ -420,6 +438,10 @@
   // Parse -link-cxx-sanitizer flag.
   LinkCXXRuntimes =
       Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX();
+
+  // Finally, initialize the set of available and recoverable sanitizers.
+  addAllOf(Sanitizers, Kinds);
+  addAllOf(RecoverableSanitizers, RecoverableKinds);
 }
 
 static std::string toString(const clang::SanitizerSet &Sanitizers) {
@@ -472,28 +494,8 @@
     CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
 }
 
-bool SanitizerArgs::getDefaultBlacklist(const Driver &D, std::string &BLPath) {
-  const char *BlacklistFile = nullptr;
-  if (Sanitizers.has(SanitizerKind::Address))
-    BlacklistFile = "asan_blacklist.txt";
-  else if (Sanitizers.has(SanitizerKind::Memory))
-    BlacklistFile = "msan_blacklist.txt";
-  else if (Sanitizers.has(SanitizerKind::Thread))
-    BlacklistFile = "tsan_blacklist.txt";
-  else if (Sanitizers.has(SanitizerKind::DataFlow))
-    BlacklistFile = "dfsan_abilist.txt";
-
-  if (BlacklistFile) {
-    SmallString<64> Path(D.ResourceDir);
-    llvm::sys::path::append(Path, BlacklistFile);
-    BLPath = Path.str();
-    return true;
-  }
-  return false;
-}
-
-unsigned parseValue(const char *Value) {
-  unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
+uint64_t parseValue(const char *Value) {
+  uint64_t ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
 #define SANITIZER(NAME, ID) .Case(NAME, ID)
 #define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group)
 #include "clang/Basic/Sanitizers.def"
@@ -501,24 +503,24 @@
   return ParsedKind;
 }
 
-unsigned expandGroups(unsigned Kinds) {
+uint64_t expandGroups(uint64_t Kinds) {
 #define SANITIZER(NAME, ID)
 #define SANITIZER_GROUP(NAME, ID, ALIAS) if (Kinds & ID##Group) Kinds |= ID;
 #include "clang/Basic/Sanitizers.def"
   return Kinds;
 }
 
-unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
+uint64_t parseArgValues(const Driver &D, const llvm::opt::Arg *A,
                         bool DiagnoseErrors) {
   assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
           A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
           A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
           A->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) &&
          "Invalid argument in parseArgValues!");
-  unsigned Kinds = 0;
-  for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
-    const char *Value = A->getValue(I);
-    unsigned Kind;
+  uint64_t Kinds = 0;
+  for (int i = 0, n = A->getNumValues(); i != n; ++i) {
+    const char *Value = A->getValue(i);
+    uint64_t Kind;
     // Special case: don't accept -fsanitize=all.
     if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
         0 == strcmp("all", Value))
@@ -536,33 +538,33 @@
 }
 
 std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
-                                unsigned Mask) {
+                                uint64_t Mask) {
   for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
                                                   E = Args.rend();
        I != E; ++I) {
     const auto *Arg = *I;
     if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
-      unsigned AddKinds = expandGroups(parseArgValues(D, Arg, false));
+      uint64_t AddKinds = expandGroups(parseArgValues(D, Arg, false));
       if (AddKinds & Mask)
         return describeSanitizeArg(Arg, Mask);
     } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
-      unsigned RemoveKinds = expandGroups(parseArgValues(D, Arg, false));
+      uint64_t RemoveKinds = expandGroups(parseArgValues(D, Arg, false));
       Mask &= ~RemoveKinds;
     }
   }
   llvm_unreachable("arg list didn't provide expected value");
 }
 
-std::string describeSanitizeArg(const llvm::opt::Arg *A, unsigned Mask) {
+std::string describeSanitizeArg(const llvm::opt::Arg *A, uint64_t Mask) {
   assert(A->getOption().matches(options::OPT_fsanitize_EQ)
          && "Invalid argument in describeSanitizerArg!");
 
   std::string Sanitizers;
-  for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
-    if (expandGroups(parseValue(A->getValue(I))) & Mask) {
+  for (int i = 0, n = A->getNumValues(); i != n; ++i) {
+    if (expandGroups(parseValue(A->getValue(i))) & Mask) {
       if (!Sanitizers.empty())
         Sanitizers += ",";
-      Sanitizers += A->getValue(I);
+      Sanitizers += A->getValue(i);
     }
   }
 
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 5feeda4..52e8603 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -48,7 +48,7 @@
 
   // On the PS4, turning on c++ exceptions turns on rtti.
   // We're assuming that, if we see -fexceptions, rtti gets turned on.
-  Arg *Exceptions = Args.getLastArg(
+  Arg *Exceptions = Args.getLastArgNoClaim(
       options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
       options::OPT_fexceptions, options::OPT_fno_exceptions);
   if (Exceptions &&
@@ -297,10 +297,7 @@
     // '-mbig-endian'/'-EB'.
     if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
                                  options::OPT_mbig_endian)) {
-      if (A->getOption().matches(options::OPT_mlittle_endian))
-        IsBigEndian = false;
-      else
-        IsBigEndian = true;
+      IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
     }
 
     // Thumb2 is the default for V7 on Darwin.
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 93e6db8..9606df6 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -302,8 +302,8 @@
   // For now, allow missing resource libraries to support developers who may
   // not have compiler-rt checked out or integrated into their build (unless
   // we explicitly force linking with this library).
-  if (AlwaysLink || llvm::sys::fs::exists(P.str()))
-    CmdArgs.push_back(Args.MakeArgString(P.str()));
+  if (AlwaysLink || llvm::sys::fs::exists(P))
+    CmdArgs.push_back(Args.MakeArgString(P));
 
   // Adding the rpaths might negatively interact when other rpaths are involved,
   // so we should make sure we add the rpaths last, after all user-specified
@@ -320,10 +320,26 @@
     // Add the path to the resource dir to rpath to support using the dylib
     // from the default location without copying.
     CmdArgs.push_back("-rpath");
-    CmdArgs.push_back(Args.MakeArgString(Dir.str()));
+    CmdArgs.push_back(Args.MakeArgString(Dir));
   }
 }
 
+void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
+                                          ArgStringList &CmdArgs,
+                                          StringRef Sanitizer) const {
+  if (!Args.hasArg(options::OPT_dynamiclib) &&
+      !Args.hasArg(options::OPT_bundle)) {
+    // Sanitizer runtime libraries requires C++.
+    AddCXXStdlibLibArgs(Args, CmdArgs);
+  }
+  assert(isTargetMacOS() || isTargetIOSSimulator());
+  StringRef OS = isTargetMacOS() ? "osx" : "iossim";
+  AddLinkRuntimeLib(Args, CmdArgs, (Twine("libclang_rt.") + Sanitizer + "_" +
+                                    OS + "_dynamic.dylib").str(),
+                    /*AlwaysLink*/ true, /*IsEmbedded*/ false,
+                    /*AddRPath*/ true);
+}
+
 void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
                                         ArgStringList &CmdArgs) const {
   // Darwin only supports the compiler-rt based runtime libraries.
@@ -368,47 +384,26 @@
 
   const SanitizerArgs &Sanitize = getSanitizerArgs();
 
-  // Add Ubsan runtime library, if required.
-  if (Sanitize.needsUbsanRt()) {
-    // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
-    if (isTargetIOSBased()) {
+  if (Sanitize.needsAsanRt()) {
+    if (!isTargetMacOS() && !isTargetIOSSimulator()) {
+      // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
       getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
-        << "-fsanitize=undefined";
+          << "-fsanitize=address";
     } else {
-      assert(isTargetMacOS() && "unexpected non OS X target");
-      AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ubsan_osx.a", true);
-
-      // The Ubsan runtime library requires C++.
-      AddCXXStdlibLibArgs(Args, CmdArgs);
+      AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
     }
   }
 
-  // Add ASAN runtime library, if required. Dynamic libraries and bundles
-  // should not be linked with the runtime library.
-  if (Sanitize.needsAsanRt()) {
-    // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
-    if (isTargetIPhoneOS()) {
+  if (Sanitize.needsUbsanRt()) {
+    if (!isTargetMacOS() && !isTargetIOSSimulator()) {
+      // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
       getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
-        << "-fsanitize=address";
+          << "-fsanitize=undefined";
     } else {
-      if (!Args.hasArg(options::OPT_dynamiclib) &&
-          !Args.hasArg(options::OPT_bundle)) {
-        // The ASAN runtime library requires C++.
-        AddCXXStdlibLibArgs(Args, CmdArgs);
-      }
-      if (isTargetMacOS()) {
-        AddLinkRuntimeLib(Args, CmdArgs,
-                          "libclang_rt.asan_osx_dynamic.dylib",
-                          /*AlwaysLink*/ true, /*IsEmbedded*/ false,
-                          /*AddRPath*/ true);
-      } else {
-        if (isTargetIOSSimulator()) {
-          AddLinkRuntimeLib(Args, CmdArgs,
-                            "libclang_rt.asan_iossim_dynamic.dylib",
-                            /*AlwaysLink*/ true, /*IsEmbedded*/ false,
-                            /*AddRPath*/ true);
-        }
-      }
+      AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
+      // Add explicit dependcy on -lc++abi, as -lc++ doesn't re-export
+      // all RTTI-related symbols that UBSan uses.
+      CmdArgs.push_back("-lc++abi");
     }
   }
 
@@ -599,11 +594,11 @@
       SmallString<128> P(A->getValue());
       llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
 
-      if (!llvm::sys::fs::exists(P.str())) {
+      if (!llvm::sys::fs::exists(P)) {
         llvm::sys::path::remove_filename(P);
         llvm::sys::path::append(P, "libstdc++.6.dylib");
-        if (llvm::sys::fs::exists(P.str())) {
-          CmdArgs.push_back(Args.MakeArgString(P.str()));
+        if (llvm::sys::fs::exists(P)) {
+          CmdArgs.push_back(Args.MakeArgString(P));
           return;
         }
       }
@@ -646,8 +641,8 @@
 
   // For now, allow missing resource libraries to support developers who may
   // not have compiler-rt checked out or integrated into their build.
-  if (llvm::sys::fs::exists(P.str()))
-    CmdArgs.push_back(Args.MakeArgString(P.str()));
+  if (llvm::sys::fs::exists(P))
+    CmdArgs.push_back(Args.MakeArgString(P));
 }
 
 DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
@@ -1498,11 +1493,12 @@
 
 namespace {
 // Filter to remove Multilibs that don't exist as a suffix to Path
-class FilterNonExistent : public MultilibSet::FilterCallback {
-  std::string Base;
+class FilterNonExistent {
+  StringRef Base;
+
 public:
-  FilterNonExistent(std::string Base) : Base(Base) {}
-  bool operator()(const Multilib &M) const override {
+  FilterNonExistent(StringRef Base) : Base(Base) {}
+  bool operator()(const Multilib &M) {
     return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o");
   }
 };
@@ -2249,7 +2245,7 @@
 
   llvm::sys::path::append(IncludeDir, "hexagon/include/c++/");
   llvm::sys::path::append(IncludeDir, Ver);
-  addSystemInclude(DriverArgs, CC1Args, IncludeDir.str());
+  addSystemInclude(DriverArgs, CC1Args, IncludeDir);
 }
 
 ToolChain::CXXStdlibType
@@ -2344,6 +2340,36 @@
   return false;
 }
 
+// CloudABI - CloudABI tool chain which can call ld(1) directly.
+
+CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple,
+                   const ArgList &Args)
+    : Generic_ELF(D, Triple, Args) {
+  SmallString<128> P(getDriver().Dir);
+  llvm::sys::path::append(P, "..", getTriple().str(), "lib");
+  getFilePaths().push_back(P.str());
+}
+
+void CloudABI::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+                                            ArgStringList &CC1Args) const {
+  if (DriverArgs.hasArg(options::OPT_nostdlibinc) &&
+      DriverArgs.hasArg(options::OPT_nostdincxx))
+    return;
+
+  SmallString<128> P(getDriver().Dir);
+  llvm::sys::path::append(P, "..", getTriple().str(), "include/c++/v1");
+  addSystemInclude(DriverArgs, CC1Args, P.str());
+}
+
+void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args,
+                                   ArgStringList &CmdArgs) const {
+  CmdArgs.push_back("-lc++");
+  CmdArgs.push_back("-lc++abi");
+  CmdArgs.push_back("-lunwind");
+}
+
+Tool *CloudABI::buildLinker() const { return new tools::cloudabi::Link(*this); }
+
 /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
 
 OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
@@ -3147,7 +3173,7 @@
   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
     SmallString<128> P(D.ResourceDir);
     llvm::sys::path::append(P, "include");
-    addSystemInclude(DriverArgs, CC1Args, P.str());
+    addSystemInclude(DriverArgs, CC1Args, P);
   }
 
   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
@@ -3171,7 +3197,7 @@
 
   // Add include directories specific to the selected multilib set and multilib.
   if (GCCInstallation.isValid()) {
-    auto Callback = Multilibs.includeDirsCallback();
+    const auto &Callback = Multilibs.includeDirsCallback();
     if (Callback) {
       const auto IncludePaths = Callback(GCCInstallation.getInstallPath(),
                                          GCCInstallation.getTriple().str(),
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 90893c3..ebd23d1 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -494,6 +494,11 @@
   AddLinkARCArgs(const llvm::opt::ArgList &Args,
                  llvm::opt::ArgStringList &CmdArgs) const override;
   /// }
+
+private:
+  void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
+                               llvm::opt::ArgStringList &CmdArgs,
+                               StringRef Sanitizer) const;
 };
 
 class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
@@ -507,6 +512,31 @@
                              llvm::opt::ArgStringList &CC1Args) const override;
 };
 
+class LLVM_LIBRARY_VISIBILITY CloudABI : public Generic_ELF {
+public:
+  CloudABI(const Driver &D, const llvm::Triple &Triple,
+           const llvm::opt::ArgList &Args);
+  bool HasNativeLLVMSupport() const override { return true; }
+
+  bool IsMathErrnoDefault() const override { return false; }
+  bool IsObjCNonFragileABIDefault() const override { return true; }
+
+  CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args)
+      const override {
+    return ToolChain::CST_Libcxx;
+  }
+  void AddClangCXXStdlibIncludeArgs(
+      const llvm::opt::ArgList &DriverArgs,
+      llvm::opt::ArgStringList &CC1Args) const override;
+  void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+                           llvm::opt::ArgStringList &CmdArgs) const override;
+
+  bool isPIEDefault() const override { return false; }
+
+protected:
+  Tool *buildLinker() const override;
+};
+
 class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC {
 public:
   Solaris(const Driver &D, const llvm::Triple &Triple,
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index b0e581b..ed1bd3e 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -24,6 +24,7 @@
 #include "clang/Driver/SanitizerArgs.h"
 #include "clang/Driver/ToolChain.h"
 #include "clang/Driver/Util.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -323,8 +324,9 @@
     if (A->getOption().matches(options::OPT_M) ||
         A->getOption().matches(options::OPT_MD))
       CmdArgs.push_back("-sys-header-deps");
-
-    if (isa<PrecompileJobAction>(JA))
+    if ((isa<PrecompileJobAction>(JA) &&
+         !Args.hasArg(options::OPT_fno_module_file_deps)) ||
+        Args.hasArg(options::OPT_fmodule_file_deps))
       CmdArgs.push_back("-module-file-deps");
   }
 
@@ -381,19 +383,19 @@
       P += ".dummy";
       if (UsePCH) {
         llvm::sys::path::replace_extension(P, "pch");
-        if (llvm::sys::fs::exists(P.str()))
+        if (llvm::sys::fs::exists(P))
           FoundPCH = true;
       }
 
       if (!FoundPCH) {
         llvm::sys::path::replace_extension(P, "pth");
-        if (llvm::sys::fs::exists(P.str()))
+        if (llvm::sys::fs::exists(P))
           FoundPTH = true;
       }
 
       if (!FoundPCH && !FoundPTH) {
         llvm::sys::path::replace_extension(P, "gch");
-        if (llvm::sys::fs::exists(P.str())) {
+        if (llvm::sys::fs::exists(P)) {
           FoundPCH = UsePCH;
           FoundPTH = !UsePCH;
         }
@@ -406,12 +408,12 @@
             CmdArgs.push_back("-include-pch");
           else
             CmdArgs.push_back("-include-pth");
-          CmdArgs.push_back(Args.MakeArgString(P.str()));
+          CmdArgs.push_back(Args.MakeArgString(P));
           continue;
         } else {
           // Ignore the PCH if not first on command line and emit warning.
           D.Diag(diag::warn_drv_pch_not_first_include)
-              << P.str() << A->getAsString(Args);
+              << P << A->getAsString(Args);
         }
       }
     }
@@ -1315,9 +1317,22 @@
     ABIName = A->getValue();
   } else if (getToolChain().getTriple().isOSLinux())
     switch(getToolChain().getArch()) {
-    case llvm::Triple::ppc64:
+    case llvm::Triple::ppc64: {
+      // When targeting a processor that supports QPX, or if QPX is
+      // specifically enabled, default to using the ABI that supports QPX (so
+      // long as it is not specifically disabled).
+      bool HasQPX = false;
+      if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+        HasQPX = A->getValue() == StringRef("a2q");
+      HasQPX = Args.hasFlag(options::OPT_mqpx, options::OPT_mno_qpx, HasQPX);
+      if (HasQPX) {
+        ABIName = "elfv1-qpx";
+        break;
+      }
+
       ABIName = "elfv1";
       break;
+    }
     case llvm::Triple::ppc64le:
       ABIName = "elfv2";
       break;
@@ -1548,8 +1563,7 @@
     CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
 }
 
-static void getX86TargetFeatures(const Driver & D,
-                                 const llvm::Triple &Triple,
+static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
   if (Triple.getArchName() == "x86_64h") {
@@ -1563,7 +1577,7 @@
     Features.push_back("-fsgsbase");
   }
 
-  // Add features to comply with gcc on Android
+  // Add features to be compatible with gcc for Android.
   if (Triple.getEnvironment() == llvm::Triple::Android) {
     if (Triple.getArch() == llvm::Triple::x86_64) {
       Features.push_back("+sse4.2");
@@ -1572,7 +1586,7 @@
       Features.push_back("+ssse3");
   }
 
-  // Set features according to the -arch flag on MSVC
+  // Set features according to the -arch flag on MSVC.
   if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
     StringRef Arch = A->getValue();
     bool ArchUsed = false;
@@ -2269,13 +2283,16 @@
     StaticRuntimes.push_back("tsan");
   // WARNING: UBSan should always go last.
   if (SanArgs.needsUbsanRt()) {
-    // If UBSan is not combined with another sanitizer, we need to pull in
-    // sanitizer_common explicitly.
-    if (StaticRuntimes.empty())
-      HelperStaticRuntimes.push_back("san");
-    StaticRuntimes.push_back("ubsan");
-    if (SanArgs.linkCXXRuntimes())
-      StaticRuntimes.push_back("ubsan_cxx");
+    // Check if UBSan is combined with another sanitizers.
+    if (StaticRuntimes.empty()) {
+      StaticRuntimes.push_back("ubsan_standalone");
+      if (SanArgs.linkCXXRuntimes())
+        StaticRuntimes.push_back("ubsan_standalone_cxx");
+    } else {
+      StaticRuntimes.push_back("ubsan");
+      if (SanArgs.linkCXXRuntimes())
+        StaticRuntimes.push_back("ubsan_cxx");
+    }
   }
 }
 
@@ -2468,24 +2485,17 @@
     CmdArgs.push_back(types::getTypeName(Input.getType()));
 }
 
-static std::string getMSCompatibilityVersion(const char *VersionStr) {
-  unsigned Version;
-  if (StringRef(VersionStr).getAsInteger(10, Version))
-    return "0";
-
+static VersionTuple getMSCompatibilityVersion(unsigned Version) {
   if (Version < 100)
-    return llvm::utostr_32(Version) + ".0";
+    return VersionTuple(Version);
 
   if (Version < 10000)
-    return llvm::utostr_32(Version / 100) + "." +
-        llvm::utostr_32(Version % 100);
+    return VersionTuple(Version / 100, Version % 100);
 
   unsigned Build = 0, Factor = 1;
   for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10)
     Build = Build + (Version % 10) * Factor;
-  return llvm::utostr_32(Version / 100) + "." +
-      llvm::utostr_32(Version % 100) + "." +
-      llvm::utostr_32(Build);
+  return VersionTuple(Version / 100, Version % 100, Build);
 }
 
 // Claim options we don't want to warn if they are unused. We do this for
@@ -2850,6 +2860,8 @@
   else
     CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel()));
 
+  Args.AddLastArg(CmdArgs, options::OPT_fveclib);
+
   if (!Args.hasFlag(options::OPT_fmerge_all_constants,
                     options::OPT_fno_merge_all_constants))
     CmdArgs.push_back("-fno-merge-all-constants");
@@ -3306,13 +3318,16 @@
     CmdArgs.push_back("-generate-type-units");
   }
 
+  // CloudABI uses -ffunction-sections and -fdata-sections by default.
+  bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI;
+
   if (Args.hasFlag(options::OPT_ffunction_sections,
-                   options::OPT_fno_function_sections, false)) {
+                   options::OPT_fno_function_sections, UseSeparateSections)) {
     CmdArgs.push_back("-ffunction-sections");
   }
 
   if (Args.hasFlag(options::OPT_fdata_sections,
-                   options::OPT_fno_data_sections, false)) {
+                   options::OPT_fno_data_sections, UseSeparateSections)) {
     CmdArgs.push_back("-fdata-sections");
   }
 
@@ -3361,10 +3376,10 @@
       } else {
         CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
       }
-      if (llvm::sys::path::is_relative(CoverageFilename.str())) {
+      if (llvm::sys::path::is_relative(CoverageFilename)) {
         SmallString<128> Pwd;
         if (!llvm::sys::fs::current_path(Pwd)) {
-          llvm::sys::path::append(Pwd, CoverageFilename.str());
+          llvm::sys::path::append(Pwd, CoverageFilename);
           CoverageFilename.swap(Pwd);
         }
       }
@@ -3447,6 +3462,7 @@
     Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
     Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
     Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
+    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax);
     Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
     Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
     Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
@@ -4032,8 +4048,9 @@
 
   ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
 
-  if (RTTIMode == ToolChain::RM_DisabledExplicitly ||
-      RTTIMode == ToolChain::RM_DisabledImplicitly)
+  if (KernelOrKext || (types::isCXX(InputType) &&
+                       (RTTIMode == ToolChain::RM_DisabledExplicitly ||
+                        RTTIMode == ToolChain::RM_DisabledImplicitly)))
     CmdArgs.push_back("-fno-rtti");
 
   // -fshort-enums=0 is default for all architectures except Hexagon.
@@ -4048,11 +4065,6 @@
                     isSignedCharDefault(getToolChain().getTriple())))
     CmdArgs.push_back("-fno-signed-char");
 
-  // -fthreadsafe-static is default.
-  if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
-                    options::OPT_fno_threadsafe_statics))
-    CmdArgs.push_back("-fno-threadsafe-statics");
-
   // -fuse-cxa-atexit is default.
   if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
                     options::OPT_fno_use_cxa_atexit,
@@ -4080,9 +4092,11 @@
                                                   true))))
     CmdArgs.push_back("-fms-compatibility");
 
-  // -fms-compatibility-version=17.00 is default.
+  // -fms-compatibility-version=18.00 is default.
+  VersionTuple MSVT;
   if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
-                   IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) ||
+                   IsWindowsMSVC) ||
+      Args.hasArg(options::OPT_fmsc_version) ||
       Args.hasArg(options::OPT_fms_compatibility_version)) {
     const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
     const Arg *MSCompatibilityVersion =
@@ -4093,16 +4107,23 @@
           << MSCVersion->getAsString(Args)
           << MSCompatibilityVersion->getAsString(Args);
 
-    std::string Ver;
-    if (MSCompatibilityVersion)
-      Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version);
-    else if (MSCVersion)
-      Ver = getMSCompatibilityVersion(MSCVersion->getValue());
+    if (MSCompatibilityVersion) {
+      if (MSVT.tryParse(MSCompatibilityVersion->getValue()))
+        D.Diag(diag::err_drv_invalid_value)
+            << MSCompatibilityVersion->getAsString(Args)
+            << MSCompatibilityVersion->getValue();
+    } else if (MSCVersion) {
+      unsigned Version = 0;
+      if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version))
+        D.Diag(diag::err_drv_invalid_value) << MSCVersion->getAsString(Args)
+                                            << MSCVersion->getValue();
+      MSVT = getMSCompatibilityVersion(Version);
+    } else {
+      MSVT = VersionTuple(18);
+    }
 
-    if (Ver.empty())
-      CmdArgs.push_back("-fms-compatibility-version=18.00");
-    else
-      CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
+    CmdArgs.push_back(
+        Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
   }
 
   // -fno-borland-extensions is default.
@@ -4110,6 +4131,13 @@
                    options::OPT_fno_borland_extensions, false))
     CmdArgs.push_back("-fborland-extensions");
 
+  // -fthreadsafe-static is default, except for MSVC compatibility versions less
+  // than 19.
+  if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
+                    options::OPT_fno_threadsafe_statics,
+                    !IsWindowsMSVC || MSVT.getMajor() >= 19))
+    CmdArgs.push_back("-fno-threadsafe-statics");
+
   // -fno-delayed-template-parsing is default, except for Windows where MSVC STL
   // needs it.
   if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
@@ -4215,6 +4243,10 @@
     }
   }
 
+  if (Args.hasFlag(options::OPT_fapplication_extension,
+                   options::OPT_fno_application_extension, false))
+    CmdArgs.push_back("-fapplication-extension");
+
   // Handle GCC-style exception args.
   if (!C.getDriver().IsCLMode())
     addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext,
@@ -4228,6 +4260,12 @@
                     options::OPT_fno_assume_sane_operator_new))
     CmdArgs.push_back("-fno-assume-sane-operator-new");
 
+  // -fsized-deallocation is off by default, as it is an ABI-breaking change for
+  // most platforms.
+  if (Args.hasFlag(options::OPT_fsized_deallocation,
+                   options::OPT_fno_sized_deallocation, false))
+    CmdArgs.push_back("-fsized-deallocation");
+
   // -fconstant-cfstrings is default, and may be subject to argument translation
   // on Darwin.
   if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
@@ -4582,7 +4620,7 @@
       Flags += EscapedArg;
     }
     CmdArgs.push_back("-dwarf-debug-flags");
-    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+    CmdArgs.push_back(Args.MakeArgString(Flags));
   }
 
   // Add the split debug info name to the command lines here so we
@@ -5042,7 +5080,7 @@
       Flags += EscapedArg;
     }
     CmdArgs.push_back("-dwarf-debug-flags");
-    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+    CmdArgs.push_back(Args.MakeArgString(Flags));
   }
 
   // FIXME: Add -static support, once we have it.
@@ -5542,8 +5580,9 @@
     .Cases("arm9e",  "arm926ej-s",  "arm946e-s", "v5e")
     .Cases("arm966e-s",  "arm968e-s",  "arm10e", "v5e")
     .Cases("arm1020e",  "arm1022e",  "xscale", "iwmmxt", "v5e")
-    .Cases("arm1136j-s",  "arm1136jf-s",  "arm1176jz-s", "v6")
-    .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")
+    .Cases("arm1136j-s",  "arm1136jf-s", "v6")
+    .Cases("arm1176jz-s", "arm1176jzf-s", "v6k")
+    .Cases("mpcorenovfp",  "mpcore", "v6k")
     .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")
     .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
     .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7")
@@ -5564,7 +5603,7 @@
   StringRef Suffix = getLLVMArchSuffixForARM(getARMCPUForMArch(Args, Triple));
   const char *LinkFlag = llvm::StringSwitch<const char *>(Suffix)
     .Cases("v4", "v4t", "v5", "v5e", nullptr)
-    .Cases("v6", "v6t2", nullptr)
+    .Cases("v6", "v6k", "v6t2", nullptr)
     .Default("--be8");
 
   if (LinkFlag)
@@ -5689,6 +5728,76 @@
   return Args.MakeArgString(Res + ".d");
 }
 
+void cloudabi::Link::ConstructJob(Compilation &C, const JobAction &JA,
+                                  const InputInfo &Output,
+                                  const InputInfoList &Inputs,
+                                  const ArgList &Args,
+                                  const char *LinkingOutput) const {
+  const ToolChain &ToolChain = getToolChain();
+  const Driver &D = ToolChain.getDriver();
+  ArgStringList CmdArgs;
+
+  // Silence warning for "clang -g foo.o -o foo"
+  Args.ClaimAllArgs(options::OPT_g_Group);
+  // and "clang -emit-llvm foo.o -o foo"
+  Args.ClaimAllArgs(options::OPT_emit_llvm);
+  // and for "clang -w foo.o -o foo". Other warning options are already
+  // handled somewhere else.
+  Args.ClaimAllArgs(options::OPT_w);
+
+  if (!D.SysRoot.empty())
+    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+  // CloudABI only supports static linkage.
+  CmdArgs.push_back("-Bstatic");
+  CmdArgs.push_back("--eh-frame-hdr");
+  CmdArgs.push_back("--gc-sections");
+
+  if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_L);
+  const ToolChain::path_list &Paths = ToolChain.getFilePaths();
+  for (const auto &Path : Paths)
+    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_e);
+  Args.AddAllArgs(CmdArgs, options::OPT_s);
+  Args.AddAllArgs(CmdArgs, options::OPT_t);
+  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+  Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+  if (D.IsUsingLTO(ToolChain, Args))
+    AddGoldPlugin(ToolChain, Args, CmdArgs);
+
+  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    if (D.CCCIsCXX())
+      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+    CmdArgs.push_back("-lc");
+    CmdArgs.push_back("-lcompiler_rt");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles))
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+
+  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
+}
+
 void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
@@ -5810,6 +5919,12 @@
   if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
     CmdArgs.push_back("-export_dynamic");
 
+  // If we are using App Extension restrictions, pass a flag to the linker
+  // telling it that the compiled code has been audited.
+  if (Args.hasFlag(options::OPT_fapplication_extension,
+                   options::OPT_fno_application_extension, false))
+    CmdArgs.push_back("-application_extension");
+
   // If we are using LTO, then automatically create a temporary file path for
   // the linker to use, so that it's lifetime will extend past a possible
   // dsymutil step.
@@ -6110,6 +6225,16 @@
     CmdArgs.push_back(Args.MakeArgString(std::string("-F") +
                                          (*it)->getValue()));
 
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
+      if (A->getValue() == StringRef("Accelerate")) {
+        CmdArgs.push_back("-framework");
+        CmdArgs.push_back("Accelerate");
+      }
+    }
+  }
+
   const char *Exec =
     Args.MakeArgString(getToolChain().GetLinkerPath());
   std::unique_ptr<Command> Cmd =
@@ -7209,47 +7334,64 @@
   ArgStringList CmdArgs;
   bool NeedsKPIC = false;
 
+  switch (getToolChain().getArch()) {
+  default:
+    break;
   // Add --32/--64 to make sure we get the format we want.
   // This is incomplete
-  if (getToolChain().getArch() == llvm::Triple::x86) {
+  case llvm::Triple::x86:
     CmdArgs.push_back("--32");
-  } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
+    break;
+  case llvm::Triple::x86_64:
     if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
       CmdArgs.push_back("--x32");
     else
       CmdArgs.push_back("--64");
-  } else if (getToolChain().getArch() == llvm::Triple::ppc) {
+    break;
+  case llvm::Triple::ppc:
     CmdArgs.push_back("-a32");
     CmdArgs.push_back("-mppc");
     CmdArgs.push_back("-many");
-  } else if (getToolChain().getArch() == llvm::Triple::ppc64) {
+    break;
+  case llvm::Triple::ppc64:
     CmdArgs.push_back("-a64");
     CmdArgs.push_back("-mppc64");
     CmdArgs.push_back("-many");
-  } else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
+    break;
+  case llvm::Triple::ppc64le:
     CmdArgs.push_back("-a64");
     CmdArgs.push_back("-mppc64");
     CmdArgs.push_back("-many");
     CmdArgs.push_back("-mlittle-endian");
-  } else if (getToolChain().getArch() == llvm::Triple::sparc) {
+    break;
+  case llvm::Triple::sparc:
     CmdArgs.push_back("-32");
     CmdArgs.push_back("-Av8plusa");
     NeedsKPIC = true;
-  } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
+    break;
+  case llvm::Triple::sparcv9:
     CmdArgs.push_back("-64");
     CmdArgs.push_back("-Av9a");
     NeedsKPIC = true;
-  } else if (getToolChain().getArch() == llvm::Triple::arm ||
-             getToolChain().getArch() == llvm::Triple::armeb) {
-    StringRef MArch = getToolChain().getArchName();
-    if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+    break;
+  case llvm::Triple::arm:
+  case llvm::Triple::armeb:
+  case llvm::Triple::thumb:
+  case llvm::Triple::thumbeb: {
+    const llvm::Triple &Triple = getToolChain().getTriple();
+    switch (Triple.getSubArch()) {
+    case llvm::Triple::ARMSubArch_v7:
       CmdArgs.push_back("-mfpu=neon");
-    if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" ||
-        MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a")
+      break;
+    case llvm::Triple::ARMSubArch_v8:
       CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
+      break;
+    default:
+      break;
+    }
 
     StringRef ARMFloatABI = tools::arm::getARMFloatABI(
-        getToolChain().getDriver(), Args, getToolChain().getTriple());
+        getToolChain().getDriver(), Args, Triple);
     CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));
 
     Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
@@ -7264,10 +7406,12 @@
     else
       Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
     Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
-  } else if (getToolChain().getArch() == llvm::Triple::mips ||
-             getToolChain().getArch() == llvm::Triple::mipsel ||
-             getToolChain().getArch() == llvm::Triple::mips64 ||
-             getToolChain().getArch() == llvm::Triple::mips64el) {
+    break;
+  }
+  case llvm::Triple::mips:
+  case llvm::Triple::mipsel:
+  case llvm::Triple::mips64:
+  case llvm::Triple::mips64el: {
     StringRef CPUName;
     StringRef ABIName;
     mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
@@ -7351,11 +7495,15 @@
                     options::OPT_mno_odd_spreg);
 
     NeedsKPIC = true;
-  } else if (getToolChain().getArch() == llvm::Triple::systemz) {
+    break;
+  }
+  case llvm::Triple::systemz: {
     // Always pass an -march option, since our default of z10 is later
     // than the GNU assembler's default.
     StringRef CPUName = getSystemZTargetCPU(Args);
     CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
+    break;
+  }
   }
 
   if (NeedsKPIC)
@@ -7564,11 +7712,7 @@
   const bool IsPIE =
     !Args.hasArg(options::OPT_shared) &&
     !Args.hasArg(options::OPT_static) &&
-    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
-     // On Android every code is PIC so every executable is PIE
-     // Cannot use isPIEDefault here since otherwise
-     // PIE only logic will be enabled during compilation
-     isAndroid);
+    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
 
   ArgStringList CmdArgs;
 
@@ -7696,6 +7840,8 @@
       CmdArgs.push_back("-Bdynamic");
     CmdArgs.push_back("-lm");
   }
+  // Silence warnings when linking C code with a C++ '-stdlib' argument.
+  Args.ClaimAllArgs(options::OPT_stdlib_EQ);
 
   if (!Args.hasArg(options::OPT_nostdlib)) {
     if (!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -8055,8 +8201,8 @@
   if (!llvm::sys::Process::GetEnv("LIB")) {
     // If the VC environment hasn't been configured (perhaps because the user
     // did not run vcvarsall), try to build a consistent link environment.  If
-    // the environment variable is set however, assume the user knows what he's
-    // doing.
+    // the environment variable is set however, assume the user knows what
+    // they're doing.
     std::string VisualStudioDir;
     const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
     if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) {
@@ -8090,14 +8236,16 @@
   if (Args.hasArg(options::OPT_g_Group))
     CmdArgs.push_back("-debug");
 
-  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
+  bool DLL = Args.hasArg(options::OPT__SLASH_LD,
+                         options::OPT__SLASH_LDd,
+                         options::OPT_shared);
   if (DLL) {
     CmdArgs.push_back(Args.MakeArgString("-dll"));
 
     SmallString<128> ImplibName(Output.getFilename());
     llvm::sys::path::replace_extension(ImplibName, "lib");
     CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
-                                         ImplibName.str()));
+                                         ImplibName));
   }
 
   if (TC.getSanitizerArgs().needsAsanRt()) {
@@ -8214,7 +8362,7 @@
     }
   }
 
-  // Flags for which clang-cl have an alias.
+  // Flags for which clang-cl has an alias.
   // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
 
   if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
@@ -8234,7 +8382,8 @@
   if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
     CmdArgs.push_back("/Z7");
 
-  std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
+  std::vector<std::string> Includes =
+      Args.getAllArgValues(options::OPT_include);
   for (const auto &Include : Includes)
     CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
 
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 93a19fb..5161557 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -248,6 +248,22 @@
   bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value);
 }
 
+  /// cloudabi -- Directly call GNU Binutils linker
+namespace cloudabi {
+class LLVM_LIBRARY_VISIBILITY Link : public GnuTool {
+public:
+  Link(const ToolChain &TC) : GnuTool("cloudabi::Link", "linker", TC) {}
+
+  bool hasIntegratedCPP() const override { return false; }
+  bool isLinkJob() const override { return true; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+                    const InputInfo &Output, const InputInfoList &Inputs,
+                    const llvm::opt::ArgList &TCArgs,
+                    const char *LinkingOutput) const override;
+};
+} // end namespace cloudabi
+
 namespace darwin {
   llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
   void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 6ee764c..7b28145 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -85,7 +85,7 @@
   case TY_Asm:
   case TY_C: case TY_PP_C:
   case TY_CL:
-  case TY_CUDA:
+  case TY_CUDA: case TY_PP_CUDA:
   case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
   case TY_CXX: case TY_PP_CXX:
   case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
@@ -122,7 +122,7 @@
   case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
   case TY_CXXHeader: case TY_PP_CXXHeader:
   case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
-  case TY_CUDA:
+  case TY_CUDA: case TY_PP_CUDA:
     return true;
   }
 }
@@ -153,6 +153,7 @@
            .Case("cl", TY_CL)
            .Case("cp", TY_CXX)
            .Case("cu", TY_CUDA)
+           .Case("cui", TY_PP_CUDA)
            .Case("hh", TY_CXXHeader)
            .Case("ll", TY_LLVM_IR)
            .Case("hpp", TY_CXXHeader)