aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-06-01 21:37:04 -0400
committerPatrick Palka <ppalka@redhat.com>2020-06-01 21:37:04 -0400
commitc2449995ca36ea955e3c6d4ee7f0d401b512c897 (patch)
tree5e828f15585a6625a8755ae0e91d6c2ffed80daf
parent4a9aa9dec7fc413654807890061a4d7df8a1c5e7 (diff)
downloadgcc-c2449995ca36ea955e3c6d4ee7f0d401b512c897.zip
gcc-c2449995ca36ea955e3c6d4ee7f0d401b512c897.tar.gz
gcc-c2449995ca36ea955e3c6d4ee7f0d401b512c897.tar.bz2
c++: constrained lambda inside template [PR92633]
When regenerating a constrained lambda during instantiation of an enclosing template, we are forgetting to substitute into the lambda's constraints. Fix this by substituting through the constraints during tsubst_lambda_expr. gcc/cp/ChangeLog: PR c++/92633 PR c++/92838 * pt.c (tsubst_function_decl): Don't do set_constraints when regenerating a lambda. (tsubst_lambda_expr): Substitute into the lambda's constraints and do set_constraints here. gcc/testsuite/ChangeLog: PR c++/92633 PR c++/92838 * g++.dg/cpp2a/concepts-lambda11.C: New test. * g++.dg/cpp2a/concepts-lambda12.C: New test.
-rw-r--r--gcc/cp/pt.c16
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-lambda11.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-lambda12.C15
3 files changed, 47 insertions, 1 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index df647af..907ca87 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13854,7 +13854,10 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
don't substitute through the constraints; that's only done when
they are checked. */
if (tree ci = get_constraints (t))
- set_constraints (r, ci);
+ /* Unless we're regenerating a lambda, in which case we'll set the
+ lambda's constraints in tsubst_lambda_expr. */
+ if (!lambda_fntype)
+ set_constraints (r, ci);
if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
SET_DECL_FRIEND_CONTEXT (r,
@@ -19029,6 +19032,17 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
finish_member_declaration (fn);
}
+ if (tree ci = get_constraints (oldfn))
+ {
+ /* Substitute into the lambda's constraints. */
+ if (oldtmpl)
+ ++processing_template_decl;
+ ci = tsubst_constraint_info (ci, args, complain, in_decl);
+ if (oldtmpl)
+ --processing_template_decl;
+ set_constraints (fn, ci);
+ }
+
/* Let finish_function set this. */
DECL_DECLARED_CONSTEXPR_P (fn) = false;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda11.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda11.C
new file mode 100644
index 0000000..dd9cd4e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda11.C
@@ -0,0 +1,17 @@
+// PR c++/92838
+// { dg-do compile { target c++20 } }
+
+template<int N>
+auto foo()
+{
+ [] () requires (N != 0) { }(); // { dg-error "no match" }
+ [] () requires (N == 0) { }();
+
+ [] <int M=1> () requires (N == M) { }(); // { dg-error "no match" }
+ [] <int M=1> () requires (N != M) { }();
+}
+
+void bar()
+{
+ foo<0>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda12.C b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda12.C
new file mode 100644
index 0000000..2bc9fd0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda12.C
@@ -0,0 +1,15 @@
+// PR c++/92633
+// { dg-do compile { target c++20 } }
+
+template<class A, class B>
+concept different_than = !__is_same_as(A, B);
+
+template<class B>
+auto diff(B) {
+ return [](different_than<B> auto a) {};
+}
+
+int main() {
+ diff(42)("");
+ diff(42)(42); // { dg-error "no match" }
+}