diff options
author | Jason Merrill <jason@redhat.com> | 2019-11-06 15:20:00 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-11-06 15:20:00 -0500 |
commit | babd71c168ad447d2d11886683dea263ba1d814d (patch) | |
tree | 890e5bf75cb35d71ba7b7d79a17c57c0156edc10 /gcc | |
parent | 5d24b4f2dad8883db004481ebd633a0bf8d4f8e9 (diff) | |
download | gcc-babd71c168ad447d2d11886683dea263ba1d814d.zip gcc-babd71c168ad447d2d11886683dea263ba1d814d.tar.gz gcc-babd71c168ad447d2d11886683dea263ba1d814d.tar.bz2 |
C++20 NB CA378 - Remove constrained non-template functions.
No real use cases have ever arisen for constraints on non-templated
functions, and handling of them has never been entirely clear, so the
committee agreed to accept this national body comment proposing that we
remove them.
* decl.c (grokfndecl): Reject constraints on non-templated function.
From-SVN: r277891
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-friend4.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-lambda2.C | 26 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C | 4 |
6 files changed, 46 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e60a45b..c185af4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2019-11-06 Jason Merrill <jason@redhat.com> + + C++20 NB CA378 - Remove constrained non-template functions. + * decl.c (grokfndecl): Reject constraints on non-templated function. + 2019-11-06 Matthias Kretz <m.kretz@gsi.de> * parser.c (cp_parser_operator): Parse operator?: as an diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 3bfcfb2..5c5a85e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9262,7 +9262,9 @@ grokfndecl (tree ctype, if (flag_concepts) { tree tmpl_reqs = NULL_TREE; - if (processing_template_decl > template_class_depth (ctype)) + tree ctx = friendp ? current_class_type : ctype; + bool memtmpl = (processing_template_decl > template_class_depth (ctx)); + if (memtmpl) tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); tree ci = build_constraints (tmpl_reqs, decl_reqs); if (concept_p && ci) @@ -9270,6 +9272,14 @@ grokfndecl (tree ctype, error_at (location, "a function concept cannot be constrained"); ci = NULL_TREE; } + /* C++20 CA378: Remove non-templated constrained functions. */ + if (ci && !flag_concepts_ts + && (!processing_template_decl + || (friendp && !memtmpl && !funcdef_flag))) + { + error_at (location, "constraints on a non-templated function"); + ci = NULL_TREE; + } set_constraints (decl, ci); } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend4.C new file mode 100644 index 0000000..88f9fe8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend4.C @@ -0,0 +1,13 @@ +// C++20 NB comment US115 +// { dg-do compile { target c++2a } } + +template <class T> concept Any = true; + +template <class T> +struct A +{ + friend void f() requires Any<T> { } // OK + friend void g() requires Any<T>; // { dg-error "" } +}; + +A<int> a; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda2.C index ffad95c..a7419d6 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda2.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda2.C @@ -60,19 +60,19 @@ void test0() auto g0 = []<False T>(T t) { return t; }; auto g1 = []<typename T> requires False<T> (T t) { return t; }; auto g2 = []<typename T>(T t) requires False<decltype(t)> { return t; }; - auto g3 = [](int t) requires False<decltype(t)> { return t; }; + auto g3 = [](int t) requires False<decltype(t)> { return t; }; // { dg-error "non-templated" } auto g4 = [](False auto t) { return t; }; auto g5 = [](auto t) requires False<decltype(t)> { return t; }; - auto g6 = [](int t) requires False<int> { return t; }; - auto g7 = [](int t) requires false { return t; }; + auto g6 = [](int t) requires False<int> { return t; }; // { dg-error "non-templated" } + auto g7 = [](int t) requires false { return t; }; // { dg-error "non-templated" } g0(0); // { dg-error "no match" } g1(0); // { dg-error "no match" } g2(0); // { dg-error "no match" } - g3(0); // { dg-error "no match" } + g3(0); g4(0); // { dg-error "no match" } g5(0); // { dg-error "no match" } - g6(0); // { dg-error "no match" } - g7(0); // { dg-error "no match" } + g6(0); + g7(0); } void test1() @@ -81,19 +81,19 @@ void test1() auto g0 = [&]<False T>(T t) { return t; }; auto g1 = [&]<typename T> requires False<T> (T t) { return t; }; auto g2 = [&]<typename T>(T t) requires False<decltype(t)> { return t; }; - auto g3 = [&](int t) requires False<decltype(t)> { return t; }; + auto g3 = [&](int t) requires False<decltype(t)> { return t; }; // { dg-error "non-templated" } auto g4 = [&](False auto t) { return t; }; auto g5 = [&](auto t) requires False<decltype(t)> { return t; }; - auto g6 = [&](int t) requires False<int> { return t; }; - auto g7 = [&](int t) requires false { return t; }; + auto g6 = [&](int t) requires False<int> { return t; }; // { dg-error "non-templated" } + auto g7 = [&](int t) requires false { return t; }; // { dg-error "non-templated" } g0(0); // { dg-error "no match" } g1(0); // { dg-error "no match" } g2(0); // { dg-error "no match" } - g3(0); // { dg-error "no match" } + g3(0); g4(0); // { dg-error "no match" } g5(0); // { dg-error "no match" } - g6(0); // { dg-error "no match" } - g7(0); // { dg-error "no match" } + g6(0); + g7(0); } void test2() @@ -147,7 +147,7 @@ using Func = int(*)(int); void test6() { - Func f1 = [](int a) requires false { return a; }; // { dg-error "cannot convert" } + Func f1 = [](int a) requires false { return a; }; // { dg-error "non-templated" } Func f2 = [](auto a) requires false { return a; }; // { dg-error "cannot convert" } } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C index 7e668ff..96da785 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda3.C @@ -34,7 +34,7 @@ int main(int, char**) auto z = []<typename T, int N = 5>(T t) requires (N < 4) { return t; }; z.operator()<int, 3>(5); - [](int t) requires true { return t; }(5); + [](auto t) requires true { return t; }(5); [](C1 auto t) { return t; }(5); auto a0 = [](IsNotLarge auto a) { return [](auto b){ return b; }; }; @@ -57,7 +57,7 @@ int main(int, char**) foo2.b<int>()(5); foo2.b<long long>()(5); - Func m1 = [](int a) -> int requires true { return a; }; + Func m1 = [](auto a) -> int requires true { return a; }; return 0; } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C index 0c26516..62cc21d 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires1.C @@ -7,8 +7,8 @@ concept Class = __is_class(T); template<typename T> concept C = requires { typename T::type; }; -void f1(int a) requires true; // OK -auto f2(int a) -> bool requires true; // OK +void f1(int a) requires true; // { dg-error "non-templated" } +auto f2(int a) -> bool requires true; // { dg-error "non-templated" } 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" } |