brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 1a97dbf Raw
106 lines · cpp
1// RUN: %clang_cc1 -std=c++23 -verify %s2 3// Ensure we substitute into instantiation-dependent but non-dependent4// constructs. The poster-child for this is...5template<class ...> using void_t = void;6 7namespace PR24076 {8  template<class T> T declval();9  struct s {};10 11  template<class T,12           class = void_t<decltype(declval<T>() + 1)>>13    void foo(T) {} // expected-note {{invalid operands to binary expression}}14 15  void f() {16    foo(s{}); // expected-error {{no matching function}}17  }18 19  template<class T,20           class = void_t<decltype(declval<T>() + 1)>> // expected-error {{invalid operands to binary expression}}21  struct bar {};22 23  bar<s> bar; // expected-note {{in instantiation of}}24}25 26namespace PR33655 {27  struct One { using x = int; };28  struct Two { using y = int; };29 30  template<typename T, void_t<typename T::x> * = nullptr> int &func() {}31  template<typename T, void_t<typename T::y> * = nullptr> float &func() {}32 33  int &test1 = func<One>();34  float &test2 = func<Two>();35 36  template<class ...Args> struct indirect_void_t_imp { using type = void; };37  template<class ...Args> using indirect_void_t = typename indirect_void_t_imp<Args...>::type;38 39  template<class T> void foo() {40    int check1[__is_void(indirect_void_t<T>) == 0 ? 1 : -1]; // "ok", dependent41    int check2[__is_void(void_t<T>) == 0 ? 1 : -1]; // expected-error {{array with a negative size}}42  }43}44 45namespace PR46791 { // also PR4578246  template<typename T, typename = void>47  struct trait {48    static constexpr int specialization = 0;49  };50 51  // FIXME: Per a strict interpretation of the C++ rules, the two void_t<...>52  // types below are equivalent -- we only (effectively) do token-by-token53  // comparison for *expressions* appearing within types. But all other54  // implementations accept this, using rules that are unclear.55  template<typename T>56  struct trait<T, void_t<typename T::value_type>> { // expected-note {{previous}} FIXME-note {{matches}}57    static constexpr int specialization = 1;58  };59 60  template<typename T>61  struct trait<T, void_t<typename T::element_type>> { // expected-error {{redefinition}} FIXME-note {{matches}}62    static constexpr int specialization = 2;63  };64 65  struct A {};66  struct B { typedef int value_type; };67  struct C { typedef int element_type; };68  struct D : B, C {};69 70  static_assert(trait<A>::specialization == 0);71  static_assert(trait<B>::specialization == 1); // FIXME expected-error {{failed}} \72                                                // expected-note {{evaluates to '0 == 1'}}73  static_assert(trait<C>::specialization == 2); // FIXME expected-error {{failed}} \74                                                // expected-note {{evaluates to '0 == 2'}}75  static_assert(trait<D>::specialization == 0); // FIXME-error {{ambiguous partial specialization}}76}77 78namespace TypeQualifier {79  // Ensure that we substitute into an instantiation-dependent but80  // non-dependent qualifier.81  template<int> struct A { using type = int; };82  template<typename T> A<sizeof(sizeof(T::error))>::type f() {} // expected-note {{'int' cannot be used prior to '::'}}83  int k = f<int>(); // expected-error {{no matching}}84}85 86namespace MemberOfInstantiationDependentBase {87  template<typename T> struct A { template<int> void f(int); };88  template<typename T> struct B { using X = A<T>; };89  template<typename T> struct C1 : B<int> {90    using X = typename C1::X;91    void f(X *p) {92      p->f<0>(0);93      p->template f<0>(0);94    }95  };96  template<typename T> struct C2 : B<int> {97    using X = typename C2<T>::X;98    void f(X *p) {99      p->f<0>(0);100      p->template f<0>(0);101    }102  };103  void q(C1<int> *c) { c->f(0); }104  void q(C2<int> *c) { c->f(0); }105}106