1 // RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fms-extensions -fms-compatibility -fms-compatibility-version=19 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
2 // REQUIRES: asserts
3 
4 struct S {
5   S();
6   ~S();
7 };
8 
9 // CHECK-DAG: @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
10 // CHECK-DAG: @"\01??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
11 // CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr global %struct.S zeroinitializer
12 // CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ" = linkonce_odr global i32 0
13 // CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4
14 // CHECK-DAG: @"\01?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
15 // CHECK-DAG: @"\01??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0
16 // CHECK-DAG: @"\01?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr global %struct.S zeroinitializer
17 // CHECK-DAG: @"\01?$TSS0@?1??h@@YAAAUS@@_N@Z" = linkonce_odr global i32 0
18 
19 // CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"()
20 extern inline S &f() {
21   static thread_local S s;
22 // CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
23 // CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], 1
24 // CHECK-NEXT:  %[[cmp:.*]] = icmp ne i32 %[[mask]], 0
25 // CHECK-NEXT:  br i1 %[[cmp]], label %[[init_end:.*]], label %[[init:.*]]
26 //
27 // CHECK:     [[init]]:
28 // CHECK-NEXT:  %[[or:.*]] = or i32 %[[guard]], 1
29 // CHECK-NEXT:  store i32 %[[or]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
30 // CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A")
31 // CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
32 //
33 // CHECK:     [[invoke_cont]]:
34 // CHECK-NEXT:  call i32 @__tlregdtor(void ()* @"\01??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
35 // CHECK-NEXT:  br label %[[init_end:.*]]
36 
37 // CHECK:     [[init_end]]:
38 // CHECK-NEXT:  ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"
39 
40 // CHECK:     [[lpad:.*]]:
41 // CHECK-NEXT:  landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
42 // CHECK-NEXT:    cleanup
43 // CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
44 // CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], -2
45 // CHECK-NEXT:  store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
46 // CHECK-NEXT:  br label %[[eh_resume:.*]]
47 //
48 // CHECK:     [[eh_resume]]:
49 // CHECK:       resume { i8*, i32 }
50   return s;
51 }
52 
53 
54 // CHECK-LABEL: define {{.*}} @"\01?g@@YAAAUS@@XZ"()
55 extern inline S &g() {
56   static S s;
57 // CHECK:  %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4
58 // CHECK-NEXT:  %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch
59 // CHECK-NEXT:  %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]]
60 // CHECK-NEXT:  br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]]
61 //
62 // CHECK:     [[init_attempt]]:
63 // CHECK-NEXT:  call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
64 // CHECK-NEXT:  %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ" unordered, align 4
65 // CHECK-NEXT:  %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -1
66 // CHECK-NEXT:  br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]]
67 //
68 // CHECK:     [[init]]:
69 // CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A")
70 // CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
71 //
72 // CHECK:     [[invoke_cont]]:
73 // CHECK-NEXT:  call i32 @atexit(void ()* @"\01??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
74 // CHECK-NEXT:  call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
75 // CHECK-NEXT:  br label %init.end
76 //
77 // CHECK:     [[init_end]]:
78 // CHECK-NEXT:  ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
79 //
80 // CHECK:     [[lpad]]:
81 // CHECK:       call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
82 // CHECK-NEXT:  br label %[[eh_resume:.*]]
83 //
84 // CHECK:     [[eh_resume]]:
85 // CHECK:       resume { i8*, i32 }
86   return s;
87 }
88 
89 extern inline S&h(bool b) {
90   static thread_local S j;
91   static S i;
92   return b ? j : i;
93 }
94