Index: lib/Support/Windows/Process.inc =================================================================== --- lib/Support/Windows/Process.inc +++ lib/Support/Windows/Process.inc @@ -178,6 +178,27 @@ return std::error_code(); } +static std::error_code +ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl &Args, + SpecificBumpPtrAllocator &Allocator) { + SmallVector 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 @@ -185,12 +206,12 @@ SpecificBumpPtrAllocator &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 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));