diff options
Diffstat (limited to 'clang/test/SemaCXX/cxx2c-template-template-param.cpp')
-rw-r--r-- | clang/test/SemaCXX/cxx2c-template-template-param.cpp | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/cxx2c-template-template-param.cpp b/clang/test/SemaCXX/cxx2c-template-template-param.cpp new file mode 100644 index 0000000..ed55a059 --- /dev/null +++ b/clang/test/SemaCXX/cxx2c-template-template-param.cpp @@ -0,0 +1,352 @@ +// RUN: %clang_cc1 -std=c++2c -verify %s + +namespace Errors { + +template <template<typename T> auto> +struct S1; +template <template<auto T> auto> +struct S2; +template <template<typename T> concept> +struct S3; +template <template<auto T> concept> +struct S4; +int a; + +template <typename T> +concept C = true; // expected-note 2{{template argument refers to a concept 'C', here}} +template <typename T> +auto Var = 0; // expected-note 2{{template argument refers to a variable template 'Var', here}} + +S1<1> t1; // expected-error {{template argument for template template parameter must be a variable template}} +S1<a> t2; // expected-error {{template argument for template template parameter must be a variable template}} +S1<int> t3; // expected-error {{template argument for template template parameter must be a variable template}} +S1<C> t4; // expected-error {{template argument does not refer to a variable template, or template template parameter}} +S2<1> t5; // expected-error {{template argument for template template parameter must be a variable template}} +S2<a> t6; // expected-error {{template argument for template template parameter must be a variable template}} +S2<int> t7; // expected-error {{template argument for template template parameter must be a variable template}} +S2<C> t8; // expected-error {{template argument does not refer to a variable template, or template template parameter}} +S3<1> t9; // expected-error {{template argument for template template parameter must be a concept}} +S3<a> t10; // expected-error {{template argument for template template parameter must be a concept}} +S3<int> t11; // expected-error {{template argument for template template parameter must be a concept}} +S3<Var> t12; // expected-error {{template argument does not refer to a concept, or template template parameter}} +S4<1> t13; // expected-error {{template argument for template template parameter must be a concept}} +S4<a> t14; // expected-error {{template argument for template template parameter must be a concept}} +S4<int> t15; // expected-error {{template argument for template template parameter must be a concept}} +S4<Var> t16; // expected-error {{template argument does not refer to a concept, or template template parameter}} + +} + +template <template<typename T> auto V> // expected-note {{previous template template parameter is here}} \ + // expected-error{{template argument for non-type template parameter must be an expression}} +struct S1 { + static_assert(V<int> == 42); + static_assert(V<const int> == 84); + static_assert(V<double> == 0); +}; +template <template<auto T> auto V> // expected-error {{template argument for template type parameter must be a type}} \ + // expected-note {{previous template template parameter is here}} +struct S2 { + static_assert(V<0> == 1); + static_assert(V<1> == 0); +}; +template <template<typename T> concept C > // expected-error {{template argument for non-type template parameter must be an expression}} \ + // expected-note {{previous template template parameter is here}} +struct S3 { + static_assert(C<int>); +}; +template <template<auto> concept C> // expected-error {{template argument for template type parameter must be a type}} \ + // expected-note {{previous template template parameter is here}} +struct S4 { + static_assert(C<0>); +}; + +template <typename T> // expected-note {{template parameter is declared here}} +concept C = true; + +template <auto I> // expected-note {{template parameter is declared here}} +concept CI = true; + +template <typename T> // expected-note {{template parameter is declared here}} +constexpr auto Var = 42; +template <typename T> +constexpr auto Var<const T> = 84; +template <> +constexpr auto Var<double> = 0; + +template <auto N> // expected-note {{template parameter is declared here}} +constexpr auto Var2 = 0; +template <auto N> +requires (N%2 == 0) +constexpr auto Var2<N> = 1; + +void test () { + S1<Var2> sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}} + S2<Var> sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}} + S1<Var> s1; + S2<Var2> s2; + S3<C> s3; + S4<C> sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}} + S4<CI> s4; + S3<CI> sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}} +} + + +namespace template_type_constraints { + + +template <typename T> +concept Unary = true; +template <typename T, typename = int> +concept BinaryDefaulted = true; + +template <typename T> +concept UnaryFalse = false; // expected-note 3{{because 'false' evaluated to false}} +template <typename T, typename = int> +concept BinaryDefaultedFalse = false; + +template <template <typename...> concept C, typename T> +struct S { + template <C TT> // expected-note {{because 'int' does not satisfy 'UnaryFalse'}} + void f(TT); // expected-note {{ignored}} + void g(C auto); // expected-note {{ignored}} \ + // expected-note {{because 'int' does not satisfy 'UnaryFalse'}} + + auto h() -> C auto { // expected-error {{deduced type 'int' does not satisfy 'UnaryFalse'}} + return 0; + }; + + void test() { + C auto a = 0; + } +}; + +template <template <typename...> concept C, typename T> +struct SArg { + template <C<int> TT> + void f(TT); + void g(C<int> auto); + + auto h() -> C<int> auto { + return 0; + }; + void test() { + C<int> auto a = 0; + } +}; + +void test() { + S<Unary, int> s; + s.f(0); + s.g(0); + s.h(); + S<BinaryDefaulted, int> s2; + s2.f(0); + s2.g(0); + s2.h(); + + SArg<BinaryDefaulted, int> s3; + s3.f(0); + s3.g(0); + s3.h(); +} + +void test_errors() { + S<UnaryFalse, int> s; + s.f(0); // expected-error {{no matching member function for call to 'f'}} + s.g(0); // expected-error {{no matching member function for call to 'g'}} + s.h(); // expected-note {{in instantiation of member function 'template_type_constraints::S<template_type_constraints::UnaryFalse, int>::h'}} +} + +} + +template <typename T> +concept Unary = true; +template <typename T, typename = int> +concept BinaryDefaulted = true; + +template <typename T> +concept UnaryFalse = false; // expected-note 3{{because 'false' evaluated to false}} +template <typename T, typename = int> +concept BinaryDefaultedFalse = false; + +template <template <typename...> concept C, typename T> +struct S { + template <C TT> // expected-note {{because 'int' does not satisfy 'UnaryFalse'}} + void f(TT); // expected-note {{ignored}} + void g(C auto); // expected-note {{ignored}} \ + // expected-note {{because 'int' does not satisfy 'UnaryFalse'}} + + auto h() -> C auto { // expected-error {{deduced type 'int' does not satisfy 'UnaryFalse'}} + return 0; + }; + + void test() { + C auto a = 0; + } +}; + +template <template <typename...> concept C, typename T> +struct SArg { + template <C<int> TT> + void f(TT); + void g(C<int> auto); + + auto h() -> C<int> auto { + return 0; + }; + void test() { + C<int> auto a = 0; + } +}; + +void test_args() { + S<Unary, int> s; + s.f(0); + s.g(0); + s.h(); + S<BinaryDefaulted, int> s2; + s2.f(0); + s2.g(0); + s2.h(); + + SArg<BinaryDefaulted, int> s3; + s3.f(0); + s3.g(0); + s3.h(); +} + +void test_errors() { + S<UnaryFalse, int> s; + s.f(0); // expected-error {{no matching member function for call to 'f'}} + s.g(0); // expected-error {{no matching member function for call to 'g'}} + s.h(); // expected-note {{in instantiation of member function 'S<UnaryFalse, int>::h'}} +} + +namespace non_type { + +template <auto> +concept Unary = true; + +template <template <auto> concept C> +struct S { + template <C Foo> // expected-error {{concept named in type constraint is not a type concept}} + void f(); + // FIXME, bad diagnostic + void g(C auto); // expected-error{{concept named in type constraint is not a type concept}} + auto h() -> C auto { // expected-error{{concept named in type constraint is not a type concept}} + } + void i() { + C auto a = 0; // expected-error{{concept named in type constraint is not a type concept}} + } +}; + +} + +namespace default_args { + +template <typename T> +concept Concept = false; // expected-note 2{{template argument refers to a concept 'Concept', here}} \ + // expected-note 2{{because 'false' evaluated to false}} + +template <typename T> +constexpr auto Var = false; // expected-note 2{{template argument refers to a variable template 'Var', here}} + +template <typename T> +struct Type; // expected-note 2{{template argument refers to a class template 'Type', here}} + + +template <template <typename> auto = Concept> // expected-error {{template argument does not refer to a variable template, or template template parameter}} +struct E1; + +template <template <typename> auto = Type> // expected-error {{template argument does not refer to a variable template, or template template parameter}} +struct E2; + +template <template <typename> typename = Concept> // expected-error {{template argument does not refer to a class or alias template, or template template parameter}} +struct E3; + +template <template <typename> typename = Var> // expected-error {{template argument does not refer to a class or alias template, or template template parameter}} +struct E4; + +template <template <typename> concept = Var> // expected-error {{template argument does not refer to a concept, or template template parameter}} +struct E4; + +template <template <typename> concept = Type> // expected-error {{template argument does not refer to a concept, or template template parameter}} +struct E4; + +template < + template <typename> concept TConcept, // expected-note 2{{template argument refers to a concept 'TConcept', here}} + template <typename> auto TVar, // expected-note 2{{template argument refers to a variable template 'TVar', here}} + template <typename> typename TType // expected-note 2{{template argument refers to a class template 'TType', here}} +> +struct Nested { + template <template <typename> auto = TConcept> // expected-error {{template argument does not refer to a variable template, or template template parameter}} + struct E1; + + template <template <typename> auto = TType> // expected-error {{template argument does not refer to a variable template, or template template parameter}} + struct E2; + + template <template <typename> typename = TConcept> // expected-error {{template argument does not refer to a class or alias template, or template template parameter}} + struct E3; + + template <template <typename> typename = TVar> // expected-error {{template argument does not refer to a class or alias template, or template template parameter}} + struct E4; + + template <template <typename> concept = TVar> // expected-error {{template argument does not refer to a concept, or template template parameter}} + struct E4; + + template <template <typename> concept = TType> // expected-error {{template argument does not refer to a concept, or template template parameter}} + struct E4; +}; + + +template <template <typename> concept C = Concept> +struct TestDefaultConcept { + template <template <typename> concept CC = C> + void f() { + static_assert(C<int>); // expected-error {{static assertion failed}} \ + // expected-note {{because 'int' does not satisfy 'Concept'}} + static_assert(CC<int>); // expected-error {{static assertion failed}} \ + // expected-note {{because 'int' does not satisfy 'Concept'}} + } +}; +void do_test_concept() { + TestDefaultConcept<>{}.f(); // expected-note {{in instantiation}} +} + +template <template <typename> auto V = Var> +struct TestDefaultVar { + template <template <typename> auto VV = V> + void f() { + static_assert(V<int>); // expected-error {{static assertion failed}} + static_assert(VV<int>); // expected-error {{static assertion failed}} + } +}; +void do_test_var() { + TestDefaultVar<>{}.f(); // expected-note {{in instantiation}} +} + +} + +namespace TTPDependence { +template <template <typename... > concept C> +concept A = C<>; +template <template <typename... > concept C> +concept B = C<int>; + +template <template <typename... > auto Var> +concept C = Var<>; +template <template <typename... > auto Var> +concept D = Var<int>; + +} + +namespace InvalidName { +template <typename T, template <typename> concept C> +concept A = C<T>; // expected-note {{here}} + +template <A<concept missing<int>> T> // expected-error {{expected expression}} \ + // expected-error {{too few template arguments for concept 'A'}} \ + // expected-error {{unknown type name 'T'}} \ + // expected-error {{expected unqualified-id}} +auto f(); +} |