210 lines · cpp
1// RUN: %clang_cc1 -std=c++2c -verify -emit-llvm -triple=x86_64-pc-linux-gnu %s -o - | FileCheck %s2// RUN: %clang_cc1 -std=c++2c -verify -emit-llvm -triple=x86_64-pc-linux-gnu %s -o - -fexperimental-new-constant-interpreter | FileCheck %s3// expected-no-diagnostics4 5namespace std {6 7template <typename T> struct tuple_size;8 9template <int, typename> struct tuple_element;10 11} // namespace std12 13namespace Case1 {14 15struct S {16 int a, b;17 bool flag = false;18 19 constexpr explicit operator bool() {20 flag = true;21 return a != b;22 }23 24 constexpr operator int() {25 flag = true;26 return a * b;27 }28 29 constexpr bool operator==(S rhs) const {30 return a == rhs.a && b == rhs.b;31 }32 33 template <int I>34 constexpr int& get() {35 if (!flag)36 return a = a + b;37 return I == 0 ? a : b;38 }39};40 41} // namespace Case142 43template <> struct std::tuple_size<Case1::S> {44 static const int value = 2;45};46 47template <int I> struct std::tuple_element<I, Case1::S> {48 using type = int;49};50 51namespace Case1 {52 53void foo() {54 if (S s(1, 2); auto [a, b] = s) {55 __builtin_assume(a == 1);56 __builtin_assume(b == 2);57 }58// CHECK: %[[call:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv59// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv60// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv61// CHECK: br i1 %[[call]], label {{.*}}, label {{.*}}62 63 if (auto [a, b] = S(1, 2)) {64 __builtin_assume(a == 1);65 __builtin_assume(b == 2);66 }67// CHECK: %[[call2:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv68// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv69// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv70// CHECK: br i1 %[[call2]], label {{.*}}, label {{.*}}71 72 if (S s(3, 4); auto& [a, b] = s) {73 __builtin_assume(a == 3);74 __builtin_assume(b == 4);75 }76// CHECK: %[[call3:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv77// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv78// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv79// CHECK: br i1 %[[call3]], label {{.*}}, label {{.*}}80 81 while (auto [i, j] = S(5, 6))82 break;83 84// CHECK: while.cond{{.*}}:85// CHECK: %[[call4:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv86// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv87// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv88// CHECK: br i1 %[[call4]], label {{.*}}, label {{.*}}89 90 S s(7, 8);91 while (auto& [i, j] = s)92 break;93 94// CHECK: while.cond{{.*}}:95// CHECK: %[[call5:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv96// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv97// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv98// CHECK: br i1 %[[call5]], label {{.*}}, label {{.*}}99 100 for (int k = 0; auto [i, j] = S(24, 42); ++k)101 break;102 103// CHECK: for.cond{{.*}}:104// CHECK: %[[call6:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv105// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv106// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv107// CHECK: br i1 %[[call6]], label {{.*}}, label {{.*}}108 109 for (S s(114, 514); auto& [i, j] = s; ++i)110 break;111 112// CHECK: for.cond{{.*}}:113// CHECK: %[[call7:.+]] = call {{.*}} i1 @_ZN5Case11ScvbEv114// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv115// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv116// CHECK: br i1 %[[call7]], label {{.*}}, label {{.*}}117 118 switch (S s(10, 11); auto& [i, j] = s) {119 case 10 * 11:120 __builtin_assume(i == 10);121 __builtin_assume(j == 11);122 break;123 default:124 break;125 }126 127// CHECK: %[[call8:.+]] = call {{.*}} i32 @_ZN5Case11ScviEv128// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi0EEERiv129// CHECK: %{{.*}} = call {{.*}} ptr @_ZN5Case11S3getILi1EEERiv130// CHECK: switch i32 %[[call8]], label {{.*}}131 132}133 134constexpr int bar(auto) {135 constexpr auto value = [] {136 if (S s(1, 2); auto [i, j] = s)137 return S(i, j);138 return S(0, 0);139 }();140 static_assert(value == S(1, 2));141 142 constexpr auto value2 = [] {143 if (auto [a, b] = S(1, 2))144 return S(a, b);145 return S(0, 0);146 }();147 static_assert(value2 == S(1, 2));148 149 constexpr auto value3 = [] {150 if (auto&& [a, b] = S(3, 4))151 return S(a, b);152 return S(0, 0);153 }();154 static_assert(value3 == S(3, 4));155 156 constexpr auto value4 = [] {157 S s(7, 8);158 int cnt = 0;159 while (auto& [i, j] = s) {160 s.flag = false;161 ++i, ++j;162 if (++cnt == 10)163 break;164 }165 return s;166 }();167 static_assert(value4 == S(17, 18));168 169 constexpr auto value5 = [] {170 S s(3, 4);171 for (int cnt = 0; auto& [x, y] = s; s.flag = false, ++cnt) {172 if (cnt == 3)173 break;174 ++x, ++y;175 }176 return s;177 }();178 static_assert(value5 == S(6, 7));179 180 constexpr auto value6 = [] {181 switch (auto [x, y] = S(3, 4)) {182 case 3 * 4:183 return S(x, y);184 default:185 return S(y, x);186 }187 }();188 static_assert(value6 == S(3, 4));189 190 return 42;191}192 193constexpr int value = bar(1);194 195#if 0196 197// FIXME: This causes clang to ICE, though this is not a regression.198constexpr int ice(auto) {199 if constexpr (S s(1, 2); auto [i, j] = s) {200 static_assert(i == 1);201 }202 return 42;203}204 205constexpr int value2 = ice(1);206 207#endif208 209} // namespace Case1210