xref: /llvm-project/clang/test/CodeGen/windows-seh-EHa-TryInFinally.cpp (revision c5de4dd1eab00df76c1a68c5f397304ceacb71f2)
1 // RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck %s
2 
3 // CHECK-LABEL: @main()
4 // CHECK: invoke void @llvm.seh.try.begin()
5 // CHECK: invoke void @llvm.seh.try.begin()
6 // CHECK: %[[src:[0-9-]+]] = load volatile i32, ptr %i
7 // CHECK-NEXT: i32 noundef %[[src]]
8 // CHECK: invoke void @llvm.seh.try.end()
9 // CHECK: invoke void @llvm.seh.try.end()
10 
11 // CHECK: define internal void @"?fin$0@0@main@@"(i8 noundef %abnormal_termination
12 // CHECK: invoke void @llvm.seh.try.begin()
13 // CHECK: invoke void @llvm.seh.try.end()
14 
15 // *****************************************************************************
16 // Abstract:     Test __Try in __finally under SEH -EHa option
17 void printf(...);
18 int volatile *NullPtr = 0;
main()19 int main() {
20   for (int i = 0; i < 3; i++) {
21     printf(" --- Test _Try in _finally --- i = %d \n", i);
22     __try {
23       __try {
24         printf("  In outer _try i = %d \n", i);
25         if (i == 0)
26           *NullPtr = 0;
27       } __finally {
28         __try {
29           printf("  In outer _finally i = %d \n", i);
30           if (i == 1)
31             *NullPtr = 0;
32         } __finally {
33           printf("  In Inner _finally i = %d \n", i);
34           if (i == 2)
35             *NullPtr = 0;
36         }
37       }
38     } __except (1) {
39       printf(" --- In outer except handler i = %d \n", i);
40     }
41   }
42   return 0;
43 }
44 
45 // CHECK-LABEL:@"?foo@@YAXXZ"()
46 // CHECK: invoke.cont:
47 // CHECK: invoke void @llvm.seh.try.begin()
48 // CHECK: store volatile i32 1, ptr %cleanup.dest.slot
49 // CHECK: invoke void @llvm.seh.try.end()
50 // CHECK: invoke.cont2:
51 // CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot
52 // CHECK: %1 = icmp ne i32 %cleanup.dest, 0
53 // CHECK: %2 = zext i1 %1 to i8
54 // CHECK: call void @"?fin$0@0@foo@@"(i8 noundef %2, ptr noundef %0)
55 // CHECK: ehcleanup:
56 // CHECK: call void @"?fin$0@0@foo@@"(i8 noundef 1, ptr noundef %4)
foo()57 void foo()
58 {
59   __try {
60     return;
61   }
62   __finally {
63     if (_abnormal_termination()) {
64       printf("Passed\n");
65     } else {
66       printf("Failed\n");
67     }
68   }
69 }
70 
71 // CHECK-LABEL:@"?bar@@YAHXZ"()
72 // CHECK: invoke.cont:
73 // CHECK: invoke void @llvm.seh.try.begin()
74 // CHECK: invoke.cont1:
75 // CHECK: store volatile i32 1, ptr %cleanup.dest.slot
76 // CHECK: invoke void @llvm.seh.try.end()
77 // CHECK: invoke.cont2:
78 // CHECK: call void @"?fin$0@0@bar@@"
79 // CHECK: %cleanup.dest3 = load i32, ptr %cleanup.dest.slot
80 // CHECK: return:
81 // CHECK: ret i32 11
bar()82 int bar()
83 {
84   int x;
85   __try {
86     return 11;
87   } __finally {
88     if (_abnormal_termination()) {
89       x = 9;
90     }
91   }
92 }
93