[PATCH] D21420: Properly handle short file names on the command line in Windows

Adrian McCarthy via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 15 16:29:42 PDT 2016


amccarth created this revision.
amccarth added reviewers: majnemer, rnk.
amccarth added a subscriber: llvm-commits.

This addresses:  https://llvm.org/bugs/show_bug.cgi?id=28089

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, in addition to expanding wildcards, the code now replaces short names with long ones.

Tested with ninja check-clang.

http://reviews.llvm.org/D21420

Files:
  lib/Support/Windows/Process.inc

Index: lib/Support/Windows/Process.inc
===================================================================
--- lib/Support/Windows/Process.inc
+++ lib/Support/Windows/Process.inc
@@ -178,19 +178,40 @@
   return std::error_code();
 }
 
+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) {
+    DWORD LastError = GetLastError();
+    if (LastError == ERROR_INVALID_NAME ||
+        LastError == ERROR_FILE_NOT_FOUND ||
+        LastError == ERROR_PATH_NOT_FOUND) {
+      // This argument is probably not a file name.
+      return ConvertAndPushArg(Arg, Args, Allocator);
+    }
+    return mapWindowsError(LastError);
+  } else if (Length > MAX_PATH)
+    return mapWindowsError(GetLastError());
+  LongPath.set_size(Length);
+
+  return ConvertAndPushArg(LongPath.data(), Args, Allocator);
+}
+
 /// \brief Perform wildcard expansion of Arg, or just push it into Args if it
 /// doesn't have wildcards or doesn't match any files.
 static std::error_code
 WildcardExpand(const wchar_t *Arg, SmallVectorImpl<const char *> &Args,
                SpecificBumpPtrAllocator<char> &Allocator) {
   if (!wcspbrk(Arg, L"*?")) {
     // Arg does not contain any wildcard characters. This is the common case.
-    return ConvertAndPushArg(Arg, Args, Allocator);
+    return ExpandShortFileName(Arg, Args, Allocator);
   }
 
   if (wcscmp(Arg, L"/?") == 0 || wcscmp(Arg, L"-?") == 0) {
     // Don't wildcard expand /?. Always treat it as an option.
-    return ConvertAndPushArg(Arg, Args, Allocator);
+    return ExpandShortFileName(Arg, Args, Allocator);
   }
 
   // Extract any directory part of the argument.
@@ -201,6 +222,9 @@
   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,9 +239,19 @@
     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);
+    // Now we have a file spec in Dir, but it's been prematurely converted to
+    // UTF-8.  In order to expand the short file names, we need to once again
+    // convert to UTF-16.
+    SmallVector<wchar_t, MAX_PATH> WideFileSpec;
+    ec = windows::UTF8ToUTF16(llvm::StringRef(Dir.data(), Dir.size()),
+                              WideFileSpec);
+    if (ec)
+      break;
+    ec = ExpandShortFileName(WideFileSpec.data(), Args, Allocator);
+    if (ec)
+      break;
     Dir.resize(DirSize);
   } while (FindNextFileW(FindHandle, &FileData));
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21420.60926.patch
Type: text/x-patch
Size: 3122 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160615/4cde7edd/attachment.bin>


More information about the llvm-commits mailing list