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).

llvm-svn: 273171
This commit is contained in:
Adrian McCarthy 2016-06-20 17:51:27 +00:00
parent a038240660
commit f833141187
1 changed files with 34 additions and 2 deletions

View 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,19 @@ Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
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;