aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C')
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C71
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C
new file mode 100644
index 00000000000..f1603af8015
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C
@@ -0,0 +1,71 @@
+// { dg-do compile { target c++2a } }
+
+template<typename T>
+concept Class = __is_class(T);
+
+// Allow a requires-expression with no parms.
+template<typename T>
+concept C = requires { typename T::type; };
+
+void f1(int a) requires true; // OK
+auto f2(int a) -> bool requires true; // OK
+auto f3(int a) requires true -> bool; // { dg-error "" } requires-clause precedes trailing-return-type
+typedef void fn_t() requires true; // { dg-error "typedef" }
+void (*pf)() requires true; // { dg-error "non-function" }
+void (*fn(int))() requires false; // { dg-error "return type" }
+void g(int (*)() requires true); // { dg-error "parameter|non-function" }
+auto* p = new (void(*)(char) requires true); // { dg-error "type-id" }
+void f4(auto a) requires Class<decltype(a)> { }
+void f5(auto a) requires requires (decltype(a) x) { -x; } { } // { dg-message "in requirements" }
+
+struct Test {
+ void f(auto a) requires Class<decltype(a)>;
+} test;
+
+void driver_1() {
+ struct S { } s;
+ f4(s);
+ f5(0);
+ f5((void*)0); // { dg-error "cannot call" }
+ test.f(s);
+}
+
+void Test::f(auto a) requires Class<decltype(a)> { }
+
+template<bool B> requires B struct S0; // OK
+
+template<int N> requires N struct S1 { }; // { dg-error "does not have type" }
+S1<1> x0; // { dg-error "template constraint failure|does not have type" }
+
+template<int N> requires N == 0 struct S2 { }; // { dg-error "does not have type|must be enclosed" }
+
+template<int N> requires (N == 0) struct S3 { }; // OK
+
+template<typename T, T X> requires X struct S4 { }; // OK
+S4<int, 0> x1; // { dg-error "template constraint failure|does not have type" }
+S4<bool, true> x2; // OK
+S4<bool, false> x3; // { dg-error "template constraint failure" }
+
+
+// req11.C
+template<typename T>
+concept Streamable = requires (T t) { t; };
+
+template<typename T>
+concept Range = requires (T t) { t; };
+
+// FIXME: There are two syntax errors here when there should be
+// just one.Note that !Range<T> is not a primary-expression and needs to
+// be wrapped in parens to be syntactically valid.
+template<class T>
+ requires Streamable<T> && !Range<T> // { dg-error "must be enclosed" }
+void print1(const T& x) { }
+
+template<class T>
+ requires Streamable<T> && (!Range<T>)
+void print2(const T& x) { }
+
+void driver_3()
+{
+ print2("hello"); // { dg-error "cannot call" }
+}