brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.8 KiB · b7fef12 Raw
304 lines · cpp
1// RUN: %clang_cc1 -std=c++1z -verify %s2 3using size_t = decltype(sizeof(0));4 5struct A { int x, y; };6struct B { int x, y; };7 8void no_tuple_size_1() { auto [x, y] = A(); } // ok, bind elementwise9 10namespace std { template<typename T> struct tuple_size; }11void no_tuple_size_2() { auto [x, y] = A(); } // ok, bind elementwise12 13struct Bad1 { int a, b; };14template<> struct std::tuple_size<Bad1> {};15void no_tuple_size_3() { auto [x, y] = Bad1(); } // ok, omitting value is valid after DR238616 17struct Bad2 {};18template<> struct std::tuple_size<Bad2> { const int value = 5; };19void no_tuple_size_4() { auto [x, y] = Bad2(); } // expected-error {{cannot bind this type; 'std::tuple_size<Bad2>::value' is not a valid integral constant expression}}20 21template<> struct std::tuple_size<A> { static const int value = 3; };22template<> struct std::tuple_size<B> { enum { value = 3 }; };23 24void no_get_1() {25  {26    auto [a0, a1] = A(); // expected-error {{binds to 3 elements}}27    auto [b0, b1] = B(); // expected-error {{binds to 3 elements}}28  }29  auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}30}31 32int get(A);33 34void no_get_2() {35  // FIXME: This diagnostic is not great.36  auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}37}38 39template<int> float &get(A); // expected-note 2 {{no known conversion}}40 41void no_tuple_element_1() {42  auto [a0, a1, a2] = A(); // expected-error-re {{'std::tuple_element<0U{{L*}}, A>::type' does not name a type}} expected-note {{in implicit}}43}44 45namespace std { template<size_t, typename> struct tuple_element; } // expected-note 2{{here}}46 47void no_tuple_element_2() {48  auto [a0, a1, a2] = A(); // expected-error {{implicit instantiation of undefined template 'std::tuple_element<0, A>'}} expected-note {{in implicit}}49}50 51template<> struct std::tuple_element<0, A> { typedef float type; };52 53void no_tuple_element_3() {54  auto [a0, a1, a2] = A(); // expected-error {{implicit instantiation of undefined template 'std::tuple_element<1, A>'}} expected-note {{in implicit}}55}56 57template<> struct std::tuple_element<1, A> { typedef float &type; };58template<> struct std::tuple_element<2, A> { typedef const float &type; };59 60template<int N> auto get(B) -> int (&)[N + 1]; // expected-note 2 {{no known conversion}}61template<int N> struct std::tuple_element<N, B> { typedef int type[N +1 ]; };62 63template<typename T> struct std::tuple_size<const T> : std::tuple_size<T> {};64template<size_t N, typename T> struct std::tuple_element<N, const T> {65  typedef const typename std::tuple_element<N, T>::type type;66};67 68void referenced_type() {69  auto [a0, a1, a2] = A();70  auto [b0, b1, b2] = B();71 72  A a;73  B b;74  auto &[ar0, ar1, ar2] = a;75  auto &[br0, br1, br2] = b;76 77  auto &&[arr0, arr1, arr2] = A();78  auto &&[brr0, brr1, brr2] = B();79 80  const auto &[acr0, acr1, acr2] = A();81  const auto &[bcr0, bcr1, bcr2] = B();82 83 84  using Float = float;85  using Float = decltype(a0);86  using Float = decltype(ar0);87  using Float = decltype(arr0);88 89  using ConstFloat = const float;90  using ConstFloat = decltype(acr0);91 92  using FloatRef = float&;93  using FloatRef = decltype(a1);94  using FloatRef = decltype(ar1);95  using FloatRef = decltype(arr1);96  using FloatRef = decltype(acr1);97 98  using ConstFloatRef = const float&;99  using ConstFloatRef = decltype(a2);100  using ConstFloatRef = decltype(ar2);101  using ConstFloatRef = decltype(arr2);102  using ConstFloatRef = decltype(acr2);103 104 105  using Int1 = int[1];106  using Int1 = decltype(b0);107  using Int1 = decltype(br0);108  using Int1 = decltype(brr0);109 110  using ConstInt1 = const int[1];111  using ConstInt1 = decltype(bcr0);112 113  using Int2 = int[2];114  using Int2 = decltype(b1);115  using Int2 = decltype(br1);116  using Int2 = decltype(brr1);117 118  using ConstInt2 = const int[2];119  using ConstInt2 = decltype(bcr1);120 121  using Int3 = int[3];122  using Int3 = decltype(b2);123  using Int3 = decltype(br2);124  using Int3 = decltype(brr2);125 126  using ConstInt3 = const int[3];127  using ConstInt3 = decltype(bcr2);128}129 130struct C { template<int> int get() const; };131template<> struct std::tuple_size<C> { static const int value = 1; };132template<> struct std::tuple_element<0, C> { typedef int type; };133 134int member_get() {135  auto [c] = C();136  using T = int;137  using T = decltype(c);138  return c;139}140 141constexpr C c = C();142template<const C *p> void dependent_binding_PR40674() {143  const auto &[c] = *p;144  (void)c;145}146 147struct D {148  // FIXME: Emit a note here explaining why this was ignored.149  template<int> struct get {};150};151template<> struct std::tuple_size<D> { static const int value = 1; };152template<> struct std::tuple_element<0, D> { typedef D::get<0> type; };153void member_get_class_template() {154  auto [d] = D(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}155}156 157struct E {158  // FIXME: Emit a note here explaining why this was ignored.159  int get();160};161template<> struct std::tuple_size<E> { static const int value = 1; };162template<> struct std::tuple_element<0, E> { typedef int type; };163void member_get_non_template() {164  // FIXME: This diagnostic is not very good.165  auto [e] = E(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}}166}167 168namespace ADL {169  struct X {};170};171template<int> int get(ADL::X);172template<> struct std::tuple_size<ADL::X> { static const int value = 1; };173template<> struct std::tuple_element<0, ADL::X> { typedef int type; };174void adl_only_bad() {175  auto [x] = ADL::X(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit init}}176}177 178template<typename ElemType, typename GetTypeLV, typename GetTypeRV>179struct wrap {180  template<size_t> GetTypeLV get() &;181  template<size_t> GetTypeRV get() &&;182};183template<typename ET, typename GTL, typename GTR>184struct std::tuple_size<wrap<ET, GTL, GTR>> {185  static const int value = 1;186};187template<typename ET, typename GTL, typename GTR>188struct std::tuple_element<0, wrap<ET, GTL, GTR>> {189  using type = ET;190};191 192template<typename T> T &lvalue();193 194void test_value_category() {195  // If the declared variable is an lvalue reference, the operand to get is an196  // lvalue. Otherwise it's an xvalue.197  { auto [a] = wrap<int, void, int>(); }198  { auto &[a] = lvalue<wrap<int, int, void>>(); }199  { auto &&[a] = wrap<int, void, int>(); }200  // If the initializer (call to get) is an lvalue, the binding is an lvalue201  // reference to the element type. Otherwise it's an rvalue reference to the202  // element type.203  { auto [a] = wrap<int, void, int&>(); }204  { auto [a] = wrap<int&, void, int&>(); }205  { auto [a] = wrap<int&&, void, int&>(); } // ok, reference collapse to int&206 207  { auto [a] = wrap<int, void, int&&>(); }208  { auto [a] = wrap<int&, void, int&&>(); } // expected-error {{non-const lvalue reference to type 'int' cannot bind}} expected-note {{in implicit}}209  { auto [a] = wrap<const int&, void, int&&>(); }210  { auto [a] = wrap<int&&, void, int&&>(); }211 212  { auto [a] = wrap<int, void, float&>(); } // expected-error {{cannot bind}} expected-note {{implicit}}213  { auto [a] = wrap<const int, void, float&>(); } // ok, const int &a can bind to float214  { auto [a] = wrap<int, void, float>(); } // ok, int &&a can bind to float215}216 217namespace constant {218  struct Q {};219  template<int N> constexpr int get(Q &&) { return N * N; }220}221template<> struct std::tuple_size<constant::Q> { static const int value = 3; };222template<int N> struct std::tuple_element<N, constant::Q> { typedef int type; };223namespace constant {224  Q q;225  // This creates and lifetime-extends a temporary to hold the result of each get() call.226  auto [a, b, c] = q;    // expected-note {{temporary}}227  static_assert(a == 0); // expected-error {{constant expression}} expected-note {{temporary}}228 229  constexpr bool f() {230    auto [a, b, c] = q;231    return a == 0 && b == 1 && c == 4;232  }233  static_assert(f());234 235  constexpr int g() {236    int *p = nullptr;237    {238      auto [a, b, c] = q;239      p = &c;240    }241    return *p; // expected-note {{read of object outside its lifetime}}242  }243  static_assert(g() == 4); // expected-error {{constant}} expected-note {{in call to 'g()'}}244}245 246// P0961R1247struct InvalidMemberGet {248  int get();249  template <class T> int get();250  struct get {};251};252template <> struct std::tuple_size<InvalidMemberGet> { static constexpr size_t value = 1; };253template <> struct std::tuple_element<0, InvalidMemberGet> { typedef float type; };254template <size_t> float get(InvalidMemberGet) { return 0; }255int f() {256  InvalidMemberGet img;257  auto [x] = img;258  typedef decltype(x) same_as_float;259  typedef float same_as_float;260}261 262struct ValidMemberGet {263  int get();264  template <class T> int get() { return 0; }265  template <size_t N> float get() { return 0; }266};267template <> struct std::tuple_size<ValidMemberGet> { static constexpr size_t value = 1; };268template <> struct std::tuple_element<0, ValidMemberGet> { typedef float type; };269// Don't use this one; we should use the member get.270template <size_t N> int get(ValidMemberGet) { static_assert(N && false, ""); }271int f2() {272  ValidMemberGet img;273  auto [x] = img;274  typedef decltype(x) same_as_float;275  typedef float same_as_float;276}277 278struct Base1 {279  int get(); // expected-note{{member found by ambiguous name lookup}}280};281struct Base2 {282  template<int> int get(); // expected-note{{member found by ambiguous name lookup}}283};284struct Derived : Base1, Base2 {};285 286template <> struct std::tuple_size<Derived> { static constexpr size_t value = 1; };287template <> struct std::tuple_element<0, Derived> { typedef int type; };288 289auto [x] = Derived(); // expected-error{{member 'get' found in multiple base classes of different types}}290 291struct Base {292  template<int> int get();293};294struct UsingGet : Base {295  using Base::get;296};297 298template <> struct std::tuple_size<UsingGet> {299  static constexpr size_t value = 1;300};301template <> struct std::tuple_element<0, UsingGet> { typedef int type; };302 303auto [y] = UsingGet();304