Skip to content

Commit 2ae72b4

Browse files
committed
Add more tests; handle switch (..) case .. in constant evaluator
1 parent ffe3922 commit 2ae72b4

File tree

2 files changed

+130
-21
lines changed

2 files changed

+130
-21
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5351,6 +5351,12 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info,
53515351
if (!EvaluateInteger(SS->getCond(), Value, Info))
53525352
return ESR_Failed;
53535353

5354+
if (auto *DD =
5355+
dyn_cast_if_present<DecompositionDecl>(SS->getConditionVariable());
5356+
DD && DD->isDecisionVariable() &&
5357+
!EvaluateDecompositionDeclInit(Info, DD))
5358+
return ESR_Failed;
5359+
53545360
if (!CondScope.destroy())
53555361
return ESR_Failed;
53565362
}

clang/test/CodeGen/p0963r3.cpp

Lines changed: 124 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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

44
namespace std {
@@ -13,16 +13,26 @@ namespace Case1 {
1313

1414
struct 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

Comments
 (0)