On 4/21/20 9:55 AM, Patrick Palka wrote:
When building the parameter mapping for an atomic constraint,
find_template_parameters does not spot the template parameter within the
conversion-type-id of a dependent conversion operator, which later leads to an
ICE during substitution when looking up the missing template argument for this
unnoticed template parameter.

(The below testcase is a modification of the reduced testcase in the PR, adding
parens to the requirement 'e.operator c;' as a workaround for PR94645.)

Boostrapped and regtested on x86_64-pc-linux-gnu, does this look OK to commit?

OK.

gcc/cp/ChangeLog:

        PR c++/94597
        * pt.c (any_template_parm_r) <case IDENTIFIER_NODE>: New case.  If this
        is a conversion operator, visit its TREE_TYPE.

gcc/testsuite/ChangeLog:

        PR c++/94597
        * g++.dg/cpp2a/concepts-conv2.C: New test.
---
  gcc/cp/pt.c                                 |  6 ++++++
  gcc/testsuite/g++.dg/cpp2a/concepts-conv2.C | 19 +++++++++++++++++++
  2 files changed, 25 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-conv2.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cd6392aca22..2111f031d9e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10529,6 +10529,12 @@ any_template_parm_r (tree t, void *data)
        }
        break;
+ case IDENTIFIER_NODE:
+      if (IDENTIFIER_CONV_OP_P (t))
+       /* The conversion-type-id of a conversion operator may be dependent.  */
+       WALK_SUBTREE (TREE_TYPE (t));
+      break;
+
      default:
        break;
      }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-conv2.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-conv2.C
new file mode 100644
index 00000000000..abe68187cce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-conv2.C
@@ -0,0 +1,19 @@
+// PR c++/94597
+// { dg-do compile { target c++2a } }
+
+template <typename b, typename c> concept d = requires(b e) { e.operator c(); 
};
+
+template <typename f, typename g> requires(d<f, g>) bool equal(f, g);
+
+template <typename h> struct i {
+  i(h);
+  operator h();
+};
+
+static_assert(d<i<float>, float>);
+static_assert(!d<i<float>, int>);
+
+bool fun() {
+  i a(2.0f);
+  return equal(a, 3.0f);
+}


Reply via email to