[llvm] r273171 - Properly handle short file names on the command line in Windows [TAKE 2]

Adrian McCarthy via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 20 10:51:28 PDT 2016


Author: amccarth
Date: Mon Jun 20 12:51:27 2016
New Revision: 273171

URL: http://llvm.org/viewvc/llvm-project?rev=273171&view=rev
Log:
Properly handle short file names on the command line in Windows [TAKE 2]

Trying to expand short names with a relative path doesn't work, so this
first gets the module name to get a full path (which can still have short
names).

Modified:
    llvm/trunk/lib/Support/Windows/Process.inc

Modified: llvm/trunk/lib/Support/Windows/Process.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Process.inc?rev=273171&r1=273170&r2=273171&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Windows/Process.inc (original)
+++ llvm/trunk/lib/Support/Windows/Process.inc Mon Jun 20 12:51:27 2016
@@ -201,6 +201,9 @@ WildcardExpand(const wchar_t *Arg, Small
   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, Small
     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, Small
   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,19 @@ Process::GetArgumentVector(SmallVectorIm
   Args.reserve(ArgCount);
   std::error_code ec;
 
-  for (int i = 0; i < ArgCount; ++i) {
+  // The first argument may contain just the name of the executable (e.g.,
+  // "clang") rather than the full path, so swap it with the full path.
+  wchar_t ModuleName[MAX_PATH];
+  int Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH);
+  if (0 < Length && Length < MAX_PATH)
+    UnicodeCommandLine[0] = ModuleName;
+
+  // If the first argument is a shortened (8.3) name (which is possible even
+  // if we got the module name), the driver will have trouble distinguishing it
+  // (e.g., clang.exe v. clang++.exe), so expand it now.
+  ec = ExpandShortFileName(UnicodeCommandLine[0], Args, ArgAllocator);
+
+  for (int i = 1; i < ArgCount && !ec; ++i) {
     ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator);
     if (ec)
       break;




More information about the llvm-commits mailing list