From 56e0346dcb882b07199b8b19616b52f9667e356f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 30 Oct 2019 22:01:16 -0400 Subject: [PATCH] PR c++/92268 - hard error satisfying return-type-requirement Previously we would put the template arguments for the concept-check in a TEMPLATE_ID and then also pass them to constraints_satisfied_p, which meant that we would try to normalize the concept-check with the fully instantiated arguments, leading to sadness. Simply not passing the args to constraints_satisfied_p fixes the problem. I also noticed that we weren't detecting substitution failure in the constraints, but were silently treating it as success. * constraint.cc (type_deducible_p): Check for substitution failure. (diagnose_compound_requirement): Adjust diagnostic. * pt.c (do_auto_deduction): Don't pass cargs to constraints_satisfied_p. From-SVN: r277654 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/constraint.cc | 15 +++++++++------ gcc/cp/pt.c | 2 +- gcc/testsuite/g++.dg/concepts/diagnostic1.C | 4 ++-- gcc/testsuite/g++.dg/concepts/placeholder3.C | 2 +- gcc/testsuite/g++.dg/concepts/placeholder4.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C | 2 +- .../g++.dg/cpp2a/concepts-requires6.C | 2 +- .../g++.dg/cpp2a/concepts-return-req1.C | 19 +++++++++++++++++++ 9 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index efb135e385d..585420a62c3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-10-30 Jason Merrill + + PR c++/92268 - hard error satisfying return-type-requirement + * constraint.cc (type_deducible_p): Check for substitution failure. + (diagnose_compound_requirement): Adjust diagnostic. + * pt.c (do_auto_deduction): Don't pass cargs to + constraints_satisfied_p. + 2019-10-30 Jakub Jelinek PR c++/91369 - Implement P0784R7: constexpr new diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index b8a2645d8c9..db2a30ced7c 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1822,10 +1822,7 @@ tsubst_type_requirement (tree t, tree args, subst_info info) return finish_type_requirement (EXPR_LOCATION (t), type); } -/* True if TYPE can be deduced from EXPR. - - FIXME: C++20 compound requirement constraints should be normalized and then - satisfied rather than substituted. */ +/* True if TYPE can be deduced from EXPR. */ static bool type_deducible_p (tree expr, tree type, tree placeholder, tree args, @@ -1839,12 +1836,17 @@ type_deducible_p (tree expr, tree type, tree placeholder, tree args, substitutes args into any template parameters in the trailing result type. */ tree saved_constr = PLACEHOLDER_TYPE_CONSTRAINTS (placeholder); - PLACEHOLDER_TYPE_CONSTRAINTS (placeholder) + tree subst_constr = tsubst_constraint (saved_constr, args, info.complain | tf_partial, info.in_decl); + if (subst_constr == error_mark_node) + return false; + + PLACEHOLDER_TYPE_CONSTRAINTS (placeholder) = subst_constr; + /* Temporarily unlink the canonical type. */ tree saved_type = TYPE_CANONICAL (placeholder); TYPE_CANONICAL (placeholder) = NULL_TREE; @@ -3139,7 +3141,8 @@ diagnose_compound_requirement (tree req, tree args, tree in_decl) if (!type_deducible_p (expr, type, placeholder, args, quiet)) { tree orig_expr = TREE_OPERAND (req, 0); - inform (loc, "type deduction from %qE failed", orig_expr); + inform (loc, "%qE does not satisfy return-type-requirement", + orig_expr); /* Further explain the reason for the error. */ type_deducible_p (expr, type, placeholder, args, noisy); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c5675dd8e3f..414140ade6c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -28138,7 +28138,7 @@ do_auto_deduction (tree type, tree init, tree auto_node, /* Rebuild the check using the deduced arguments. */ check = build_concept_check (cdecl, cargs, tf_none); - if (!constraints_satisfied_p (check, cargs)) + if (!constraints_satisfied_p (check)) { if (complain & tf_warning_or_error) { diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic1.C b/gcc/testsuite/g++.dg/concepts/diagnostic1.C index ced56d400ba..7da08db2792 100644 --- a/gcc/testsuite/g++.dg/concepts/diagnostic1.C +++ b/gcc/testsuite/g++.dg/concepts/diagnostic1.C @@ -8,12 +8,12 @@ concept bool SameAs = __is_same_as(T, U); template concept bool R1 = requires (T& t) { // { dg-message "in requirements" } { t.begin() } -> T; // { dg-error "no match" } - { t.end() } -> SameAs; // { dg-error "does not satisfy" } + { t.end() } -> SameAs; // { dg-message "does not satisfy" } }; template concept bool R2 = requires (T& t) { // { dg-message "in requirements" } - { t.end() } -> SameAs; // { dg-error "does not satisfy" } + { t.end() } -> SameAs; // { dg-message "does not satisfy" } }; struct foo { diff --git a/gcc/testsuite/g++.dg/concepts/placeholder3.C b/gcc/testsuite/g++.dg/concepts/placeholder3.C index 4f8600bd07f..d90e5cfb02f 100644 --- a/gcc/testsuite/g++.dg/concepts/placeholder3.C +++ b/gcc/testsuite/g++.dg/concepts/placeholder3.C @@ -8,7 +8,7 @@ concept bool Same = __is_same_as(T, U); template concept bool C = requires { // { dg-message "in requirements" } - { 0 } -> Same; // { dg-error "does not satisfy" } + { 0 } -> Same; // { dg-message "does not satisfy" } }; template diff --git a/gcc/testsuite/g++.dg/concepts/placeholder4.C b/gcc/testsuite/g++.dg/concepts/placeholder4.C index 2b5afbbc6f2..ab9d8e632af 100644 --- a/gcc/testsuite/g++.dg/concepts/placeholder4.C +++ b/gcc/testsuite/g++.dg/concepts/placeholder4.C @@ -8,7 +8,7 @@ concept bool Same = __is_same_as(T, U); template concept bool C = requires { // { dg-message "in requirements" } - { 0 } -> Same; // { dg-error "does not satisfy" } + { 0 } -> Same; // { dg-message "does not satisfy" } }; template diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C index f76f2e3fc86..264b873c7f4 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C @@ -12,7 +12,7 @@ concept C0 = requires (auto x) { // { dg-error "placeholder type" } template concept C1 = requires (C1 auto x) { // { dg-error "not been declared|placeholder|two or more|in requirements" } x; // { dg-error "not declared" } - { x } -> c; // { dg-error "not declared|does not satisfy" } + { x } -> c; // { dg-message "not declared|does not satisfy" } }; template diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires6.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires6.C index 20df78bebf1..065876e94e4 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires6.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires6.C @@ -10,7 +10,7 @@ concept SameAs = __is_same_as(T, U); template concept C1 = requires(T t) { // { dg-message "in requirements" } { t } -> SameAs; // NOTE: t deduced as decltype((t)) - // { dg-error "does not satisfy placeholder constraints" "" { target *-*-* } .-1 } + // { dg-message "does not satisfy" "" { target *-*-* } .-1 } }; template diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C new file mode 100644 index 00000000000..1d005f059d0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C @@ -0,0 +1,19 @@ +// PR c++/92268 +// { dg-do compile { target c++2a } } + +template concept Two = true; +template concept One = Two; +template concept Zero = requires + { + { T() } -> One; + }; + +template +void f() requires Zero; +template +int f(...); + +int main() +{ + f(); +} -- 2.30.2