On 1/13/21 6:39 PM, Marek Polacek wrote:
r11-6301 added some asserts in mangle.c, and now we trip over one of
them.  In particular, it's the one asserting that we didn't get
IDENTIFIER_ANY_OP_P when mangling an expression with a dependent name.

As this testcase shows, it's possible to get that, so turn the assert
into an if and write "on".  That changes the mangling in the following
way:

With this patch:

$ c++filt _ZN1i1hIJ1adS1_EEEDTcldtdefpTonclspcvT__EEEDpS2_
decltype (((*this).(operator()))((a)(), (double)(), (a)())) i::h<a, double, 
a>(a, double, a)

G++10:
$ c++filt _ZN1i1hIJ1adS1_EEEDTcldtdefpTclspcvT__EEEDpS2_
decltype (((*this).(operator()))((a)(), (double)(), (a)())) i::h<a, double, 
a>(a, double, a)

clang++/icc:
$ c++filt _ZN1i1hIJ1adS1_EEEDTclonclspcvT__EEEDpS2_
decltype ((operator())((a)(), (double)(), (a)())) i::h<a, double, a>(a, double, 
a)

I'm not sure why we differ in the "(*this)." part

Is there a PR for that?

but at least the
suffix "onclspcvT__EEEDpS2_" is the same for all three compilers.  So
I hope the following fix makes sense.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

gcc/cp/ChangeLog:

        PR c++/98545
        * mangle.c (write_expression): When the expression is a dependent name
        and an operator name, write "on" before writing its name.

gcc/testsuite/ChangeLog:

        PR c++/98545
        * g++.dg/abi/mangle76.C: New test.
---
  gcc/cp/mangle.c                     |  3 ++-
  gcc/testsuite/g++.dg/abi/mangle76.C | 39 +++++++++++++++++++++++++++++
  2 files changed, 41 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/abi/mangle76.C

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 11eb8962d28..bb3c4b76d33 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3349,7 +3349,8 @@ write_expression (tree expr)
    else if (dependent_name (expr))
      {
        tree name = dependent_name (expr);
-      gcc_assert (!IDENTIFIER_ANY_OP_P (name));
+      if (IDENTIFIER_ANY_OP_P (name))
+       write_string ("on");

Any mangling change needs to handle different -fabi-versions; see the similar code in write_member_name.

And why doesn't this go through write_member_name?

        write_unqualified_id (name);
      }
    else
diff --git a/gcc/testsuite/g++.dg/abi/mangle76.C 
b/gcc/testsuite/g++.dg/abi/mangle76.C
new file mode 100644
index 00000000000..0c2964cbecb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle76.C
@@ -0,0 +1,39 @@
+// PR c++/98545
+// { dg-do compile { target c++11 } }
+
+class a {
+public:
+  a();
+  template <typename b> a(b);
+};
+template <class = double> using c = a;
+class f {
+protected:
+  template <class d, class e> void operator()(d, double, e);
+};
+class i : f {
+public:
+  template <class... g>
+  [[gnu::used]] auto h(g...) -> decltype(operator()(g()...)) {}
+// { dg-final { scan-assembler 
"_ZN1i1hIJ1adS1_EEEDTcldtdefpTonclspcvT__EEEDpS2_" } }
+};
+template <class> class C {
+public:
+  template <class j> C(j);
+  i k() const;
+  int operator()() {
+    int l = 10;
+    c<> m, n;
+    operator()(m, l, n);
+    return 0;
+  }
+  int operator()(c<> &, c<> const &, c<> const &) const;
+  template <class d, class e> void k(d m, double gamma, e o) const {
+    k().h(m, gamma, o);
+  }
+};
+template <class r> int C<r>::operator()(c<> &, c<> const &, c<> const &) const 
{
+  [&](c<> m, double gamma, c<> o) { k(m, gamma, o); };
+  return 0;
+}
+c<> p = C<double>(p)();

base-commit: 796ead19f85372e59217c9888db688a2fe11b54f


Reply via email to