1 // Make sure we can throw exceptions from work items executed via
2 // BindIoCompletionCallback.
3 //
4 // Clang doesn't support exceptions on Windows yet, so for the time being we
5 // build this program in two parts: the code with exceptions is built with CL,
6 // the rest is built with Clang.  This represents the typical scenario when we
7 // build a large project using "clang-cl -fallback -fsanitize=address".
8 //
9 // RUN: cl -c %s -Fo%t.obj
10 // RUN: %clangxx_asan -o %t.exe %s %t.obj
11 // RUN: %run %t.exe 2>&1 | FileCheck %s
12 
13 #include <windows.h>
14 #include <stdio.h>
15 
16 void ThrowAndCatch();
17 
18 #if !defined(__clang__)
19 __declspec(noinline)
Throw()20 void Throw() {
21   fprintf(stderr, "Throw\n");
22 // CHECK: Throw
23   throw 1;
24 }
25 
ThrowAndCatch()26 void ThrowAndCatch() {
27   int local;
28   try {
29     Throw();
30   } catch(...) {
31     fprintf(stderr, "Catch\n");
32 // CHECK: Catch
33   }
34 }
35 #else
36 
37 char buffer[65536];
38 HANDLE done;
39 OVERLAPPED ov;
40 
completion_callback(DWORD error,DWORD bytesRead,LPOVERLAPPED pov)41 void CALLBACK completion_callback(DWORD error, DWORD bytesRead,
42                                   LPOVERLAPPED pov) {
43   ThrowAndCatch();
44   SetEvent(done);
45 }
46 
main(int argc,char ** argv)47 int main(int argc, char **argv) {
48   done = CreateEvent(0, false, false, "job is done");
49   if (!done)
50     return 1;
51   HANDLE file = CreateFile(
52       argv[0], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
53       OPEN_EXISTING,
54       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
55       NULL);
56   if (!file)
57     return 2;
58   if (!BindIoCompletionCallback(file, completion_callback, 0))
59     return 3;
60 
61   if (!ReadFile(file, buffer, sizeof(buffer), NULL, &ov) &&
62       GetLastError() != ERROR_IO_PENDING)
63     return 4;
64 
65   if (WAIT_OBJECT_0 != WaitForSingleObject(done, INFINITE))
66     return 5;
67   fprintf(stderr, "Done!\n");
68 // CHECK: Done!
69 }
70 #endif
71