OSDN Git Service

Properly handle short file names on the command line in Windows
authorAdrian McCarthy <amccarth@google.com>
Thu, 16 Jun 2016 22:07:55 +0000 (22:07 +0000)
committerAdrian McCarthy <amccarth@google.com>
Thu, 16 Jun 2016 22:07:55 +0000 (22:07 +0000)
Some build systems use the short (8.3) file names on Windows, especially if the path has spaces in it. The shortening made it impossible for clang to distinguish between clang.exe, clang++.exe, and clang-cl.exe.  So this expands short names in the first argument and does wildcard expansion for the rest.

Differential Revision: http://reviews.llvm.org/D21420

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272967 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/Windows/Process.inc

index 3aef79f..12b1b4d 100644 (file)
@@ -201,6 +201,9 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
   const int DirSize = Dir.size();
 
   // Search for matching files.
+  // FIXME:  This assumes the wildcard is only in the file name and not in the
+  // directory portion of the file path.  For example, it doesn't handle
+  // "*\foo.c" nor "s?c\bar.cpp".
   WIN32_FIND_DATAW FileData;
   HANDLE FindHandle = FindFirstFileW(Arg, &FileData);
   if (FindHandle == INVALID_HANDLE_VALUE) {
@@ -215,7 +218,7 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
     if (ec)
       break;
 
-    // Push the filename onto Dir, and remove it afterwards.
+    // Append FileName to Dir, and remove it afterwards.
     llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size()));
     AllocateAndPush(Dir, Args, Allocator);
     Dir.resize(DirSize);
@@ -225,6 +228,23 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
   return ec;
 }
 
+static std::error_code
+ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
+  SpecificBumpPtrAllocator<char> &Allocator) {
+  SmallVector<wchar_t, MAX_PATH> LongPath;
+  DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity());
+  if (Length == 0)
+    return mapWindowsError(GetLastError());
+  if (Length > LongPath.capacity()) {
+    // We're not going to try to deal with paths longer than MAX_PATH, so we'll
+    // treat this as an error.  GetLastError() returns ERROR_SUCCESS, which
+    // isn't useful, so we'll hardcode an appropriate error value.
+    return mapWindowsError(ERROR_INSUFFICIENT_BUFFER);
+  }
+  LongPath.set_size(Length);
+  return ConvertAndPushArg(LongPath.data(), Args, Allocator);
+}
+
 std::error_code
 Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
                            ArrayRef<const char *>,
@@ -238,7 +258,12 @@ Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
   Args.reserve(ArgCount);
   std::error_code ec;
 
-  for (int i = 0; i < ArgCount; ++i) {
+  // If the first argument is a shortenedd (8.3) name, the driver will have
+  // trouble distinguishing it (e.g., clang.exe v. clang++.exe), so make sure
+  // it's a full name.
+  ec = ExpandShortFileName(UnicodeCommandLine[0], Args, ArgAllocator);
+
+  for (int i = 1; i < ArgCount && !ec; ++i) {
     ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);
     if (ec)
       break;