c++: Fix wrong no post-decrement operator error in template [PR94190]
authorMarek Polacek <polacek@redhat.com>
Mon, 16 Mar 2020 14:17:11 +0000 (10:17 -0400)
committerMarek Polacek <polacek@redhat.com>
Tue, 24 Mar 2020 23:36:20 +0000 (19:36 -0400)
Now that convert_like creates an IMPLICIT_CONV_EXPR when it converts
something that involves a class in a template, we must be prepared to
handle it.  In this test, we have a class S and we're converting it
to long int& using a user-defined conversion since we're performing
-- on it.  So cp_build_unary_op/POSTDECREMENT_EXPR calls
build_expr_type_conversion which gets the IMPLICIT_CONV_EXPR.  Before
the convert_like change it got *S::operator long int &(&b) whose type
is long int but now it gets IMPLICIT_CONV_EXPR<long int&>(b) whose type
is a reference type.  But the !MAYBE_CLASS_TYPE_P switch doesn't handle
reference types and so we complain.

Fixed by calling convert_from_reference on the result of convert_like.

PR c++/94190 - wrong no post-decrement operator error in template.
* call.c (convert_like_real): Use convert_from_reference on the result.

* g++.dg/conversion/op7.C: New test.

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/conversion/op7.C [new file with mode: 0644]

index f867d0e4e1aa853eaf490658ce8f2c5ce320d7d8..4332b07cc5f771ba48bdd4ae324df57a368097bd 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-24  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/94190 - wrong no post-decrement operator error in template.
+       * call.c (convert_like_real): Use convert_from_reference on the result.
+
 2020-03-24  Jason Merrill  <jason@redhat.com>
 
        PR c++/94186
index 65a3ea35deef6f3dae357d3f81802535eb5b4a2f..bae4b2c0f5214a30e31fac9abbc38e26ad03ec0f 100644 (file)
@@ -7389,7 +7389,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
   if (processing_template_decl
       && convs->kind != ck_identity
       && (CLASS_TYPE_P (totype) || CLASS_TYPE_P (TREE_TYPE (expr))))
-    return build1 (IMPLICIT_CONV_EXPR, totype, expr);
+    {
+      expr = build1 (IMPLICIT_CONV_EXPR, totype, expr);
+      return convs->kind == ck_ref_bind ? expr : convert_from_reference (expr);
+    }
 
   switch (convs->kind)
     {
index 858ad070d6238d34babf9bfa88dd68facfa539af..bd2e45dcb2d8f417d9b95296d3558ac3ca08aa42 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-24  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/94190 - wrong no post-decrement operator error in template.
+       * g++.dg/conversion/op7.C: New test.
+
 2020-03-24  Christophe Lyon  <christophe.lyon@linaro.org>
 
        * gcc/arm/vfp-1.c: Use arm_fp__ok effective-target.
diff --git a/gcc/testsuite/g++.dg/conversion/op7.C b/gcc/testsuite/g++.dg/conversion/op7.C
new file mode 100644 (file)
index 0000000..c6401d1
--- /dev/null
@@ -0,0 +1,22 @@
+// PR c++/94190 - wrong no post-decrement operator error in template.
+
+struct S { operator long & (); } b;
+
+template<int> void
+foo ()
+{
+  b--;
+  ++b;
+  --b;
+  b++;
+  !b;
+  ~b;
+  +b;
+  -b;
+}
+
+void
+bar ()
+{
+  foo<0> ();
+}