c++: ICE when mangling operator name [PR98545]
authorMarek Polacek <polacek@redhat.com>
Wed, 13 Jan 2021 21:33:39 +0000 (16:33 -0500)
committerMarek Polacek <polacek@redhat.com>
Fri, 22 Jan 2021 18:02:23 +0000 (13:02 -0500)
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)

This is now tracked in PR98756.

gcc/cp/ChangeLog:

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

gcc/ChangeLog:

PR c++/98545
* doc/invoke.texi: Update C++ ABI Version 15 description.

gcc/testsuite/ChangeLog:

PR c++/98545
* g++.dg/abi/mangle76.C: New test.

gcc/cp/mangle.c
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/abi/mangle76.C [new file with mode: 0644]

index 11eb8962d2848765e482fe5054e1f0e7c97bd243..0a9e5aa79a027b421a411ffa655a51d4390837cd 100644 (file)
@@ -2868,9 +2868,10 @@ write_member_name (tree member)
 {
   if (identifier_p (member))
     {
-      if (abi_version_at_least (11) && IDENTIFIER_ANY_OP_P (member))
+      if (IDENTIFIER_ANY_OP_P (member))
        {
-         write_string ("on");
+         if (abi_version_at_least (11))
+           write_string ("on");
          if (abi_warn_or_compat_version_crosses (11))
            G.need_abi_warning = 1;
        }
@@ -3349,7 +3350,13 @@ 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))
+       {
+         if (abi_version_at_least (15))
+           write_string ("on");
+         if (abi_warn_or_compat_version_crosses (15))
+           G.need_abi_warning = 1;
+       }
       write_unqualified_id (name);
     }
   else
index 5f4a06625eb98ebbbb70a946dc2591f2f250f8f0..99d25462e488eecf1088e98fbe2eff0e03b1e8e0 100644 (file)
@@ -2837,7 +2837,8 @@ Version 14, which first appeared in G++ 10, corrects the mangling of
 the nullptr expression.
 
 Version 15, which first appeared in G++ 11, changes the mangling of
-@code{__alignof__} to be distinct from that of @code{alignof}.
+@code{__alignof__} to be distinct from that of @code{alignof}, and
+dependent operator names.
 
 See also @option{-Wabi}.
 
diff --git a/gcc/testsuite/g++.dg/abi/mangle76.C b/gcc/testsuite/g++.dg/abi/mangle76.C
new file mode 100644 (file)
index 0000000..fe326e6
--- /dev/null
@@ -0,0 +1,40 @@
+// PR c++/98545
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wabi=14" }
+
+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-warning "mangled name" }
+// { 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)();