1- // RUN: %clang_cc1 -std=c++2c -verify -emit-llvm %s -o - | FileCheck %s
1+ // RUN: %clang_cc1 -std=c++2c -verify -emit-llvm -triple=x86_64-pc-linux-gnu %s -o - | FileCheck %s
22// expected-no-diagnostics
33
44namespace std {
@@ -13,16 +13,26 @@ namespace Case1 {
1313
1414struct S {
1515 int a, b;
16- bool called_operator_bool = false ;
16+ bool flag = false ;
1717
18- operator bool () {
19- called_operator_bool = true ;
18+ constexpr explicit operator bool () {
19+ flag = true ;
2020 return a != b;
2121 }
2222
23- template <int I> int get () {
24- if (!called_operator_bool)
25- return a + b;
23+ constexpr operator int () {
24+ flag = true ;
25+ return a * b;
26+ }
27+
28+ constexpr bool operator ==(S rhs) const {
29+ return a == rhs.a && b == rhs.b ;
30+ }
31+
32+ template <int I>
33+ constexpr int & get () {
34+ if (!flag)
35+ return a = a + b;
2636 return I == 0 ? a : b;
2737 }
2838};
@@ -45,35 +55,35 @@ void foo() {
4555 __builtin_assume (b == 2 );
4656 }
4757// CHECK: %[[call:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv
48- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi0EEEiv
49- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi1EEEiv
58+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
59+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
5060// CHECK: br i1 %[[call]], label {{.*}}, label {{.*}}
5161
5262 if (auto [a, b] = S (1 , 2 )) {
5363 __builtin_assume (a == 1 );
5464 __builtin_assume (b == 2 );
5565 }
5666// CHECK: %[[call2:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv
57- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi0EEEiv
58- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi1EEEiv
67+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
68+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
5969// CHECK: br i1 %[[call2]], label {{.*}}, label {{.*}}
6070
6171 if (S s (3 , 4 ); auto & [a, b] = s) {
6272 __builtin_assume (a == 3 );
6373 __builtin_assume (b == 4 );
6474 }
6575// CHECK: %[[call3:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv
66- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi0EEEiv
67- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi1EEEiv
76+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
77+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
6878// CHECK: br i1 %[[call3]], label {{.*}}, label {{.*}}
6979
7080 while (auto [i, j] = S (5 , 6 ))
7181 break ;
7282
7383// CHECK: while.cond{{.*}}:
7484// CHECK: %[[call4:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv
75- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi0EEEiv
76- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi1EEEiv
85+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
86+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
7787// CHECK: br i1 %[[call4]], label {{.*}}, label {{.*}}
7888
7989 S s (7 , 8 );
@@ -82,27 +92,120 @@ void foo() {
8292
8393// CHECK: while.cond{{.*}}:
8494// CHECK: %[[call5:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv
85- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi0EEEiv
86- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi1EEEiv
95+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
96+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
8797// CHECK: br i1 %[[call5]], label {{.*}}, label {{.*}}
8898
8999 for (int k = 0 ; auto [i, j] = S (24 , 42 ); ++k)
90100 break ;
91101
92102// CHECK: for.cond{{.*}}:
93103// CHECK: %[[call6:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv
94- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi0EEEiv
95- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi1EEEiv
104+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
105+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
96106// CHECK: br i1 %[[call6]], label {{.*}}, label {{.*}}
97107
98108 for (S s (114 , 514 ); auto & [i, j] = s; ++i)
99109 break ;
100110
101111// CHECK: for.cond{{.*}}:
102112// CHECK: %[[call7:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv
103- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi0EEEiv
104- // CHECK: %{{.*}} = call {{.*}} i32 @_ZN5Case11S3getILi1EEEiv
113+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
114+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
105115// CHECK: br i1 %[[call7]], label {{.*}}, label {{.*}}
116+
117+ switch (S s (10 , 11 ); auto & [i, j] = s) {
118+ case 10 * 11 :
119+ __builtin_assume (i == 10 );
120+ __builtin_assume (j == 11 );
121+ break ;
122+ default :
123+ break ;
124+ }
125+
126+ // CHECK: %[[call8:.+]] = call {{.*}} i32 @_ZN5Case11ScviEv
127+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv
128+ // CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv
129+ // CHECK: switch i32 %[[call8]], label {{.*}}
130+
106131}
107132
133+ constexpr int bar (auto ) {
134+ constexpr auto value = [] {
135+ if (S s (1 , 2 ); auto [i, j] = s)
136+ return S (i, j);
137+ return S (0 , 0 );
138+ }();
139+ static_assert (value == S (1 , 2 ));
140+
141+ // FIXME: The diagnostic message adds a trailing comma "static assertion failed due to requirement 'value == Case1::S((0, 1, ))'"
142+ // static_assert(value == S(0, 1));
143+
144+ constexpr auto value2 = [] {
145+ if (auto [a, b] = S (1 , 2 ))
146+ return S (a, b);
147+ return S (0 , 0 );
148+ }();
149+ static_assert (value2 == S (1 , 2 ));
150+
151+ constexpr auto value3 = [] {
152+ if (auto && [a, b] = S (3 , 4 ))
153+ return S (a, b);
154+ return S (0 , 0 );
155+ }();
156+ static_assert (value3 == S (3 , 4 ));
157+
158+ constexpr auto value4 = [] {
159+ S s (7 , 8 );
160+ int cnt = 0 ;
161+ while (auto & [i, j] = s) {
162+ s.flag = false ;
163+ ++i, ++j;
164+ if (++cnt == 10 )
165+ break ;
166+ }
167+ return s;
168+ }();
169+ static_assert (value4 == S (17 , 18 ));
170+
171+ constexpr auto value5 = [] {
172+ S s (3 , 4 );
173+ for (int cnt = 0 ; auto & [x, y] = s; s.flag = false , ++cnt) {
174+ if (cnt == 3 )
175+ break ;
176+ ++x, ++y;
177+ }
178+ return s;
179+ }();
180+ static_assert (value5 == S (6 , 7 ));
181+
182+ constexpr auto value6 = [] {
183+ switch (auto [x, y] = S (3 , 4 )) {
184+ case 3 * 4 :
185+ return S (x, y);
186+ default :
187+ return S (y, x);
188+ }
189+ }();
190+ static_assert (value6 == S (3 , 4 ));
191+
192+ return 42 ;
193+ }
194+
195+ constexpr int value = bar(1 );
196+
197+ #if 0
198+
199+ // FIXME: This causes clang to ICE, though this is not a regression.
200+ constexpr int ice(auto) {
201+ if constexpr (S s(1, 2); auto [i, j] = s) {
202+ static_assert(i == 1);
203+ }
204+ return 42;
205+ }
206+
207+ constexpr int value2 = ice(1);
208+
209+ #endif
210+
108211} // namespace Case1
0 commit comments