PR 120618 gcc/cp/ChangeLog:
* constraint.cc (tsubst_compound_requirement): Return NULL_TREE when t1 is not a TEMPLATE_TYPE_PARM (tsubst_requires_expr): Propagate failure when the compound requirement has an ill-formed type-constraint gcc/testsuite/ChangeLog: * g++.dg/concepts/pr120618.C: New test. This testcase caused an ICE in mangle.cc when attempting to mangle the compound requirement `requires (!requires(T t) { { t } -> bool; })`, since write_type_constraint expects a TEMPLATE_TYPE_PARM. When instantiating the call `foo(b)`, the constraint `requires(T t) { { t } -> bool; }` seems to be cached as a boolean_false_node, so the constraints were met due to the TRUTH_NOT_EXPR even though the type-constraint was invalid. This was Andrew's hypothesis which we discussed on irc, and it seems to be correct from what I tried to do here. This patch attempts to bail out when building a call for a function with an ill-formed type-constraint in a compound requirement. Bootstrapped and tested with check-gcc-c++ on x86_64-linux-gnu (I did not see new regressions with compare_tests). Could someone help review? Thanks. Suggested-by: Andrew Pinski <quic_apin...@quicinc.com> --- gcc/cp/constraint.cc | 8 ++++++++ gcc/testsuite/g++.dg/concepts/pr120618.C | 13 +++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 gcc/testsuite/g++.dg/concepts/pr120618.C diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index cbdfafc90c0..a9f6bcc9c69 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1478,6 +1478,9 @@ tsubst_compound_requirement (tree t, tree args, sat_info info) { tree t0 = TREE_OPERAND (t, 0); tree t1 = TREE_OPERAND (t, 1); + if (t1 && TREE_CODE (t1) != TEMPLATE_TYPE_PARM) + return NULL_TREE; + tree expr = tsubst_valid_expression_requirement (t0, args, info); if (expr == error_mark_node) return error_mark_node; @@ -1744,6 +1747,11 @@ tsubst_requires_expr (tree t, tree args, sat_info info) else break; } + else if (req == NULL_TREE) + { + result = error_mark_node; + break; + } else if (processing_template_decl) result = tree_cons (NULL_TREE, req, result); } diff --git a/gcc/testsuite/g++.dg/concepts/pr120618.C b/gcc/testsuite/g++.dg/concepts/pr120618.C new file mode 100644 index 00000000000..13f390a7aa0 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr120618.C @@ -0,0 +1,13 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-fconcepts" } + +class B{}; + +template <typename T> +requires (!requires(T t) { { t } -> bool; }) // { dg-error "return-type-requirement is not a type-constraint" } +void foo(T t) {} + +int main() { + B b; + foo(b); // { dg-error "no matching function" } +} -- 2.43.0