From: Adrian McCarthy Date: Thu, 16 Jun 2016 22:07:55 +0000 (+0000) Subject: Properly handle short file names on the command line in Windows X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3e5651782cfc985fca9d94595cad63059e587e2f;p=llvm Properly handle short file names on the command line in Windows 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 --- diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index 3aef79fee84..12b1b4dcf3a 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -201,6 +201,9 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl &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 &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 &Args, return ec; } +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) + 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 &Args, ArrayRef, @@ -238,7 +258,12 @@ Process::GetArgumentVector(SmallVectorImpl &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;