xref: /llvm-project/clang/test/CodeGenCXX/for-range.cpp (revision 7eca38ce76d5d1915f4ab7e665964062c0b37697)
1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++11 -emit-llvm -o - %s | FileCheck %s
3 
4 struct A {
5   A();
6   A(const A&);
7   ~A();
8 };
9 
10 struct B {
11   B();
12   B(const B&);
13   ~B();
14 };
15 
16 struct C {
17   C();
18   C(const C&);
19   ~C();
20 };
21 
22 struct D {
23   D();
24   D(const D&);
25   ~D();
26 
27   B *begin();
28   B *end();
29 };
30 
31 B *begin(C&);
32 B *end(C&);
33 
34 extern B array[5];
35 
36 // CHECK-LABEL: @_Z9for_arrayv(
37 // CHECK-NEXT:  entry:
38 // CHECK-NEXT:    [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 1
39 // CHECK-NEXT:    [[__RANGE1:%.*]] = alloca ptr, align 8
40 // CHECK-NEXT:    [[__BEGIN1:%.*]] = alloca ptr, align 8
41 // CHECK-NEXT:    [[__END1:%.*]] = alloca ptr, align 8
42 // CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_B:%.*]], align 1
43 // CHECK-NEXT:    call void @_ZN1AC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
44 // CHECK-NEXT:    store ptr @array, ptr [[__RANGE1]], align 8
45 // CHECK-NEXT:    store ptr @array, ptr [[__BEGIN1]], align 8
46 // CHECK-NEXT:    store ptr getelementptr inbounds ([[STRUCT_B]], ptr @array, i64 5), ptr [[__END1]], align 8
47 // CHECK-NEXT:    br label [[FOR_COND:%.*]]
48 // CHECK:       for.cond:
49 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
50 // CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[__END1]], align 8
51 // CHECK-NEXT:    [[CMP:%.*]] = icmp ne ptr [[TMP0]], [[TMP1]]
52 // CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
53 // CHECK:       for.body:
54 // CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
55 // CHECK-NEXT:    call void @_ZN1BC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[B]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP2]])
56 // CHECK-NEXT:    call void @_ZN1BD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[B]]) #[[ATTR3:[0-9]+]]
57 // CHECK-NEXT:    br label [[FOR_INC:%.*]]
58 // CHECK:       for.inc:
59 // CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
60 // CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_B]], ptr [[TMP3]], i32 1
61 // CHECK-NEXT:    store ptr [[INCDEC_PTR]], ptr [[__BEGIN1]], align 8
62 // CHECK-NEXT:    br label [[FOR_COND]]
63 // CHECK:       for.end:
64 // CHECK-NEXT:    call void @_ZN1AD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR3]]
65 // CHECK-NEXT:    ret void
66 //
67 void for_array() {
68   A a;
69   for (B b : array) {
70   }
71 }
72 
73 // CHECK-LABEL: @_Z9for_rangev(
74 // CHECK-NEXT:  entry:
75 // CHECK-NEXT:    [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 1
76 // CHECK-NEXT:    [[__RANGE1:%.*]] = alloca ptr, align 8
77 // CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_C:%.*]], align 1
78 // CHECK-NEXT:    [[__BEGIN1:%.*]] = alloca ptr, align 8
79 // CHECK-NEXT:    [[__END1:%.*]] = alloca ptr, align 8
80 // CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_B:%.*]], align 1
81 // CHECK-NEXT:    call void @_ZN1AC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
82 // CHECK-NEXT:    call void @_ZN1CC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]])
83 // CHECK-NEXT:    store ptr [[REF_TMP]], ptr [[__RANGE1]], align 8
84 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[__RANGE1]], align 8
85 // CHECK-NEXT:    [[CALL:%.*]] = call noundef ptr @_Z5beginR1C(ptr noundef nonnull align 1 dereferenceable(1) [[TMP0]])
86 // CHECK-NEXT:    store ptr [[CALL]], ptr [[__BEGIN1]], align 8
87 // CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[__RANGE1]], align 8
88 // CHECK-NEXT:    [[CALL1:%.*]] = call noundef ptr @_Z3endR1C(ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]])
89 // CHECK-NEXT:    store ptr [[CALL1]], ptr [[__END1]], align 8
90 // CHECK-NEXT:    br label [[FOR_COND:%.*]]
91 // CHECK:       for.cond:
92 // CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
93 // CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[__END1]], align 8
94 // CHECK-NEXT:    [[CMP:%.*]] = icmp ne ptr [[TMP2]], [[TMP3]]
95 // CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
96 // CHECK:       for.cond.cleanup:
97 // CHECK-NEXT:    call void @_ZN1CD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]]) #[[ATTR3]]
98 // CHECK-NEXT:    br label [[FOR_END:%.*]]
99 // CHECK:       for.body:
100 // CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
101 // CHECK-NEXT:    call void @_ZN1BC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[B]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP4]])
102 // CHECK-NEXT:    call void @_ZN1BD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[B]]) #[[ATTR3]]
103 // CHECK-NEXT:    br label [[FOR_INC:%.*]]
104 // CHECK:       for.inc:
105 // CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
106 // CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_B]], ptr [[TMP5]], i32 1
107 // CHECK-NEXT:    store ptr [[INCDEC_PTR]], ptr [[__BEGIN1]], align 8
108 // CHECK-NEXT:    br label [[FOR_COND]]
109 // CHECK:       for.end:
110 // CHECK-NEXT:    call void @_ZN1AD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR3]]
111 // CHECK-NEXT:    ret void
112 //
113 void for_range() {
114   A a;
115   for (B b : C()) {
116   }
117 }
118 
119 // CHECK-LABEL: @_Z16for_member_rangev(
120 // CHECK-NEXT:  entry:
121 // CHECK-NEXT:    [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 1
122 // CHECK-NEXT:    [[__RANGE1:%.*]] = alloca ptr, align 8
123 // CHECK-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_D:%.*]], align 1
124 // CHECK-NEXT:    [[__BEGIN1:%.*]] = alloca ptr, align 8
125 // CHECK-NEXT:    [[__END1:%.*]] = alloca ptr, align 8
126 // CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_B:%.*]], align 1
127 // CHECK-NEXT:    call void @_ZN1AC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
128 // CHECK-NEXT:    call void @_ZN1DC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]])
129 // CHECK-NEXT:    store ptr [[REF_TMP]], ptr [[__RANGE1]], align 8
130 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[__RANGE1]], align 8
131 // CHECK-NEXT:    [[CALL:%.*]] = call noundef ptr @_ZN1D5beginEv(ptr noundef nonnull align 1 dereferenceable(1) [[TMP0]])
132 // CHECK-NEXT:    store ptr [[CALL]], ptr [[__BEGIN1]], align 8
133 // CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[__RANGE1]], align 8
134 // CHECK-NEXT:    [[CALL1:%.*]] = call noundef ptr @_ZN1D3endEv(ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]])
135 // CHECK-NEXT:    store ptr [[CALL1]], ptr [[__END1]], align 8
136 // CHECK-NEXT:    br label [[FOR_COND:%.*]]
137 // CHECK:       for.cond:
138 // CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
139 // CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[__END1]], align 8
140 // CHECK-NEXT:    [[CMP:%.*]] = icmp ne ptr [[TMP2]], [[TMP3]]
141 // CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
142 // CHECK:       for.cond.cleanup:
143 // CHECK-NEXT:    call void @_ZN1DD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]]) #[[ATTR3]]
144 // CHECK-NEXT:    br label [[FOR_END:%.*]]
145 // CHECK:       for.body:
146 // CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
147 // CHECK-NEXT:    call void @_ZN1BC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[B]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP4]])
148 // CHECK-NEXT:    call void @_ZN1BD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[B]]) #[[ATTR3]]
149 // CHECK-NEXT:    br label [[FOR_INC:%.*]]
150 // CHECK:       for.inc:
151 // CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[__BEGIN1]], align 8
152 // CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr inbounds nuw [[STRUCT_B]], ptr [[TMP5]], i32 1
153 // CHECK-NEXT:    store ptr [[INCDEC_PTR]], ptr [[__BEGIN1]], align 8
154 // CHECK-NEXT:    br label [[FOR_COND]]
155 // CHECK:       for.end:
156 // CHECK-NEXT:    call void @_ZN1AD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR3]]
157 // CHECK-NEXT:    ret void
158 //
159 void for_member_range() {
160   A a;
161   for (B b : D()) {
162   }
163 }
164