llvm.org GIT mirror llvm / bbb9ea7
Add KillTheDoctor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116216 91177308-0d34-0410-b5e6-96231b3b80d8 Michael J. Spencer 10 years ago
5 changed file(s) with 1560 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
388388 add_subdirectory(test)
389389 add_subdirectory(utils/unittest)
390390 add_subdirectory(unittests)
391 if (WIN32)
392 # This utility is used to prevent chrashing tests from calling Dr. Watson on
393 # Windows.
394 add_subdirectory(utils/KillTheDoctor)
395 endif()
391396 endif()
392397
393398 add_subdirectory(cmake/modules)
0 add_executable(KillTheDoctor
1 KillTheDoctor.cpp
2 system_error.cpp
3 )
4
5 target_link_libraries(KillTheDoctor LLVMSupport LLVMSystem)
0 //===- KillTheDoctor - Prevent Dr. Watson from stopping tests ---*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This program provides an extremely hacky way to stop Dr. Watson from starting
10 // due to unhandled exceptions in child processes.
11 //
12 // This simply starts the program named in the first positional argument with
13 // the arguments following it under a debugger. All this debugger does is catch
14 // any unhandled exceptions thrown in the child process and close the program
15 // (and hopefully tells someone about it).
16 //
17 // This also provides another really hacky method to prevent assert dialog boxes
18 // from poping up. When --no-user32 is passed, if any process loads user32.dll,
19 // we assume it is trying to call MessageBoxEx and terminate it. The proper way
20 // to do this would be to actually set a break point, but there's quite a bit
21 // of code involved to get the address of MessageBoxEx in the remote process's
22 // address space due to Address space layout randomization (ASLR). This can be
23 // added if it's ever actually needed.
24 //
25 // If the subprocess exits for any reason other than sucessful termination, -1
26 // is returned. If the process exits normally the value it returned is returned.
27 //
28 // I hate Windows.
29 //
30 //===----------------------------------------------------------------------===//
31
32 #include "llvm/ADT/STLExtras.h"
33 #include "llvm/ADT/SmallString.h"
34 #include "llvm/ADT/SmallVector.h"
35 #include "llvm/ADT/StringExtras.h"
36 #include "llvm/ADT/StringRef.h"
37 #include "llvm/ADT/Twine.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/ManagedStatic.h"
40 #include "llvm/Support/PrettyStackTrace.h"
41 #include "llvm/Support/raw_ostream.h"
42 #include "llvm/Support/type_traits.h"
43 #include "llvm/System/Signals.h"
44 #include "system_error.h"
45 #include
46 #include
47 #include
48 #include
49 #include
50 #include
51 #include
52 #include
53 #include
54 using namespace llvm;
55
56 #undef max
57
58 namespace {
59 cl::opt ProgramToRun(cl::Positional,
60 cl::desc(""));
61 cl::list Argv(cl::ConsumeAfter,
62 cl::desc("..."));
63 cl::opt TraceExecution("x",
64 cl::desc("Print detailed output about what is being run to stderr."));
65 cl::opt Timeout("t", cl::init(0),
66 cl::desc("Set maximum runtime in seconds. Defaults to infinite."));
67 cl::opt NoUser32("no-user32",
68 cl::desc("Terminate process if it loads user32.dll."));
69
70 StringRef ToolName;
71
72 template
73 class ScopedHandle {
74 typedef typename HandleType::handle_type handle_type;
75
76 handle_type Handle;
77
78 public:
79 ScopedHandle()
80 : Handle(HandleType::GetInvalidHandle()) {}
81
82 explicit ScopedHandle(handle_type handle)
83 : Handle(handle) {}
84
85 ~ScopedHandle() {
86 HandleType::Destruct(Handle);
87 }
88
89 ScopedHandle& operator=(handle_type handle) {
90 // Cleanup current handle.
91 if (!HandleType::isValid(Handle))
92 HandleType::Destruct(Handle);
93 Handle = handle;
94 return *this;
95 }
96
97 operator bool() const {
98 return HandleType::isValid(Handle);
99 }
100
101 operator handle_type() {
102 return Handle;
103 }
104 };
105
106 // This implements the most common handle in the Windows API.
107 struct CommonHandle {
108 typedef HANDLE handle_type;
109
110 static handle_type GetInvalidHandle() {
111 return INVALID_HANDLE_VALUE;
112 }
113
114 static void Destruct(handle_type Handle) {
115 ::CloseHandle(Handle);
116 }
117
118 static bool isValid(handle_type Handle) {
119 return Handle != GetInvalidHandle();
120 }
121 };
122
123 struct FileMappingHandle {
124 typedef HANDLE handle_type;
125
126 static handle_type GetInvalidHandle() {
127 return NULL;
128 }
129
130 static void Destruct(handle_type Handle) {
131 ::CloseHandle(Handle);
132 }
133
134 static bool isValid(handle_type Handle) {
135 return Handle != GetInvalidHandle();
136 }
137 };
138
139 struct MappedViewOfFileHandle {
140 typedef LPVOID handle_type;
141
142 static handle_type GetInvalidHandle() {
143 return NULL;
144 }
145
146 static void Destruct(handle_type Handle) {
147 ::UnmapViewOfFile(Handle);
148 }
149
150 static bool isValid(handle_type Handle) {
151 return Handle != GetInvalidHandle();
152 }
153 };
154
155 struct ProcessHandle : CommonHandle {};
156 struct ThreadHandle : CommonHandle {};
157 struct TokenHandle : CommonHandle {};
158 struct FileHandle : CommonHandle {};
159
160 typedef ScopedHandle FileMappingScopedHandle;
161 typedef ScopedHandle MappedViewOfFileScopedHandle;
162 typedef ScopedHandle ProcessScopedHandle;
163 typedef ScopedHandle ThreadScopedHandle;
164 typedef ScopedHandle TokenScopedHandle;
165 typedef ScopedHandle FileScopedHandle;
166
167 error_code get_windows_last_error() {
168 return make_error_code(windows_error(::GetLastError()));
169 }
170 }
171
172 static error_code GetFileNameFromHandle(HANDLE FileHandle,
173 std::string& Name) {
174 char Filename[MAX_PATH+1];
175 bool Sucess = false;
176 Name.clear();
177
178 // Get the file size.
179 LARGE_INTEGER FileSize;
180 Sucess = ::GetFileSizeEx(FileHandle, &FileSize);
181
182 if (!Sucess)
183 return get_windows_last_error();
184
185 // Create a file mapping object.
186 FileMappingScopedHandle FileMapping(
187 ::CreateFileMappingA(FileHandle,
188 NULL,
189 PAGE_READONLY,
190 0,
191 1,
192 NULL));
193
194 if (!FileMapping)
195 return get_windows_last_error();
196
197 // Create a file mapping to get the file name.
198 MappedViewOfFileScopedHandle MappedFile(
199 ::MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 1));
200
201 if (!MappedFile)
202 return get_windows_last_error();
203
204 Sucess = ::GetMappedFileNameA(::GetCurrentProcess(),
205 MappedFile,
206 Filename,
207 array_lengthof(Filename) - 1);
208
209 if (!Sucess)
210 return get_windows_last_error();
211 else {
212 Name = Filename;
213 return windows_error::success;
214 }
215 }
216
217 static std::string QuoteProgramPathIfNeeded(StringRef Command) {
218 if (Command.find_first_of(' ') == StringRef::npos)
219 return Command;
220 else {
221 std::string ret;
222 ret.reserve(Command.size() + 3);
223 ret.push_back('"');
224 ret.append(Command.begin(), Command.end());
225 ret.push_back('"');
226 return ret;
227 }
228 }
229
230 /// @brief Find program using shell lookup rules.
231 /// @param Program This is either an absolute path, relative path, or simple a
232 /// program name. Look in PATH for any programs that match. If no
233 /// extension is present, try all extensions in PATHEXT.
234 /// @return If ec == errc::success, The absolute path to the program. Otherwise
235 /// the return value is undefined.
236 static std::string FindProgram(const std::string &Program, error_code &ec) {
237 char PathName[MAX_PATH + 1];
238 typedef SmallVector pathext_t;
239 pathext_t pathext;
240 // Check for the program without an extension (in case it already has one).
241 pathext.push_back("");
242 SplitString(std::getenv("PATHEXT"), pathext, ";");
243
244 for (pathext_t::iterator i = pathext.begin(), e = pathext.end(); i != e; ++i){
245 SmallString<5> ext;
246 for (std::size_t ii = 0, e = i->size(); ii != e; ++ii)
247 ext.push_back(::tolower((*i)[ii]));
248 LPCSTR Extension = NULL;
249 if (ext.size() && ext[0] == '.')
250 Extension = ext.c_str();
251 DWORD length = ::SearchPathA(NULL,
252 Program.c_str(),
253 Extension,
254 array_lengthof(PathName),
255 PathName,
256 NULL);
257 if (length == 0)
258 ec = get_windows_last_error();
259 else if (length > array_lengthof(PathName)) {
260 // This may have been the file, return with error.
261 ec = error_code(windows_error::buffer_overflow);
262 break;
263 } else {
264 // We found the path! Return it.
265 ec = windows_error::success;
266 break;
267 }
268 }
269
270 // Make sure PathName is valid.
271 PathName[MAX_PATH] = 0;
272 return PathName;
273 }
274
275 static error_code EnableDebugPrivileges() {
276 HANDLE TokenHandle;
277 BOOL success = ::OpenProcessToken(::GetCurrentProcess(),
278 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
279 &TokenHandle);
280 if (!success)
281 return error_code(::GetLastError(), system_category());
282
283 TokenScopedHandle Token(TokenHandle);
284 TOKEN_PRIVILEGES TokenPrivileges;
285 LUID LocallyUniqueID;
286
287 success = ::LookupPrivilegeValueA(NULL,
288 SE_DEBUG_NAME,
289 &LocallyUniqueID);
290 if (!success)
291 return error_code(::GetLastError(), system_category());
292
293 TokenPrivileges.PrivilegeCount = 1;
294 TokenPrivileges.Privileges[0].Luid = LocallyUniqueID;
295 TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
296
297 success = ::AdjustTokenPrivileges(Token,
298 FALSE,
299 &TokenPrivileges,
300 sizeof(TOKEN_PRIVILEGES),
301 NULL,
302 NULL);
303 // The value of success is basically useless. Either way we are just returning
304 // the value of ::GetLastError().
305 return error_code(::GetLastError(), system_category());
306 }
307
308 static StringRef ExceptionCodeToString(DWORD ExceptionCode) {
309 switch(ExceptionCode) {
310 case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION";
311 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
312 return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
313 case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT";
314 case EXCEPTION_DATATYPE_MISALIGNMENT:
315 return "EXCEPTION_DATATYPE_MISALIGNMENT";
316 case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND";
317 case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
318 case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT";
319 case EXCEPTION_FLT_INVALID_OPERATION:
320 return "EXCEPTION_FLT_INVALID_OPERATION";
321 case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW";
322 case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK";
323 case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW";
324 case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION";
325 case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR";
326 case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";
327 case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW";
328 case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION";
329 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
330 return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
331 case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION";
332 case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP";
333 case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW";
334 default: return "";
335 }
336 }
337
338 int main(int argc, char **argv) {
339 // Print a stack trace if we signal out.
340 sys::PrintStackTraceOnErrorSignal();
341 PrettyStackTraceProgram X(argc, argv);
342 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
343
344 ToolName = argv[0];
345
346 cl::ParseCommandLineOptions(argc, argv, "Dr. Watson Assassin.\n");
347 if (ProgramToRun.size() == 0) {
348 cl::PrintHelpMessage();
349 return -1;
350 }
351
352 if (Timeout > std::numeric_limits::max() / 1000) {
353 errs() << ToolName << ": Timeout value too large, must be less than: "
354 << std::numeric_limits::max() / 1000
355 << '\n';
356 return -1;
357 }
358
359 std::string CommandLine(ProgramToRun);
360
361 error_code ec;
362 ProgramToRun = FindProgram(ProgramToRun, ec);
363 if (ec) {
364 errs() << ToolName << ": Failed to find program: '" << CommandLine
365 << "': " << ec.message() << '\n';
366 return -1;
367 }
368
369 if (TraceExecution)
370 errs() << ToolName << ": Found Program: " << ProgramToRun << '\n';
371
372 for (std::vector::iterator i = Argv.begin(),
373 e = Argv.end();
374 i != e; ++i) {
375 CommandLine.push_back(' ');
376 CommandLine.append(*i);
377 }
378
379 if (TraceExecution)
380 errs() << ToolName << ": Program Image Path: " << ProgramToRun << '\n'
381 << ToolName << ": Command Line: " << CommandLine << '\n';
382
383 STARTUPINFO StartupInfo;
384 PROCESS_INFORMATION ProcessInfo;
385 std::memset(&StartupInfo, 0, sizeof(StartupInfo));
386 StartupInfo.cb = sizeof(StartupInfo);
387 std::memset(&ProcessInfo, 0, sizeof(ProcessInfo));
388
389 // Set error mode to not display any message boxes. The child process inherets
390 // this.
391 ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
392 ::_set_error_mode(_OUT_TO_STDERR);
393
394 BOOL success = ::CreateProcessA(ProgramToRun.c_str(),
395 LPSTR(CommandLine.c_str()),
396 NULL,
397 NULL,
398 FALSE,
399 DEBUG_PROCESS,
400 NULL,
401 NULL,
402 &StartupInfo,
403 &ProcessInfo);
404 if (!success) {
405 errs() << ToolName << ": Failed to run program: '" << ProgramToRun
406 << "': " << error_code(::GetLastError(), system_category()).message()
407 << '\n';
408 return -1;
409 }
410
411 // Make sure ::CloseHandle is called on exit.
412 std::map ProcessIDToHandle;
413
414 DEBUG_EVENT DebugEvent;
415 std::memset(&DebugEvent, 0, sizeof(DebugEvent));
416 DWORD dwContinueStatus = DBG_CONTINUE;
417
418 // Run the program under the debugger until either it exits, or throws an
419 // exception.
420 if (TraceExecution)
421 errs() << ToolName << ": Debugging...\n";
422
423 while(true) {
424 DWORD TimeLeft = INFINITE;
425 if (Timeout > 0) {
426 FILETIME CreationTime, ExitTime, KernelTime, UserTime;
427 ULARGE_INTEGER a, b;
428 success = ::GetProcessTimes(ProcessInfo.hProcess,
429 &CreationTime,
430 &ExitTime,
431 &KernelTime,
432 &UserTime);
433 if (!success) {
434 ec = error_code(::GetLastError(), system_category());
435
436 errs() << ToolName << ": Failed to get process times: "
437 << ec.message() << '\n';
438 return -1;
439 }
440 a.LowPart = KernelTime.dwLowDateTime;
441 a.HighPart = KernelTime.dwHighDateTime;
442 b.LowPart = UserTime.dwLowDateTime;
443 b.HighPart = UserTime.dwHighDateTime;
444 // Convert 100-nanosecond units to miliseconds.
445 uint64_t TotalTimeMiliseconds = (a.QuadPart + b.QuadPart) / 10000;
446 // Handle the case where the process has been running for more than 49
447 // days.
448 if (TotalTimeMiliseconds > std::numeric_limits::max()) {
449 errs() << ToolName << ": Timeout Failed: Process has been running for"
450 "more than 49 days.\n";
451 return -1;
452 }
453
454 // We check with > instead of using Timeleft because if
455 // TotalTimeMiliseconds is greater than Timeout * 1000, TimeLeft would
456 // underflow.
457 if (TotalTimeMiliseconds > (Timeout * 1000)) {
458 errs() << ToolName << ": Process timed out.\n";
459 ::TerminateProcess(ProcessInfo.hProcess, -1);
460 // Otherwise other stuff starts failing...
461 return -1;
462 }
463
464 TimeLeft = (Timeout * 1000) - static_cast(TotalTimeMiliseconds);
465 }
466 success = WaitForDebugEvent(&DebugEvent, TimeLeft);
467
468 if (!success) {
469 ec = error_code(::GetLastError(), system_category());
470
471 if (ec == error_condition(errc::timed_out)) {
472 errs() << ToolName << ": Process timed out.\n";
473 ::TerminateProcess(ProcessInfo.hProcess, -1);
474 // Otherwise other stuff starts failing...
475 return -1;
476 }
477
478 errs() << ToolName << ": Failed to wait for debug event in program: '"
479 << ProgramToRun << "': " << ec.message() << '\n';
480 return -1;
481 }
482
483 switch(DebugEvent.dwDebugEventCode) {
484 case CREATE_PROCESS_DEBUG_EVENT:
485 // Make sure we remove the handle on exit.
486 if (TraceExecution)
487 errs() << ToolName << ": Debug Event: CREATE_PROCESS_DEBUG_EVENT\n";
488 ProcessIDToHandle[DebugEvent.dwProcessId] =
489 DebugEvent.u.CreateProcessInfo.hProcess;
490 ::CloseHandle(DebugEvent.u.CreateProcessInfo.hFile);
491 break;
492 case EXIT_PROCESS_DEBUG_EVENT: {
493 if (TraceExecution)
494 errs() << ToolName << ": Debug Event: EXIT_PROCESS_DEBUG_EVENT\n";
495
496 // If this is the process we origionally created, exit with its exit
497 // code.
498 if (DebugEvent.dwProcessId == ProcessInfo.dwProcessId)
499 return DebugEvent.u.ExitProcess.dwExitCode;
500
501 // Otherwise cleanup any resources we have for it.
502 std::map::iterator ExitingProcess =
503 ProcessIDToHandle.find(DebugEvent.dwProcessId);
504 if (ExitingProcess == ProcessIDToHandle.end()) {
505 errs() << ToolName << ": Got unknown process id!\n";
506 return -1;
507 }
508 ::CloseHandle(ExitingProcess->second);
509 ProcessIDToHandle.erase(ExitingProcess);
510 }
511 break;
512 case CREATE_THREAD_DEBUG_EVENT:
513 ::CloseHandle(DebugEvent.u.CreateThread.hThread);
514 break;
515 case LOAD_DLL_DEBUG_EVENT: {
516 // Cleanup the file handle.
517 FileScopedHandle DLLFile(DebugEvent.u.LoadDll.hFile);
518 std::string DLLName;
519 ec = GetFileNameFromHandle(DLLFile, DLLName);
520 if (ec) {
521 DLLName = " : ";
522 DLLName += ec.message();
523 }
524 if (TraceExecution) {
525 errs() << ToolName << ": Debug Event: LOAD_DLL_DEBUG_EVENT\n";
526 errs().indent(ToolName.size()) << ": DLL Name : " << DLLName << '\n';
527 }
528
529 if (NoUser32 && sys::Path(DLLName).getBasename() == "user32") {
530 // Program is loading user32.dll, in the applications we are testing,
531 // this only happens if an assert has fired. By now the message has
532 // already been printed, so simply close the program.
533 errs() << ToolName << ": user32.dll loaded!\n";
534 errs().indent(ToolName.size())
535 << ": This probably means that assert was called. Closing "
536 "program to prevent message box from poping up.\n";
537 dwContinueStatus = DBG_CONTINUE;
538 ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
539 return -1;
540 }
541 }
542 break;
543 case EXCEPTION_DEBUG_EVENT: {
544 // Close the application if this exception will not be handled by the
545 // child application.
546 if (TraceExecution)
547 errs() << ToolName << ": Debug Event: EXCEPTION_DEBUG_EVENT\n";
548
549 EXCEPTION_DEBUG_INFO &Exception = DebugEvent.u.Exception;
550 if (Exception.dwFirstChance > 0) {
551 if (TraceExecution) {
552 errs().indent(ToolName.size()) << ": Debug Info : ";
553 errs() << "First chance exception at "
554 << Exception.ExceptionRecord.ExceptionAddress
555 << ", exception code: "
556 << ExceptionCodeToString(
557 Exception.ExceptionRecord.ExceptionCode)
558 << " (" << Exception.ExceptionRecord.ExceptionCode << ")\n";
559 }
560 dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
561 } else {
562 errs() << ToolName << ": Unhandled exception in: " << ProgramToRun
563 << "!\n";
564 errs().indent(ToolName.size()) << ": location: ";
565 errs() << Exception.ExceptionRecord.ExceptionAddress
566 << ", exception code: "
567 << ExceptionCodeToString(
568 Exception.ExceptionRecord.ExceptionCode)
569 << " (" << Exception.ExceptionRecord.ExceptionCode
570 << ")\n";
571 dwContinueStatus = DBG_CONTINUE;
572 ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
573 return -1;
574 }
575 }
576 break;
577 default:
578 // Do nothing.
579 if (TraceExecution)
580 errs() << ToolName << ": Debug Event: \n";
581 break;
582 }
583
584 success = ContinueDebugEvent(DebugEvent.dwProcessId,
585 DebugEvent.dwThreadId,
586 dwContinueStatus);
587 if (!success) {
588 ec = error_code(::GetLastError(), system_category());
589 errs() << ToolName << ": Failed to continue debugging program: '"
590 << ProgramToRun << "': " << ec.message() << '\n';
591 return -1;
592 }
593
594 dwContinueStatus = DBG_CONTINUE;
595 }
596
597 assert(0 && "Fell out of debug loop. This shouldn't be possible!");
598 return -1;
599 }
0 //===---------------------- system_error.cpp ------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This was lifted from libc++ and modified for C++03.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Config/config.h"
14 #include "system_error.h"
15 #include
16 #include
17
18 namespace llvm {
19
20 // class error_category
21
22 error_category::error_category() {
23 }
24
25 error_category::~error_category() {
26 }
27
28 error_condition
29 error_category::default_error_condition(int ev) const {
30 return error_condition(ev, *this);
31 }
32
33 bool
34 error_category::equivalent(int code, const error_condition& condition) const {
35 return default_error_condition(code) == condition;
36 }
37
38 bool
39 error_category::equivalent(const error_code& code, int condition) const {
40 return *this == code.category() && code.value() == condition;
41 }
42
43 std::string
44 _do_message::message(int ev) const {
45 return std::string(std::strerror(ev));
46 }
47
48 class _generic_error_category : public _do_message {
49 public:
50 virtual const char* name() const;
51 virtual std::string message(int ev) const;
52 };
53
54 const char*
55 _generic_error_category::name() const {
56 return "generic";
57 }
58
59 std::string
60 _generic_error_category::message(int ev) const {
61 #ifdef ELAST
62 if (ev > ELAST)
63 return std::string("unspecified generic_category error");
64 #endif // ELAST
65 return _do_message::message(ev);
66 }
67
68 const error_category&
69 generic_category() {
70 static _generic_error_category s;
71 return s;
72 }
73
74 class _system_error_category : public _do_message {
75 public:
76 virtual const char* name() const;
77 virtual std::string message(int ev) const;
78 virtual error_condition default_error_condition(int ev) const;
79 };
80
81 const char*
82 _system_error_category::name() const {
83 return "system";
84 }
85
86 // std::string _system_error_category::message(int ev) const {
87 // Is in Platform/system_error.inc
88
89 // error_condition _system_error_category::default_error_condition(int ev) const
90 // Is in Platform/system_error.inc
91
92 const error_category&
93 system_category() {
94 static _system_error_category s;
95 return s;
96 }
97
98 // error_condition
99
100 std::string
101 error_condition::message() const {
102 return _cat_->message(_val_);
103 }
104
105 // error_code
106
107 std::string
108 error_code::message() const {
109 return _cat_->message(_val_);
110 }
111
112 // system_error
113
114 std::string
115 system_error::_init(const error_code& ec, std::string what_arg) {
116 if (ec)
117 {
118 if (!what_arg.empty())
119 what_arg += ": ";
120 what_arg += ec.message();
121 }
122 return what_arg;
123 }
124
125 system_error::system_error(error_code ec, const std::string& what_arg)
126 : runtime_error(_init(ec, what_arg)), _ec_(ec) {
127 }
128
129 system_error::system_error(error_code ec, const char* what_arg)
130 : runtime_error(_init(ec, what_arg)), _ec_(ec) {
131 }
132
133 system_error::system_error(error_code ec)
134 : runtime_error(_init(ec, "")), _ec_(ec) {
135 }
136
137 system_error::system_error(int ev, const error_category& ecat,
138 const std::string& what_arg)
139 : runtime_error(_init(error_code(ev, ecat), what_arg))
140 , _ec_(error_code(ev, ecat)) {
141 }
142
143 system_error::system_error(int ev, const error_category& ecat,
144 const char* what_arg)
145 : runtime_error(_init(error_code(ev, ecat), what_arg))
146 , _ec_(error_code(ev, ecat)) {
147 }
148
149 system_error::system_error(int ev, const error_category& ecat)
150 : runtime_error(_init(error_code(ev, ecat), "")), _ec_(error_code(ev, ecat)) {
151 }
152
153 system_error::~system_error() throw() {
154 }
155
156 void
157 _throw_system_error(int ev, const char* what_arg) {
158 throw system_error(error_code(ev, system_category()), what_arg);
159 }
160
161 } // end namespace llvm
162
163 #ifdef LLVM_ON_WIN32
164 #include
165 #include
166
167 namespace llvm {
168
169 std::string
170 _system_error_category::message(int ev) const {
171 LPVOID lpMsgBuf = 0;
172 DWORD retval = ::FormatMessageA(
173 FORMAT_MESSAGE_ALLOCATE_BUFFER |
174 FORMAT_MESSAGE_FROM_SYSTEM |
175 FORMAT_MESSAGE_IGNORE_INSERTS,
176 NULL,
177 ev,
178 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
179 (LPSTR) &lpMsgBuf,
180 0,
181 NULL);
182 if (retval == 0) {
183 ::LocalFree(lpMsgBuf);
184 return std::string("Unknown error");
185 }
186
187 std::string str( static_cast(lpMsgBuf) );
188 ::LocalFree(lpMsgBuf);
189
190 while (str.size()
191 && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r'))
192 str.erase( str.size()-1 );
193 if (str.size() && str[str.size()-1] == '.')
194 str.erase( str.size()-1 );
195 return str;
196 }
197
198 error_condition
199 _system_error_category::default_error_condition(int ev) const {
200 switch (ev)
201 {
202 case 0: return make_error_condition(errc::success);
203 // Windows system -> posix_errno decode table ---------------------------//
204 // see WinError.h comments for descriptions of errors
205 case ERROR_ACCESS_DENIED: return make_error_condition(errc::permission_denied);
206 case ERROR_ALREADY_EXISTS: return make_error_condition(errc::file_exists);
207 case ERROR_BAD_UNIT: return make_error_condition(errc::no_such_device);
208 case ERROR_BUFFER_OVERFLOW: return make_error_condition(errc::filename_too_long);
209 case ERROR_BUSY: return make_error_condition(errc::device_or_resource_busy);
210 case ERROR_BUSY_DRIVE: return make_error_condition(errc::device_or_resource_busy);
211 case ERROR_CANNOT_MAKE: return make_error_condition(errc::permission_denied);
212 case ERROR_CANTOPEN: return make_error_condition(errc::io_error);
213 case ERROR_CANTREAD: return make_error_condition(errc::io_error);
214 case ERROR_CANTWRITE: return make_error_condition(errc::io_error);
215 case ERROR_CURRENT_DIRECTORY: return make_error_condition(errc::permission_denied);
216 case ERROR_DEV_NOT_EXIST: return make_error_condition(errc::no_such_device);
217 case ERROR_DEVICE_IN_USE: return make_error_condition(errc::device_or_resource_busy);
218 case ERROR_DIR_NOT_EMPTY: return make_error_condition(errc::directory_not_empty);
219 case ERROR_DIRECTORY: return make_error_condition(errc::invalid_argument);
220 case ERROR_DISK_FULL: return make_error_condition(errc::no_space_on_device);
221 case ERROR_FILE_EXISTS: return make_error_condition(errc::file_exists);
222 case ERROR_FILE_NOT_FOUND: return make_error_condition(errc::no_such_file_or_directory);
223 case ERROR_HANDLE_DISK_FULL: return make_error_condition(errc::no_space_on_device);
224 case ERROR_INVALID_ACCESS: return make_error_condition(errc::permission_denied);
225 case ERROR_INVALID_DRIVE: return make_error_condition(errc::no_such_device);
226 case ERROR_INVALID_FUNCTION: return make_error_condition(errc::function_not_supported);
227 case ERROR_INVALID_HANDLE: return make_error_condition(errc::invalid_argument);
228 case ERROR_INVALID_NAME: return make_error_condition(errc::invalid_argument);
229 case ERROR_LOCK_VIOLATION: return make_error_condition(errc::no_lock_available);
230 case ERROR_LOCKED: return make_error_condition(errc::no_lock_available);
231 case ERROR_NEGATIVE_SEEK: return make_error_condition(errc::invalid_argument);
232 case ERROR_NOACCESS: return make_error_condition(errc::permission_denied);
233 case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition(errc::not_enough_memory);
234 case ERROR_NOT_READY: return make_error_condition(errc::resource_unavailable_try_again);
235 case ERROR_NOT_SAME_DEVICE: return make_error_condition(errc::cross_device_link);
236 case ERROR_OPEN_FAILED: return make_error_condition(errc::io_error);
237 case ERROR_OPEN_FILES: return make_error_condition(errc::device_or_resource_busy);
238 case ERROR_OPERATION_ABORTED: return make_error_condition(errc::operation_canceled);
239 case ERROR_OUTOFMEMORY: return make_error_condition(errc::not_enough_memory);
240 case ERROR_PATH_NOT_FOUND: return make_error_condition(errc::no_such_file_or_directory);
241 case ERROR_READ_FAULT: return make_error_condition(errc::io_error);
242 case ERROR_RETRY: return make_error_condition(errc::resource_unavailable_try_again);
243 case ERROR_SEEK: return make_error_condition(errc::io_error);
244 case ERROR_SHARING_VIOLATION: return make_error_condition(errc::permission_denied);
245 case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition(errc::too_many_files_open);
246 case ERROR_WRITE_FAULT: return make_error_condition(errc::io_error);
247 case ERROR_WRITE_PROTECT: return make_error_condition(errc::permission_denied);
248 case ERROR_SEM_TIMEOUT: return make_error_condition(errc::timed_out);
249 case WSAEACCES: return make_error_condition(errc::permission_denied);
250 case WSAEADDRINUSE: return make_error_condition(errc::address_in_use);
251 case WSAEADDRNOTAVAIL: return make_error_condition(errc::address_not_available);
252 case WSAEAFNOSUPPORT: return make_error_condition(errc::address_family_not_supported);
253 case WSAEALREADY: return make_error_condition(errc::connection_already_in_progress);
254 case WSAEBADF: return make_error_condition(errc::bad_file_descriptor);
255 case WSAECONNABORTED: return make_error_condition(errc::connection_aborted);
256 case WSAECONNREFUSED: return make_error_condition(errc::connection_refused);
257 case WSAECONNRESET: return make_error_condition(errc::connection_reset);
258 case WSAEDESTADDRREQ: return make_error_condition(errc::destination_address_required);
259 case WSAEFAULT: return make_error_condition(errc::bad_address);
260 case WSAEHOSTUNREACH: return make_error_condition(errc::host_unreachable);
261 case WSAEINPROGRESS: return make_error_condition(errc::operation_in_progress);
262 case WSAEINTR: return make_error_condition(errc::interrupted);
263 case WSAEINVAL: return make_error_condition(errc::invalid_argument);
264 case WSAEISCONN: return make_error_condition(errc::already_connected);
265 case WSAEMFILE: return make_error_condition(errc::too_many_files_open);
266 case WSAEMSGSIZE: return make_error_condition(errc::message_size);
267 case WSAENAMETOOLONG: return make_error_condition(errc::filename_too_long);
268 case WSAENETDOWN: return make_error_condition(errc::network_down);
269 case WSAENETRESET: return make_error_condition(errc::network_reset);
270 case WSAENETUNREACH: return make_error_condition(errc::network_unreachable);
271 case WSAENOBUFS: return make_error_condition(errc::no_buffer_space);
272 case WSAENOPROTOOPT: return make_error_condition(errc::no_protocol_option);
273 case WSAENOTCONN: return make_error_condition(errc::not_connected);
274 case WSAENOTSOCK: return make_error_condition(errc::not_a_socket);
275 case WSAEOPNOTSUPP: return make_error_condition(errc::operation_not_supported);
276 case WSAEPROTONOSUPPORT: return make_error_condition(errc::protocol_not_supported);
277 case WSAEPROTOTYPE: return make_error_condition(errc::wrong_protocol_type);
278 case WSAETIMEDOUT: return make_error_condition(errc::timed_out);
279 case WSAEWOULDBLOCK: return make_error_condition(errc::operation_would_block);
280 default: return error_condition(ev, system_category());
281 }
282 }
283
284 } // end namespace llvm
285
286 #endif // LLVM_ON_WIN32
0 //===---------------------------- system_error ----------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This was lifted from libc++ and modified for C++03.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_SYSTEM_SYSTEM_ERROR_H
14 #define LLVM_SYSTEM_SYSTEM_ERROR_H
15
16 /*
17 system_error synopsis
18
19 namespace std
20 {
21
22 class error_category
23 {
24 public:
25 virtual ~error_category();
26
27 error_category(const error_category&) = delete;
28 error_category& operator=(const error_category&) = delete;
29
30 virtual const char* name() const = 0;
31 virtual error_condition default_error_condition(int ev) const;
32 virtual bool equivalent(int code, const error_condition& condition) const;
33 virtual bool equivalent(const error_code& code, int condition) const;
34 virtual std::string message(int ev) const = 0;
35
36 bool operator==(const error_category& rhs) const;
37 bool operator!=(const error_category& rhs) const;
38 bool operator<(const error_category& rhs) const;
39 };
40
41 const error_category& generic_category();
42 const error_category& system_category();
43
44 template struct is_error_code_enum
45 : public false_type {};
46
47 template struct is_error_condition_enum
48 : public false_type {};
49
50 class error_code
51 {
52 public:
53 // constructors:
54 error_code();
55 error_code(int val, const error_category& cat);
56 template
57 error_code(ErrorCodeEnum e);
58
59 // modifiers:
60 void assign(int val, const error_category& cat);
61 template
62 error_code& operator=(ErrorCodeEnum e);
63 void clear();
64
65 // observers:
66 int value() const;
67 const error_category& category() const;
68 error_condition default_error_condition() const;
69 std::string message() const;
70 explicit operator bool() const;
71 };
72
73 // non-member functions:
74 bool operator<(const error_code& lhs, const error_code& rhs);
75 template
76 basic_ostream&
77 operator<<(basic_ostream& os, const error_code& ec);
78
79 class error_condition
80 {
81 public:
82 // constructors:
83 error_condition();
84 error_condition(int val, const error_category& cat);
85 template
86 error_condition(ErrorConditionEnum e);
87
88 // modifiers:
89 void assign(int val, const error_category& cat);
90 template
91 error_condition& operator=(ErrorConditionEnum e);
92 void clear();
93
94 // observers:
95 int value() const;
96 const error_category& category() const;
97 std::string message() const;
98 explicit operator bool() const;
99 };
100
101 bool operator<(const error_condition& lhs, const error_condition& rhs);
102
103 class system_error
104 : public runtime_error
105 {
106 public:
107 system_error(error_code ec, const std::string& what_arg);
108 system_error(error_code ec, const char* what_arg);
109 system_error(error_code ec);
110 system_error(int ev, const error_category& ecat, const std::string& what_arg);
111 system_error(int ev, const error_category& ecat, const char* what_arg);
112 system_error(int ev, const error_category& ecat);
113
114 const error_code& code() const throw();
115 const char* what() const throw();
116 };
117
118 enum class errc
119 {
120 address_family_not_supported, // EAFNOSUPPORT
121 address_in_use, // EADDRINUSE
122 address_not_available, // EADDRNOTAVAIL
123 already_connected, // EISCONN
124 argument_list_too_long, // E2BIG
125 argument_out_of_domain, // EDOM
126 bad_address, // EFAULT
127 bad_file_descriptor, // EBADF
128 bad_message, // EBADMSG
129 broken_pipe, // EPIPE
130 connection_aborted, // ECONNABORTED
131 connection_already_in_progress, // EALREADY
132 connection_refused, // ECONNREFUSED
133 connection_reset, // ECONNRESET
134 cross_device_link, // EXDEV
135 destination_address_required, // EDESTADDRREQ
136 device_or_resource_busy, // EBUSY
137 directory_not_empty, // ENOTEMPTY
138 executable_format_error, // ENOEXEC
139 file_exists, // EEXIST
140 file_too_large, // EFBIG
141 filename_too_long, // ENAMETOOLONG
142 function_not_supported, // ENOSYS
143 host_unreachable, // EHOSTUNREACH
144 identifier_removed, // EIDRM
145 illegal_byte_sequence, // EILSEQ
146 inappropriate_io_control_operation, // ENOTTY
147 interrupted, // EINTR
148 invalid_argument, // EINVAL
149 invalid_seek, // ESPIPE
150 io_error, // EIO
151 is_a_directory, // EISDIR
152 message_size, // EMSGSIZE
153 network_down, // ENETDOWN
154 network_reset, // ENETRESET
155 network_unreachable, // ENETUNREACH
156 no_buffer_space, // ENOBUFS
157 no_child_process, // ECHILD
158 no_link, // ENOLINK
159 no_lock_available, // ENOLCK
160 no_message_available, // ENODATA
161 no_message, // ENOMSG
162 no_protocol_option, // ENOPROTOOPT
163 no_space_on_device, // ENOSPC
164 no_stream_resources, // ENOSR
165 no_such_device_or_address, // ENXIO
166 no_such_device, // ENODEV
167 no_such_file_or_directory, // ENOENT
168 no_such_process, // ESRCH
169 not_a_directory, // ENOTDIR
170 not_a_socket, // ENOTSOCK
171 not_a_stream, // ENOSTR
172 not_connected, // ENOTCONN
173 not_enough_memory, // ENOMEM
174 not_supported, // ENOTSUP
175 operation_canceled, // ECANCELED
176 operation_in_progress, // EINPROGRESS
177 operation_not_permitted, // EPERM
178 operation_not_supported, // EOPNOTSUPP
179 operation_would_block, // EWOULDBLOCK
180 owner_dead, // EOWNERDEAD
181 permission_denied, // EACCES
182 protocol_error, // EPROTO
183 protocol_not_supported, // EPROTONOSUPPORT
184 read_only_file_system, // EROFS
185 resource_deadlock_would_occur, // EDEADLK
186 resource_unavailable_try_again, // EAGAIN
187 result_out_of_range, // ERANGE
188 state_not_recoverable, // ENOTRECOVERABLE
189 stream_timeout, // ETIME
190 text_file_busy, // ETXTBSY
191 timed_out, // ETIMEDOUT
192 too_many_files_open_in_system, // ENFILE
193 too_many_files_open, // EMFILE
194 too_many_links, // EMLINK
195 too_many_symbolic_link_levels, // ELOOP
196 value_too_large, // EOVERFLOW
197 wrong_protocol_type // EPROTOTYPE
198 };
199
200 template <> struct is_error_condition_enum : true_type { }
201
202 error_code make_error_code(errc e);
203 error_condition make_error_condition(errc e);
204
205 // Comparison operators:
206 bool operator==(const error_code& lhs, const error_code& rhs);
207 bool operator==(const error_code& lhs, const error_condition& rhs);
208 bool operator==(const error_condition& lhs, const error_code& rhs);
209 bool operator==(const error_condition& lhs, const error_condition& rhs);
210 bool operator!=(const error_code& lhs, const error_code& rhs);
211 bool operator!=(const error_code& lhs, const error_condition& rhs);
212 bool operator!=(const error_condition& lhs, const error_code& rhs);
213 bool operator!=(const error_condition& lhs, const error_condition& rhs);
214
215 template <> struct hash;
216
217 } // std
218
219 */
220
221 #include "llvm/Config/config.h"
222 #include "llvm/Support/type_traits.h"
223 #include
224 #include
225
226 namespace llvm {
227
228 template
229 struct integral_constant {
230 typedef T value_type;
231 static const value_type value = v;
232 typedef integral_constant type;
233 operator value_type() { return value; }
234 };
235
236 typedef integral_constant true_type;
237 typedef integral_constant false_type;
238
239 // is_error_code_enum
240
241 template struct is_error_code_enum : public false_type {};
242
243 // is_error_condition_enum
244
245 template struct is_error_condition_enum : public false_type {};
246
247 // Some error codes are not present on all platforms, so we provide equivalents
248 // for them:
249
250 //enum class errc
251 struct errc {
252 enum _ {
253 success = 0,
254 address_family_not_supported = EAFNOSUPPORT,
255 address_in_use = EADDRINUSE,
256 address_not_available = EADDRNOTAVAIL,
257 already_connected = EISCONN,
258 argument_list_too_long = E2BIG,
259 argument_out_of_domain = EDOM,
260 bad_address = EFAULT,
261 bad_file_descriptor = EBADF,
262 bad_message = EBADMSG,
263 broken_pipe = EPIPE,
264 connection_aborted = ECONNABORTED,
265 connection_already_in_progress = EALREADY,
266 connection_refused = ECONNREFUSED,
267 connection_reset = ECONNRESET,
268 cross_device_link = EXDEV,
269 destination_address_required = EDESTADDRREQ,
270 device_or_resource_busy = EBUSY,
271 directory_not_empty = ENOTEMPTY,
272 executable_format_error = ENOEXEC,
273 file_exists = EEXIST,
274 file_too_large = EFBIG,
275 filename_too_long = ENAMETOOLONG,
276 function_not_supported = ENOSYS,
277 host_unreachable = EHOSTUNREACH,
278 identifier_removed = EIDRM,
279 illegal_byte_sequence = EILSEQ,
280 inappropriate_io_control_operation = ENOTTY,
281 interrupted = EINTR,
282 invalid_argument = EINVAL,
283 invalid_seek = ESPIPE,
284 io_error = EIO,
285 is_a_directory = EISDIR,
286 message_size = EMSGSIZE,
287 network_down = ENETDOWN,
288 network_reset = ENETRESET,
289 network_unreachable = ENETUNREACH,
290 no_buffer_space = ENOBUFS,
291 no_child_process = ECHILD,
292 no_link = ENOLINK,
293 no_lock_available = ENOLCK,
294 #ifdef ENODATA
295 no_message_available = ENODATA,
296 #else
297 no_message_available = ENOMSG,
298 #endif
299 no_message = ENOMSG,
300 no_protocol_option = ENOPROTOOPT,
301 no_space_on_device = ENOSPC,
302 #ifdef ENOSR
303 no_stream_resources = ENOSR,
304 #else
305 no_stream_resources = ENOMEM,
306 #endif
307 no_such_device_or_address = ENXIO,
308 no_such_device = ENODEV,
309 no_such_file_or_directory = ENOENT,
310 no_such_process = ESRCH,
311 not_a_directory = ENOTDIR,
312 not_a_socket = ENOTSOCK,
313 #ifdef ENOSTR
314 not_a_stream = ENOSTR,
315 #else
316 not_a_stream = EINVAL,
317 #endif
318 not_connected = ENOTCONN,
319 not_enough_memory = ENOMEM,
320 not_supported = ENOTSUP,
321 operation_canceled = ECANCELED,
322 operation_in_progress = EINPROGRESS,
323 operation_not_permitted = EPERM,
324 operation_not_supported = EOPNOTSUPP,
325 operation_would_block = EWOULDBLOCK,
326 owner_dead = EOWNERDEAD,
327 permission_denied = EACCES,
328 protocol_error = EPROTO,
329 protocol_not_supported = EPROTONOSUPPORT,
330 read_only_file_system = EROFS,
331 resource_deadlock_would_occur = EDEADLK,
332 resource_unavailable_try_again = EAGAIN,
333 result_out_of_range = ERANGE,
334 state_not_recoverable = ENOTRECOVERABLE,
335 #ifdef ETIME
336 stream_timeout = ETIME,
337 #else
338 stream_timeout = ETIMEDOUT,
339 #endif
340 text_file_busy = ETXTBSY,
341 timed_out = ETIMEDOUT,
342 too_many_files_open_in_system = ENFILE,
343 too_many_files_open = EMFILE,
344 too_many_links = EMLINK,
345 too_many_symbolic_link_levels = ELOOP,
346 value_too_large = EOVERFLOW,
347 wrong_protocol_type = EPROTOTYPE
348 };
349
350 _ v_;
351
352 errc(_ v) : v_(v) {}
353 operator int() const {return v_;}
354 };
355
356 template <> struct is_error_condition_enum : true_type { };
357
358 template <> struct is_error_condition_enum : true_type { };
359
360 class error_condition;
361 class error_code;
362
363 // class error_category
364
365 class _do_message;
366
367 class error_category
368 {
369 public:
370 virtual ~error_category();
371
372 private:
373 error_category();
374 error_category(const error_category&);// = delete;
375 error_category& operator=(const error_category&);// = delete;
376
377 public:
378 virtual const char* name() const = 0;
379 virtual error_condition default_error_condition(int _ev) const;
380 virtual bool equivalent(int _code, const error_condition& _condition) const;
381 virtual bool equivalent(const error_code& _code, int _condition) const;
382 virtual std::string message(int _ev) const = 0;
383
384 bool operator==(const error_category& _rhs) const {return this == &_rhs;}
385
386 bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);}
387
388 bool operator< (const error_category& _rhs) const {return this < &_rhs;}
389
390 friend class _do_message;
391 };
392
393 class _do_message : public error_category
394 {
395 public:
396 virtual std::string message(int ev) const;
397 };
398
399 const error_category& generic_category();
400 const error_category& system_category();
401
402 class error_condition
403 {
404 int _val_;
405 const error_category* _cat_;
406 public:
407 error_condition() : _val_(0), _cat_(&generic_category()) {}
408
409 error_condition(int _val, const error_category& _cat)
410 : _val_(_val), _cat_(&_cat) {}
411
412 template
413 error_condition(E _e, typename enable_if_c<
414 is_error_condition_enum::value
415 >::type* = 0)
416 {*this = make_error_condition(_e);}
417
418 void assign(int _val, const error_category& _cat) {
419 _val_ = _val;
420 _cat_ = &_cat;
421 }
422
423 template
424 typename enable_if_c
425 <
426 is_error_condition_enum::value,
427 error_condition&
428 >::type
429 operator=(E _e)
430 {*this = make_error_condition(_e); return *this;}
431
432 void clear() {
433 _val_ = 0;
434 _cat_ = &generic_category();
435 }
436
437 int value() const {return _val_;}
438
439 const error_category& category() const {return *_cat_;}
440 std::string message() const;
441
442 // explicit
443 operator bool() const {return _val_ != 0;}
444 };
445
446 inline error_condition make_error_condition(errc _e) {
447 return error_condition(static_cast(_e), generic_category());
448 }
449
450 inline bool operator<(const error_condition& _x, const error_condition& _y) {
451 return _x.category() < _y.category()
452 || _x.category() == _y.category() && _x.value() < _y.value();
453 }
454
455 // error_code
456
457 class error_code {
458 int _val_;
459 const error_category* _cat_;
460 public:
461 error_code() : _val_(0), _cat_(&system_category()) {}
462
463 error_code(int _val, const error_category& _cat)
464 : _val_(_val), _cat_(&_cat) {}
465
466 template
467 error_code(E _e, typename enable_if_c<
468 is_error_code_enum::value
469 >::type* = 0) {
470 *this = make_error_code(_e);
471 }
472
473 void assign(int _val, const error_category& _cat) {
474 _val_ = _val;
475 _cat_ = &_cat;
476 }
477
478 template
479 typename enable_if_c
480 <
481 is_error_code_enum::value,
482 error_code&
483 >::type
484 operator=(E _e)
485 {*this = make_error_code(_e); return *this;}
486
487 void clear() {
488 _val_ = 0;
489 _cat_ = &system_category();
490 }
491
492 int value() const {return _val_;}
493
494 const error_category& category() const {return *_cat_;}
495
496 error_condition default_error_condition() const
497 {return _cat_->default_error_condition(_val_);}
498
499 std::string message() const;
500
501 // explicit
502 operator bool() const {return _val_ != 0;}
503 };
504
505 inline error_code make_error_code(errc _e) {
506 return error_code(static_cast(_e), generic_category());
507 }
508
509 inline bool operator<(const error_code& _x, const error_code& _y) {
510 return _x.category() < _y.category()
511 || _x.category() == _y.category() && _x.value() < _y.value();
512 }
513
514 inline bool operator==(const error_code& _x, const error_code& _y) {
515 return _x.category() == _y.category() && _x.value() == _y.value();
516 }
517
518 inline bool operator==(const error_code& _x, const error_condition& _y) {
519 return _x.category().equivalent(_x.value(), _y)
520 || _y.category().equivalent(_x, _y.value());
521 }
522
523 inline bool operator==(const error_condition& _x, const error_code& _y) {
524 return _y == _x;
525 }
526
527 inline bool operator==(const error_condition& _x, const error_condition& _y) {
528 return _x.category() == _y.category() && _x.value() == _y.value();
529 }
530
531 inline bool operator!=(const error_code& _x, const error_code& _y) {
532 return !(_x == _y);
533 }
534
535 inline bool operator!=(const error_code& _x, const error_condition& _y) {
536 return !(_x == _y);
537 }
538
539 inline bool operator!=(const error_condition& _x, const error_code& _y) {
540 return !(_x == _y);
541 }
542
543 inline bool operator!=(const error_condition& _x, const error_condition& _y) {
544 return !(_x == _y);
545 }
546
547 // system_error
548
549 class system_error : public std::runtime_error {
550 error_code _ec_;
551 public:
552 system_error(error_code _ec, const std::string& _what_arg);
553 system_error(error_code _ec, const char* _what_arg);
554 system_error(error_code _ec);
555 system_error(int _ev, const error_category& _ecat,
556 const std::string& _what_arg);
557 system_error(int _ev, const error_category& _ecat, const char* _what_arg);
558 system_error(int _ev, const error_category& _ecat);
559 ~system_error() throw();
560
561 const error_code& code() const throw() {return _ec_;}
562
563 private:
564 static std::string _init(const error_code&, std::string);
565 };
566
567 void _throw_system_error(int ev, const char* what_arg);
568
569 } // end namespace llvm
570
571 #ifdef LLVM_ON_WIN32
572 #include
573 #include
574
575 namespace llvm {
576
577 // To construct an error_code after a API error:
578 //
579 // error_code( ::GetLastError(), system_category() )
580 struct windows_error {
581 enum _ {
582 success = 0,
583 // These names and values are based on Windows winerror.h
584 invalid_function = ERROR_INVALID_FUNCTION,
585 file_not_found = ERROR_FILE_NOT_FOUND,
586 path_not_found = ERROR_PATH_NOT_FOUND,
587 too_many_open_files = ERROR_TOO_MANY_OPEN_FILES,
588 access_denied = ERROR_ACCESS_DENIED,
589 invalid_handle = ERROR_INVALID_HANDLE,
590 arena_trashed = ERROR_ARENA_TRASHED,
591 not_enough_memory = ERROR_NOT_ENOUGH_MEMORY,
592 invalid_block = ERROR_INVALID_BLOCK,
593 bad_environment = ERROR_BAD_ENVIRONMENT,
594 bad_format = ERROR_BAD_FORMAT,
595 invalid_access = ERROR_INVALID_ACCESS,
596 outofmemory = ERROR_OUTOFMEMORY,
597 invalid_drive = ERROR_INVALID_DRIVE,
598 current_directory = ERROR_CURRENT_DIRECTORY,
599 not_same_device = ERROR_NOT_SAME_DEVICE,
600 no_more_files = ERROR_NO_MORE_FILES,
601 write_protect = ERROR_WRITE_PROTECT,
602 bad_unit = ERROR_BAD_UNIT,
603 not_ready = ERROR_NOT_READY,
604 bad_command = ERROR_BAD_COMMAND,
605 crc = ERROR_CRC,
606 bad_length = ERROR_BAD_LENGTH,
607 seek = ERROR_SEEK,
608 not_dos_disk = ERROR_NOT_DOS_DISK,
609 sector_not_found = ERROR_SECTOR_NOT_FOUND,
610 out_of_paper = ERROR_OUT_OF_PAPER,
611 write_fault = ERROR_WRITE_FAULT,
612 read_fault = ERROR_READ_FAULT,
613 gen_failure = ERROR_GEN_FAILURE,
614 sharing_violation = ERROR_SHARING_VIOLATION,
615 lock_violation = ERROR_LOCK_VIOLATION,
616 wrong_disk = ERROR_WRONG_DISK,
617 sharing_buffer_exceeded = ERROR_SHARING_BUFFER_EXCEEDED,
618 handle_eof = ERROR_HANDLE_EOF,
619 handle_disk_full= ERROR_HANDLE_DISK_FULL,
620 rem_not_list = ERROR_REM_NOT_LIST,
621 dup_name = ERROR_DUP_NAME,
622 bad_net_path = ERROR_BAD_NETPATH,
623 network_busy = ERROR_NETWORK_BUSY,
624 // ...
625 file_exists = ERROR_FILE_EXISTS,
626 cannot_make = ERROR_CANNOT_MAKE,
627 // ...
628 broken_pipe = ERROR_BROKEN_PIPE,
629 open_failed = ERROR_OPEN_FAILED,
630 buffer_overflow = ERROR_BUFFER_OVERFLOW,
631 disk_full= ERROR_DISK_FULL,
632 // ...
633 lock_failed = ERROR_LOCK_FAILED,
634 busy = ERROR_BUSY,
635 cancel_violation = ERROR_CANCEL_VIOLATION,
636 already_exists = ERROR_ALREADY_EXISTS
637 // ...
638
639 // TODO: add more Windows errors
640 };
641 _ v_;
642
643 windows_error(_ v) : v_(v) {}
644 explicit windows_error(DWORD v) : v_(_(v)) {}
645 operator int() const {return v_;}
646 };
647
648
649 template <> struct is_error_code_enum : true_type { };
650
651 template <> struct is_error_code_enum : true_type { };
652
653 inline error_code make_error_code(windows_error e) {
654 return error_code(static_cast(e), system_category());
655 }
656
657 } // end namespace llvm
658
659 #endif // LLVM_ON_WINDOWS
660
661 #endif