aboutsummaryrefslogtreecommitdiff
path: root/clang/test/SemaCXX/cxx2c-template-template-param.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/SemaCXX/cxx2c-template-template-param.cpp')
-rw-r--r--clang/test/SemaCXX/cxx2c-template-template-param.cpp352
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();
+}