// RUN: %clang_cc1 -std=c++2b -verify %s // Ensure we substitute into instantiation-dependent but non-dependent // constructs. The poster-child for this is... template using void_t = void; namespace PR24076 { template T declval(); struct s {}; template() + 1)>> void foo(T) {} // expected-note {{invalid operands to binary expression}} void f() { foo(s{}); // expected-error {{no matching function}} } template() + 1)>> // expected-error {{invalid operands to binary expression}} struct bar {}; bar bar; // expected-note {{in instantiation of}} } namespace PR33655 { struct One { using x = int; }; struct Two { using y = int; }; template * = nullptr> int &func() {} template * = nullptr> float &func() {} int &test1 = func(); float &test2 = func(); template struct indirect_void_t_imp { using type = void; }; template using indirect_void_t = typename indirect_void_t_imp::type; template void foo() { static_assert(!__is_void(indirect_void_t)); // "ok", dependent static_assert(!__is_void(void_t)); // expected-error {{failed}} } } namespace PR46791 { // also PR45782 template struct trait { static constexpr int specialization = 0; }; // FIXME: Per a strict interpretation of the C++ rules, the two void_t<...> // types below are equivalent -- we only (effectively) do token-by-token // comparison for *expressions* appearing within types. But all other // implementations accept this, using rules that are unclear. template struct trait> { // expected-note {{previous}} FIXME-note {{matches}} static constexpr int specialization = 1; }; template struct trait> { // expected-error {{redefinition}} FIXME-note {{matches}} static constexpr int specialization = 2; }; struct A {}; struct B { typedef int value_type; }; struct C { typedef int element_type; }; struct D : B, C {}; static_assert(trait::specialization == 0); static_assert(trait::specialization == 1); // FIXME expected-error {{failed}} static_assert(trait::specialization == 2); // FIXME expected-error {{failed}} static_assert(trait::specialization == 0); // FIXME-error {{ambiguous partial specialization}} } namespace TypeQualifier { // Ensure that we substitute into an instantiation-dependent but // non-dependent qualifier. template struct A { using type = int; }; template A::type f() {} // expected-note {{'int' cannot be used prior to '::'}} int k = f(); // expected-error {{no matching}} }