aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2021-01-13 16:33:39 -0500
committerMarek Polacek <polacek@redhat.com>2021-01-22 13:02:23 -0500
commit25fc4d01a8ed1888e6a65597a3387349eb3c950c (patch)
tree99ba82b9c52ec22db47720056a90198e905c81b7 /gcc
parentbf8ee9e4eed6ba1a6d77b4cf168df480e1f954da (diff)
downloadgcc-25fc4d01a8ed1888e6a65597a3387349eb3c950c.zip
gcc-25fc4d01a8ed1888e6a65597a3387349eb3c950c.tar.gz
gcc-25fc4d01a8ed1888e6a65597a3387349eb3c950c.tar.bz2
c++: ICE when mangling operator name [PR98545]
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/mangle.c13
-rw-r--r--gcc/doc/invoke.texi3
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle76.C40
3 files changed, 52 insertions, 4 deletions
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 11eb896..0a9e5aa 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5f4a066..99d2546 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
index 0000000..fe326e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle76.C
@@ -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)();