1 | #include <iostream> |
2 | #include <stdexcept> |
3 | |
4 | void erringFunc() { throw std::runtime_error("Hello" ); } |
5 | |
6 | void libCallA() { erringFunc(); } |
7 | |
8 | void libCallB() { throw std::runtime_error("World" ); } |
9 | |
10 | void handleEventA() { |
11 | try { |
12 | libCallA(); |
13 | } catch (std::runtime_error &E) { |
14 | std::cout << "handleEventA: unhandled error " << E.what() << "\n" ; |
15 | throw; |
16 | } |
17 | } |
18 | |
19 | void handleEventB() { |
20 | try { |
21 | libCallB(); |
22 | } catch (std::runtime_error &E) { |
23 | std::cout << "handleEventB: handle error " << E.what() << "\n" ; |
24 | } |
25 | } |
26 | |
27 | class EventGen { |
28 | unsigned RemainingEvents = 5; |
29 | |
30 | public: |
31 | int generateEvent() { |
32 | if (RemainingEvents > 0) { |
33 | --RemainingEvents; |
34 | return (RemainingEvents % 3) + 1; |
35 | } |
36 | return 0; |
37 | } |
38 | }; |
39 | |
40 | class TerminateException : public std::runtime_error { |
41 | public: |
42 | TerminateException() : std::runtime_error("Time to stop!" ) {} |
43 | }; |
44 | |
45 | void runEventLoop(EventGen &EG) { |
46 | while (true) { |
47 | try { |
48 | int Ev = EG.generateEvent(); |
49 | switch (Ev) { |
50 | case 0: |
51 | throw TerminateException(); |
52 | case 1: |
53 | handleEventA(); |
54 | break; |
55 | case 2: |
56 | handleEventB(); |
57 | break; |
58 | } |
59 | } catch (TerminateException &E) { |
60 | std::cout << "Terminated?\n" ; |
61 | throw; |
62 | } catch (std::runtime_error &E) { |
63 | std::cout << "Unhandled error: " << E.what() << "\n" ; |
64 | } |
65 | } |
66 | } |
67 | |
68 | struct CleanUp { |
69 | ~CleanUp() { std::cout << "Cleanup\n" ; } |
70 | }; |
71 | |
72 | int main() { |
73 | EventGen EG; |
74 | try { |
75 | CleanUp CU; |
76 | runEventLoop(EG); |
77 | } catch (TerminateException &E) { |
78 | std::cout << "Terminated!\n" ; |
79 | } |
80 | return 0; |
81 | } |
82 | |
83 | /* |
84 | REQUIRES: system-linux |
85 | |
86 | RUN: %clang++ %cflags %s -o %t.exe -Wl,-q |
87 | RUN: llvm-bolt %t.exe --split-functions --split-strategy=randomN \ |
88 | RUN: --split-all-cold --split-eh --bolt-seed=7 -o %t.bolt |
89 | RUN: %t.bolt | FileCheck %s |
90 | |
91 | CHECK: handleEventB: handle error World |
92 | CHECK-NEXT: handleEventA: unhandled error Hello |
93 | CHECK-NEXT: Unhandled error: Hello |
94 | CHECK-NEXT: handleEventB: handle error World |
95 | CHECK-NEXT: handleEventA: unhandled error Hello |
96 | CHECK-NEXT: Unhandled error: Hello |
97 | CHECK-NEXT: Terminated? |
98 | CHECK-NEXT: Cleanup |
99 | CHECK-NEXT: Terminated! |
100 | */ |
101 | |