1; RUN: opt < %s -functionattrs -S | FileCheck %s
2; RUN: opt < %s -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S | FileCheck %s --check-prefix=ATTRIBUTOR
3
4; TEST 1
5; CHECK: Function Attrs: norecurse nounwind readnone
6; CHECK-NEXT: define i32 @foo1()
7; ATTRIBUTOR: Function Attrs: nofree nosync nounwind
8; ATTRIBUTOR-NEXT: define i32 @foo1()
9define i32 @foo1() {
10  ret i32 1
11}
12
13; TEST 2
14; CHECK: Function Attrs: nounwind readnone
15; CHECK-NEXT: define i32 @scc1_foo()
16; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind
17; ATTRIBUTOR-NEXT: define i32 @scc1_foo()
18define i32 @scc1_foo() {
19  %1 = call i32 @scc1_bar()
20  ret i32 1
21}
22
23
24; TEST 3
25; CHECK: Function Attrs: nounwind readnone
26; CHECK-NEXT: define i32 @scc1_bar()
27; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind
28; ATTRIBUTOR-NEXT: define i32 @scc1_bar()
29define i32 @scc1_bar() {
30  %1 = call i32 @scc1_foo()
31  ret i32 1
32}
33
34; CHECK: declare i32 @non_nounwind()
35declare i32 @non_nounwind()
36
37; TEST 4
38; CHECK: define void @call_non_nounwind() {
39; ATTRIBUTOR: define void @call_non_nounwind() {
40define void @call_non_nounwind(){
41    tail call i32 @non_nounwind()
42    ret void
43}
44
45; TEST 5 - throw
46; int maybe_throw(bool canThrow) {
47;   if (canThrow)
48;     throw;
49;   else
50;     return -1;
51; }
52
53; CHECK: define i32 @maybe_throw(i1 zeroext %0)
54; ATTRIBUTOR: define i32 @maybe_throw(i1 zeroext %0)
55define i32 @maybe_throw(i1 zeroext %0) {
56  br i1 %0, label %2, label %3
57
582:                                                ; preds = %1
59  tail call void @__cxa_rethrow() #1
60  unreachable
61
623:                                                ; preds = %1
63  ret i32 -1
64}
65
66declare void @__cxa_rethrow()
67
68; TEST 6 - catch
69; int catch_thing() {
70;   try {
71;       int a = doThing(true);
72;   }
73;   catch(...) { return -1; }
74;   return 1;
75; }
76
77; CHECK: define i32 @catch_thing()
78; ATTRIBUTOR: define i32 @catch_thing()
79define i32 @catch_thing() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
80  invoke void @__cxa_rethrow() #1
81          to label %1 unwind label %2
82
831:                                                ; preds = %0
84  unreachable
85
862:                                                ; preds = %0
87  %3 = landingpad { i8*, i32 }
88          catch i8* null
89  %4 = extractvalue { i8*, i32 } %3, 0
90  %5 = tail call i8* @__cxa_begin_catch(i8* %4) #2
91  tail call void @__cxa_end_catch()
92  ret i32 -1
93}
94
95define i32 @catch_thing_user() {
96; ATTRIBUTOR:     define i32 @catch_thing_user
97; ATTRIBUTOR-NEXT: %catch_thing_call = call
98; ATTRIBUTOR-NEXT: ret i32 -1
99  %catch_thing_call = call i32 @catch_thing()
100  ret i32 %catch_thing_call
101}
102
103
104declare i32 @__gxx_personality_v0(...)
105
106declare i8* @__cxa_begin_catch(i8*)
107
108declare void @__cxa_end_catch()
109