29
29
#include " swift/FrontendTool/FrontendTool.h"
30
30
#include " llvm/ADT/SmallVector.h"
31
31
#include " llvm/Support/CommandLine.h"
32
+ #include " llvm/Support/ConvertUTF.h"
32
33
#include " llvm/Support/Errno.h"
33
34
#include " llvm/Support/FileSystem.h"
34
35
#include " llvm/Support/Host.h"
45
46
#include < memory>
46
47
#include < stdlib.h>
47
48
49
+ #if defined(_WIN32)
50
+ #include < windows.h>
51
+ #endif
52
+
48
53
using namespace swift ;
49
54
using namespace swift ::driver;
50
55
@@ -174,6 +179,26 @@ static int run_driver(StringRef ExecName,
174
179
}
175
180
176
181
int main (int argc_, const char **argv_) {
182
+ #if defined(_WIN32)
183
+ LPWSTR *wargv_ = CommandLineToArgvW (GetCommandLineW (), &argc_);
184
+ std::vector<std::string> utf8Args;
185
+ // We use UTF-8 as the internal character encoding. On Windows,
186
+ // arguments passed to wmain are encoded in UTF-16
187
+ for (int i = 0 ; i < argc_; i++) {
188
+ const wchar_t *wideArg = wargv_[i];
189
+ int wideArgLen = std::wcslen (wideArg);
190
+ utf8Args.push_back (" " );
191
+ llvm::ArrayRef<char > uRef ((const char *)wideArg,
192
+ (const char *)(wideArg + wideArgLen));
193
+ llvm::convertUTF16ToUTF8String (uRef, utf8Args[i]);
194
+ }
195
+
196
+ std::vector<const char *> utf8CStrs;
197
+ std::transform (utf8Args.begin (), utf8Args.end (),
198
+ std::back_inserter (utf8CStrs),
199
+ std::mem_fn (&std::string::c_str));
200
+ argv_ = utf8CStrs.data ();
201
+ #endif
177
202
// Expand any response files in the command line argument vector - arguments
178
203
// may be passed through response files in the event of command line length
179
204
// restrictions.
@@ -182,17 +207,22 @@ int main(int argc_, const char **argv_) {
182
207
llvm::StringSaver Saver (Allocator);
183
208
llvm::cl::ExpandResponseFiles (
184
209
Saver,
185
- llvm::Triple (llvm::sys::getProcessTriple ()).isOSWindows () ?
186
- llvm::cl::TokenizeWindowsCommandLine :
187
- llvm::cl::TokenizeGNUCommandLine,
210
+ llvm::Triple (llvm::sys::getProcessTriple ()).isOSWindows ()
211
+ ? llvm::cl::TokenizeWindowsCommandLine
212
+ : llvm::cl::TokenizeGNUCommandLine,
188
213
ExpandedArgs);
189
214
190
215
// Initialize the stack trace using the parsed argument vector with expanded
191
216
// response files.
192
- int ExpandedArgc = ExpandedArgs.size ();
193
- const char **ExpandedArgv = ExpandedArgs.data ();
194
- PROGRAM_START (ExpandedArgc, ExpandedArgv);
195
- ArrayRef<const char *> argv (ExpandedArgv, ExpandedArgc);
217
+
218
+ // PROGRAM_START/InitLLVM overwrites the passed in arguments with UTF-8
219
+ // versions of them on Windows. This also has the effect of overwriting the
220
+ // response file expansion. Since we handle the UTF-8 conversion above, we
221
+ // pass in a copy and throw away the modifications.
222
+ int ThrowawayExpandedArgc = ExpandedArgs.size ();
223
+ const char **ThrowawayExpandedArgv = ExpandedArgs.data ();
224
+ PROGRAM_START (ThrowawayExpandedArgc, ThrowawayExpandedArgv);
225
+ ArrayRef<const char *> argv (ExpandedArgs);
196
226
197
227
// Check if this invocation should execute a subcommand.
198
228
StringRef ExecName = llvm::sys::path::stem (argv[0 ]);
0 commit comments