public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug other/59195] New: C++ demangler handles conversion operator incorrectly
@ 2013-11-19 18:53 ccoutant at gcc dot gnu.org
2013-11-19 18:56 ` [Bug other/59195] " ccoutant at gcc dot gnu.org
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: ccoutant at gcc dot gnu.org @ 2013-11-19 18:53 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195
Bug ID: 59195
Summary: C++ demangler handles conversion operator incorrectly
Product: gcc
Version: 4.9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: other
Assignee: unassigned at gcc dot gnu.org
Reporter: ccoutant at gcc dot gnu.org
Consider this simple source:
struct C {
C(int i_) : i(i_) { }
int i;
};
struct A {
A() : i(0) { }
template <typename U>
explicit operator U();
int i;
};
void foo()
{
A ai;
C c = (C)ai;
}
The conversion operator in A mangles to "_ZN1AcvT_I1CEEv", which
demangles to:
A::operator C<C>()
(I think this would be better as "A::operator C()", but let's
leave that aside for now.)
That looks OK, but not if you dig deeper. The demangler is
parsing this name as follows:
typed name
qualified name
name 'A'
cast
template
template parameter 0
template argument list
name 'C'
function type
argument list
A::operator C<C>()
It's parsing the "T_" as a <template-template-param>, not a
<template-param>. It should really be parsing it as:
typed name
template
qualified name
name 'A'
cast
template parameter 0
template argument list
name 'C'
function type
argument list
A::operator C<C>()
The template argument list actually belongs with the
<qualified-name>, not with the template parameter.
The basic problem is an ambiguity in the grammar for mangled
names. Consider the following two derivations:
(1) <nested-name>
-> <template-prefix> <template-args>
-> <prefix> <template-unqualified-name> <template-args>
-> <unqualified-name> <template-unqualified-name>
<template-args>
-> <source-name> <template-unqualified-name> <template-args>
-> <source-name> <operator-name> <template-args>
-> <source-name> cv <type> <template-args>
-> <source-name> cv <template-template-param>
<template-args> <template-args>
(2) <nested-name>
-> <template-prefix> <template-args>
-> <prefix> <template-unqualified-name> <template-args>
-> <unqualified-name> <template-unqualified-name>
<template-args>
-> <source-name> <template-unqualified-name> <template-args>
-> <source-name> <operator-name> <template-args>
-> <source-name> cv <type> <template-args>
-> <source-name> cv <template-param> <template-args>
When you get to the "T_", there's no way to know if it's a
<template-param> or a <template-template-param>. The parser in
cp-demangle.c, in cplus_demangle_type, looks ahead to
disambiguate the two. If it sees an 'I', it assumes that it's a
<template-template-param>, and it greedily consumes the
<template-args>.
In this particular case, it's wrong, but it gets the right answer
because of a hack in d_print_cast, which takes the template
arguments under the cast operator, and places them in scope
before resolving the "T_" reference.
It doesn't take much to break that hack, though. Let's throw in a
pointer:
struct C {
C(int i_) : i(i_) { }
int i;
};
struct A {
A() : i(0) { }
template <typename U>
explicit operator U*();
int i;
};
void foo()
{
A ai;
C* c = (C*)ai;
}
Now we get the mangled name "_ZN1AcvPT_I1CEEv", which the
demangler fails on:
typed name
qualified name
name 'A'
cast
pointer
template
template parameter 0
template argument list
name 'C'
function type
argument list
Failed: _ZN1AcvPT_I1CEEv
This name ought to be parsed as follows:
typed name
template
qualified name
name 'A'
cast
pointer
template parameter 0
template argument list
name 'C'
function type
argument list
A::operator C*<C>()
(This incorrect parsing can also lead to some other subtle types
of failures, because substitutions can be numbered in the wrong
order. See the long example that started me on this investigation
at the end.)
Now let's add a real template template parameter:
template <typename T>
struct C {
C(T i_) : i(i_) { }
T i;
};
struct A {
A() : i(0) { }
template <template<typename U> class V>
operator V<int>();
int i;
};
void foo()
{
A ai;
C<int> c = (C<int>)ai;
}
The conversion operator is now "_ZN1AcvT_IiEI1CEEv", and the
demangler gives us this:
typed name
template
qualified name
name 'A'
cast
template
template parameter 0
template argument list
builtin type int
template argument list
name 'C'
function type
argument list
A::operator int<int><C>()
The derivation is actually correct this time, because we really
do have a <template-template-param>, but the hack in d_print_cast
causes it to substitute the wrong type for "T_".
I'm pretty sure that the ambiguity can be resolved by context.
Note that if we have a <template-template-param>, the
<template-args> that go with it are followed by another set of
<template-args> that go with the <template-prefix> in the second
step of the derivation. (This is only true if we're parsing a
conversion operator that derives from <nested-name>; if it's a
conversion operator that's part of an <expression>, the presence
of an 'I' should always indicate that we're looking at a
<template-template-param>.)
I've got a patch that solves this with a little backtracking. If
we're in a conversion operator that's not part of an
<expression>, and we see an 'I', it checkpoints the d_info
structure, does a trial parse of <template-args>, then looks for
another 'I'. If there isn't one, it backtracks and returns a
<template-param>, leaving the <template-args> for d_prefix to
parse.
When printing a conversion operator, in d_print_cast, if the
operator is derived from a <template>, we need to place that
template in scope so that the <template-param> can look up the
correct type. We can't just add it to the stack of templates,
though, since that's only applicable when printing the type of a
function whose name is a template.
Here's the long example that started me down this path:
_ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEEcvT_ISt6vectorI12basic_stringIcSt11char_traitsIcESaIcEESaISD_EEvEEv
The demangler fails to parse this string, because the "SD_" near
the end is asking for the 15th substitution, but at that point it
has only registered 14 substitutions. That happened because it
greedily consumed the <template-args> that follow "cvT_", and
hadn't yet registered the substitution for the conversion
operator (which derives from <prefix>). Any substitutions that
are contained in the <template-args> will be off by one as a
result.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Bug other/59195] C++ demangler handles conversion operator incorrectly
2013-11-19 18:53 [Bug other/59195] New: C++ demangler handles conversion operator incorrectly ccoutant at gcc dot gnu.org
@ 2013-11-19 18:56 ` ccoutant at gcc dot gnu.org
2013-11-22 22:25 ` ccoutant at gcc dot gnu.org
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: ccoutant at gcc dot gnu.org @ 2013-11-19 18:56 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195
Cary Coutant <ccoutant at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |ASSIGNED
Last reconfirmed| |2013-11-19
Assignee|unassigned at gcc dot gnu.org |ccoutant at gcc dot gnu.org
Ever confirmed|0 |1
--- Comment #1 from Cary Coutant <ccoutant at gcc dot gnu.org> ---
Created attachment 31253
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=31253&action=edit
Proposed patch
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Bug other/59195] C++ demangler handles conversion operator incorrectly
2013-11-19 18:53 [Bug other/59195] New: C++ demangler handles conversion operator incorrectly ccoutant at gcc dot gnu.org
2013-11-19 18:56 ` [Bug other/59195] " ccoutant at gcc dot gnu.org
@ 2013-11-22 22:25 ` ccoutant at gcc dot gnu.org
2014-02-25 19:58 ` ccoutant at gcc dot gnu.org
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: ccoutant at gcc dot gnu.org @ 2013-11-22 22:25 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195
--- Comment #2 from Cary Coutant <ccoutant at gcc dot gnu.org> ---
Author: ccoutant
Date: Fri Nov 22 22:25:49 2013
New Revision: 205292
URL: http://gcc.gnu.org/viewcvs?rev=205292&root=gcc&view=rev
Log:
Fix demangler to handle conversion operators correctly.
libiberty/
PR other/59195
* cp-demangle.c (struct d_info_checkpoint): New struct.
(struct d_print_info): Add current_template field.
(d_operator_name): Set flag when processing a conversion
operator.
(cplus_demangle_type): When processing <template-args> for
a conversion operator, backtrack if necessary.
(d_expression_1): Renamed from d_expression.
(d_expression): New wrapper around d_expression_1.
(d_checkpoint): New function.
(d_backtrack): New function.
(d_print_init): Initialize current_template.
(d_print_comp): Set current_template.
(d_print_cast): Put current_template in scope for
printing conversion operator name.
(cplus_demangle_init_info): Initialize is_expression and
is_conversion.
* cp-demangle.h (struct d_info): Add is_expression and
is_conversion fields.
* testsuite/demangle-expected: New test cases.
Modified:
trunk/libiberty/ChangeLog
trunk/libiberty/cp-demangle.c
trunk/libiberty/cp-demangle.h
trunk/libiberty/testsuite/demangle-expected
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Bug other/59195] C++ demangler handles conversion operator incorrectly
2013-11-19 18:53 [Bug other/59195] New: C++ demangler handles conversion operator incorrectly ccoutant at gcc dot gnu.org
2013-11-19 18:56 ` [Bug other/59195] " ccoutant at gcc dot gnu.org
2013-11-22 22:25 ` ccoutant at gcc dot gnu.org
@ 2014-02-25 19:58 ` ccoutant at gcc dot gnu.org
2014-05-26 14:04 ` palves at redhat dot com
2014-05-26 14:05 ` palves at redhat dot com
4 siblings, 0 replies; 6+ messages in thread
From: ccoutant at gcc dot gnu.org @ 2014-02-25 19:58 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195
Cary Coutant <ccoutant at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|ASSIGNED |RESOLVED
Resolution|--- |FIXED
--- Comment #3 from Cary Coutant <ccoutant at gcc dot gnu.org> ---
Fixed at r205292.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Bug other/59195] C++ demangler handles conversion operator incorrectly
2013-11-19 18:53 [Bug other/59195] New: C++ demangler handles conversion operator incorrectly ccoutant at gcc dot gnu.org
` (2 preceding siblings ...)
2014-02-25 19:58 ` ccoutant at gcc dot gnu.org
@ 2014-05-26 14:04 ` palves at redhat dot com
2014-05-26 14:05 ` palves at redhat dot com
4 siblings, 0 replies; 6+ messages in thread
From: palves at redhat dot com @ 2014-05-26 14:04 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195
Pedro Alves <palves at redhat dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |palves at redhat dot com
--- Comment #4 from Pedro Alves <palves at redhat dot com> ---
This caused bug 61321.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Bug other/59195] C++ demangler handles conversion operator incorrectly
2013-11-19 18:53 [Bug other/59195] New: C++ demangler handles conversion operator incorrectly ccoutant at gcc dot gnu.org
` (3 preceding siblings ...)
2014-05-26 14:04 ` palves at redhat dot com
@ 2014-05-26 14:05 ` palves at redhat dot com
4 siblings, 0 replies; 6+ messages in thread
From: palves at redhat dot com @ 2014-05-26 14:05 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195
--- Comment #5 from Pedro Alves <palves at redhat dot com> ---
Likely bug 61233 too.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-05-26 14:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-19 18:53 [Bug other/59195] New: C++ demangler handles conversion operator incorrectly ccoutant at gcc dot gnu.org
2013-11-19 18:56 ` [Bug other/59195] " ccoutant at gcc dot gnu.org
2013-11-22 22:25 ` ccoutant at gcc dot gnu.org
2014-02-25 19:58 ` ccoutant at gcc dot gnu.org
2014-05-26 14:04 ` palves at redhat dot com
2014-05-26 14:05 ` palves at redhat dot com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).