@@ -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);
}
new file mode 100644
@@ -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;
@@ -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" }
}
@@ -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;
}
@@ -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" }