// RUN: %clang_cc1 -std=c++2a -x c++ %s -verify
using A = int;
using identity_t = T; // expected-note 4{{template is declared here}}}
;
// expected-note@-1 2{{template is declared here}}
;
; // expected-note{{referenced member 'type' is declared here}}
// Basic unqualified and global-qualified lookups
static_assert;
static_assert;
static_assert; // expected-error{{too many template arguments for alias template 'identity_t'}}
static_assert; // expected-error{{too many template arguments for alias template 'identity_t'}}
static_assert;
static_assert;
// expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}}
static_assert;
// expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}}
static_assert;
// expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}}
static_assert;
// expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}}
// member type lookups
static_assert;
static_assert; // expected-error{{no type named 'typr' in 'identity<int>'}}
static_assert; // expected-error{{no type named 'typr' in 'identity<int>'}}
requires requires
// expected-note@-1 {{because 'typename T::type' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
// expected-note@-2 {{because 'typename T::type' would be invalid: no type named 'type' in 'C'}}
// expected-note@-3 {{because 'typename T::type' would be invalid: typename specifier refers to non-type member 'type' in 'D'}}
// expected-note@-4 {{in instantiation of template class 'invalid<D>' requested here}}
// expected-note@-5 {{in instantiation of requirement here}}
// expected-note@-6 {{while substituting template arguments into constraint expression here}}
// expected-note@-7 {{because 'typename T::type' would be invalid}}
;
using r1i1 = r1<identity<int>>;
using r1i2 = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
using r1i3 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}}
using r1i4 = r1<D>; // expected-error{{constraints not satisfied for class template 'r1' [with T = D]}}
;
// expected-error@-1 {{typename specifier refers to non-type member 'type' in 'D'}}
using r1i5 = r1<invalid<D>>;
// expected-error@-1 {{constraints not satisfied for class template 'r1' [with T = invalid<D>]}}
// expected-note@-2 {{while checking constraint satisfaction for template 'r1<invalid<D>>' required here}}
// mismatching template arguments
requires requires // expected-note{{because 'typename identity<Ts...>' would be invalid: too many template arguments for class template 'identity'}}
;
using r2i1 = r2<int>;
using r2i2 = r2<void>;
using r2i3 = r2<int, int>; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = <int, int>]}}
using r4i2 = ns2::r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int>]}}
using E = int;
requires requires // expected-error{{expected ';' at end of requirement}}
;
requires requires // expected-error{{expected ';' at end of requirement}}
;
struct chars_only ;
requires requires // expected-note{{because 'typename chars_only<T>' would be invalid: constraints not satisfied for class template 'chars_only' [with T = int]}}
;
using r6i = r6<int>; // expected-error{{constraints not satisfied for class template 'r6' [with T = int]}}
int F = 0; // expected-note 2{{variable template 'F' declared here}}
static_assert;
// expected-error@-1{{template name refers to non-type template 'F'}}
static_assert;
// expected-error@-1{{template name refers to non-type template '::F'}}
;
requires requires
// expected-note@-1{{because 'typename T::template temp<int>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}}
// expected-note@-2{{because 'typename T::template temp<int>' would be invalid: no member named 'temp' in 'D'}}
// expected-note@-3{{because 'typename T::template temp<int>' would be invalid: template name refers to non-type template 'G::template temp'}}
;
using r7i1 = r7<int>; // expected-error{{constraints not satisfied for class template 'r7' [with T = int]}}
using r7i2 = r7<D>; // expected-error{{constraints not satisfied for class template 'r7' [with T = D]}}
using r7i3 = r7<G>; // expected-error{{constraints not satisfied for class template 'r7' [with T = G]}}
;
requires requires
;
using r8i = r8<int>;
; // expected-note{{member is declared here}}
static_assert; // expected-error{{implicit instantiation of undefined member 'I<int>::incomplete'}}
requires requires // expected-note{{because 'typename I<T>::incomplete::inner' would be invalid: implicit instantiation of undefined member 'I<int>::incomplete'}}
;
using r9i = r9<int>; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}}
; // expected-note 2{{candidate found by name lookup is 'X'}}
using namespace ns3;
static_assert; // expected-error{{reference to 'X' is ambiguous}}
static_assert; // expected-error{{reference to 'X' is ambiguous}}
// expected-error@-1{{unknown type name 'inner'}}
// naming a type template specialization in a type requirement does not require
// it to be complete and should not care about partial specializations.
;
struct Z<T> ; // expected-note{{partial specialization matches [with T = int]}}
struct Z<T> ; // expected-note{{partial specialization matches [with T = int]}}
Z<int> x; // expected-error{{ambiguous partial specializations of 'Z<int>'}}
static_assert;
// C++ [expr.prim.req.type] Example
// namespace PR48656