Reland [clangd] Resolve driver symlinks, and look up unknown relative drivers in PATH.

This reverts commit f25e3c2d0e8553e6640ca5e0d1933c0e9455bd71.
Added workaround for tempdir being a symlink on mac.
diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 84f72f5..a73312a 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -119,6 +119,48 @@
   return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy);
 }
 
+// The path passed to argv[0] is important:
+//  - its parent directory is Driver::Dir, used for library discovery
+//  - its basename affects CLI parsing (clang-cl) and other settings
+// Where possible it should be an absolute path with sensible directory, but
+// with the original basename.
+static std::string resolveDriver(llvm::StringRef Driver, bool FollowSymlink,
+                                 llvm::Optional<std::string> ClangPath) {
+  auto SiblingOf = [&](llvm::StringRef AbsPath) {
+    llvm::SmallString<128> Result = llvm::sys::path::parent_path(AbsPath);
+    llvm::sys::path::append(Result, llvm::sys::path::filename(Driver));
+    return Result.str().str();
+  };
+
+  // First, eliminate relative paths.
+  std::string Storage;
+  if (!llvm::sys::path::is_absolute(Driver)) {
+    // If the driver is a generic like "g++" with no path, add clang dir.
+    if (ClangPath &&
+        (Driver == "clang" || Driver == "clang++" || Driver == "gcc" ||
+         Driver == "g++" || Driver == "cc" || Driver == "c++")) {
+      return SiblingOf(*ClangPath);
+    }
+    // Otherwise try to look it up on PATH. This won't change basename.
+    auto Absolute = llvm::sys::findProgramByName(Driver);
+    if (Absolute && llvm::sys::path::is_absolute(*Absolute))
+      Driver = Storage = std::move(*Absolute);
+    else if (ClangPath) // If we don't find it, use clang dir again.
+      return SiblingOf(*ClangPath);
+    else // Nothing to do: can't find the command and no detected dir.
+      return Driver.str();
+  }
+
+  // Now we have an absolute path, but it may be a symlink.
+  assert(llvm::sys::path::is_absolute(Driver));
+  if (FollowSymlink) {
+    llvm::SmallString<256> Resolved;
+    if (!llvm::sys::fs::real_path(Driver, Resolved))
+      return SiblingOf(Resolved);
+  }
+  return Driver.str();
+}
+
 } // namespace
 
 CommandMangler CommandMangler::detect() {
@@ -162,25 +204,22 @@
     Cmd.push_back(*Sysroot);
   }
 
-  // If the driver is a generic name like "g++" with no path, add a clang path.
-  // This makes it easier for us to find the standard libraries on mac.
-  if (ClangPath && llvm::sys::path::is_absolute(*ClangPath) && !Cmd.empty()) {
-    std::string &Driver = Cmd.front();
-    if (Driver == "clang" || Driver == "clang++" || Driver == "gcc" ||
-        Driver == "g++" || Driver == "cc" || Driver == "c++") {
-      llvm::SmallString<128> QualifiedDriver =
-          llvm::sys::path::parent_path(*ClangPath);
-      llvm::sys::path::append(QualifiedDriver, Driver);
-      Driver = std::string(QualifiedDriver.str());
-    }
+  if (!Cmd.empty()) {
+    bool FollowSymlink = !Has("-no-canonical-prefixes");
+    Cmd.front() =
+        (FollowSymlink ? ResolvedDrivers : ResolvedDriversNoFollow)
+            .get(Cmd.front(), [&, this] {
+              return resolveDriver(Cmd.front(), FollowSymlink, ClangPath);
+            });
   }
 }
 
-CommandMangler::operator clang::tooling::ArgumentsAdjuster() {
-  return [Mangler{*this}](const std::vector<std::string> &Args,
-                          llvm::StringRef File) {
+CommandMangler::operator clang::tooling::ArgumentsAdjuster() && {
+  // ArgumentsAdjuster is a std::function and so must be copyable.
+  return [Mangler = std::make_shared<CommandMangler>(std::move(*this))](
+             const std::vector<std::string> &Args, llvm::StringRef File) {
     auto Result = Args;
-    Mangler.adjust(Result);
+    Mangler->adjust(Result);
     return Result;
   };
 }