Index: llvm/lib/Support/Windows/Process.inc =================================================================== --- llvm/lib/Support/Windows/Process.inc +++ llvm/lib/Support/Windows/Process.inc @@ -209,9 +209,7 @@ } static std::error_code ExpandShortFileName(const wchar_t *Arg, - SmallVectorImpl &Args, - BumpPtrAllocator &Alloc) { - SmallVector LongPath; + SmallVectorImpl &LongPath) { DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity()); if (Length == 0) return mapWindowsError(GetLastError()); @@ -222,7 +220,51 @@ return mapWindowsError(ERROR_INSUFFICIENT_BUFFER); } LongPath.set_size(Length); - return ConvertAndPushArg(LongPath.data(), Args, Alloc); + return std::error_code(); +} + +static std::error_code GetLongArgv0Path(const wchar_t *Argv0, + SmallVectorImpl &Args, + BumpPtrAllocator &Alloc) { + // 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); + SmallVector UTF16LongpathArgv0, UTF16Argv0; + + if (0 < Length && Length < MAX_PATH) + Argv0 = 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. + std::error_code ec = ExpandShortFileName(Argv0, UTF16LongpathArgv0); + if (ec) + return ec; + + // Replace filename in original argv0 with expanded filename. + // This may change argv0 like below, + // * clang -> clang.exe (just add extension) + // * CLANG_~1.EXE -> clang++.exe (extend shorname) + // This is for keeping relativeness of original argv0 path. + SmallVector UTF8LongPathArgv0; + ec = windows::UTF16ToUTF8(UTF16LongpathArgv0.data(), UTF16LongpathArgv0.size(), + UTF8LongPathArgv0); + if (ec) + return ec; + + SmallVector UTF8Argv0; + ec = windows::UTF16ToUTF8(Argv0, wcslen(Argv0), UTF8Argv0); + if (ec) + return ec; + + sys::path::remove_filename(UTF8Argv0); + sys::path::append(UTF8Argv0, sys::path::filename(UTF8LongPathArgv0.data())); + ec = windows::UTF8ToUTF16(UTF8Argv0.data(), UTF16Argv0); + if (ec) + return ec; + + return ConvertAndPushArg(UTF16Argv0.data(), Args, Alloc); } std::error_code @@ -235,19 +277,7 @@ return mapWindowsError(::GetLastError()); Args.reserve(ArgCount); - std::error_code ec; - - // 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, Alloc); + std::error_code ec = GetLongArgv0Path(UnicodeCommandLine[0], Args, Alloc); for (int i = 1; i < ArgCount && !ec; ++i) { ec = WildcardExpand(UnicodeCommandLine[i], Args, Alloc);