public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* c++/3211: Incorrect, substitution related mangling.
@ 2001-06-17 9:56 carlo
0 siblings, 0 replies; 6+ messages in thread
From: carlo @ 2001-06-17 9:56 UTC (permalink / raw)
To: gcc-gnats
>Number: 3211
>Category: c++
>Synopsis: Incorrect, substitution related mangling.
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: unassigned
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Jun 17 09:56:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: Carlo Wood
>Release: 3.0
>Organization:
>Environment:
>Description:
There are still issues with (de)mangling and qualifiers.
Qualifiers and pointer-to-member may even result in
wrong mangling as a result of errornous substitutions.
>How-To-Repeat:
See audit trail that I will post in a moment.
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: c++/3211: Incorrect, substitution related mangling.
@ 2001-11-13 15:16 loewis
0 siblings, 0 replies; 6+ messages in thread
From: loewis @ 2001-11-13 15:16 UTC (permalink / raw)
To: nobody; +Cc: gcc-prs
The following reply was made to PR c++/3211; it has been noted by GNATS.
From: loewis@gcc.gnu.org
To: carlo@alinoe.com, gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org,
gcc-prs@gcc.gnu.org, nobody@gcc.gnu.org
Cc:
Subject: Re: c++/3211: Incorrect, substitution related mangling.
Date: 19 Nov 2001 16:17:23 -0000
Synopsis: Incorrect, substitution related mangling.
State-Changed-From-To: open->closed
State-Changed-By: loewis
State-Changed-When: Mon Nov 19 08:17:22 2001
State-Changed-Why:
Closed on request of submitter.
http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&pr=3211&database=gcc
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: c++/3211: Incorrect, substitution related mangling.
@ 2001-11-13 15:16 loewis
0 siblings, 0 replies; 6+ messages in thread
From: loewis @ 2001-11-13 15:16 UTC (permalink / raw)
To: carlo, gcc-bugs, gcc-gnats, gcc-prs, nobody
Synopsis: Incorrect, substitution related mangling.
State-Changed-From-To: open->closed
State-Changed-By: loewis
State-Changed-When: Mon Nov 19 08:17:22 2001
State-Changed-Why:
Closed on request of submitter.
http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&pr=3211&database=gcc
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: c++/3211: Incorrect, substitution related mangling.
@ 2001-06-18 16:56 Carlo Wood
0 siblings, 0 replies; 6+ messages in thread
From: Carlo Wood @ 2001-06-18 16:56 UTC (permalink / raw)
To: nobody; +Cc: gcc-prs
The following reply was made to PR c++/3211; it has been noted by GNATS.
From: Carlo Wood <carlo@alinoe.com>
To: Mark Mitchell <mark@codesourcery.com>
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: c++/3211: Incorrect, substitution related mangling.
Date: Tue, 19 Jun 2001 01:51:50 +0200
On Mon, Jun 18, 2001 at 10:08:29AM -0700, Mark Mitchell wrote:
...
> But, we will not change the G++ mangling under any circumstances --
> unless there are programs that do not work because two mangled names
> conflict when they should not.
>
> --
> Mark Mitchell mark@codesourcery.com
> CodeSourcery, LLC http://www.codesourcery.com
Then PR c++/3211 can be closed.
--
Carlo Wood <carlo@alinoe.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: c++/3211: Incorrect, substitution related mangling.
@ 2001-06-17 17:36 Carlo Wood
0 siblings, 0 replies; 6+ messages in thread
From: Carlo Wood @ 2001-06-17 17:36 UTC (permalink / raw)
To: nobody; +Cc: gcc-prs
The following reply was made to PR c++/3211; it has been noted by GNATS.
From: Carlo Wood <carlo@alinoe.com>
To: gcc-bugs@gcc.gnu.org
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: c++/3211: Incorrect, substitution related mangling.
Date: Mon, 18 Jun 2001 02:31:05 +0200
On Sun, Jun 17, 2001 at 06:59:39PM +0200, Carlo Wood wrote:
> Please note that even:
>
> --------------------
> #include <iostream>
> #include <typeinfo>
>
> struct A {
> int member(void) { }
> };
>
> template<typename T>
> struct const_test {
> typedef int (member_type)(void);
> member_type (T::*member_pointer);
> };
>
> int main(void)
> {
> std::cout << typeid(const_test<A const>::member_pointer).name() << '\n';
> return 0;
> }
> --------------------
>
> Returns "MK1AFivE", where "1A" is <type1> and "FivE" is <type2>. There is no
> 'const' qualifier for "1A".
Hmmpf. Ok, that was nonsense... There *is* a 'K' there...
But it doesn't change the fact that there can only be a 'K' when <type2>
is a (member) function. I don't think this changes the relevance of my
argument that "K1A" shouldn't be a candidate for substitution, nor should
a substitution be used at that place for "K1A" is one such substitution
already exists.
--
Carlo Wood <carlo@alinoe.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* c++/3211: Incorrect, substitution related mangling.
@ 2001-06-17 10:06 Carlo Wood
0 siblings, 0 replies; 6+ messages in thread
From: Carlo Wood @ 2001-06-17 10:06 UTC (permalink / raw)
To: nobody; +Cc: gcc-prs
The following reply was made to PR c++/3211; it has been noted by GNATS.
From: Carlo Wood <carlo@alinoe.com>
To: gcc-bugs@gcc.gnu.org
Cc: gcc-gnats@gcc.gnu.org
Subject: c++/3211: Incorrect, substitution related mangling.
Date: Sun, 17 Jun 2001 18:59:39 +0200
I am afraid this is going to be a long one. The background is that
I've been working on a demangler for several weeks now, using g++-3.0 (pre)
and the demangler in libiberty for comparision (without looking at the source).
Now I've come to a point where start to find bugs in g++ instead of in
my own demangler ;).
PS If you don't have time to read it all, there is a CONCLUSION half way.
I've used http://reality.sgi.com/dehnert_engr/cxx/abi.html#mangling-type
as reference for writing my demangler.
---
This reference defines
<pointer-to-member-type> ::= M <class type> <member type>
being a <type> itself, it is subject to substitution.
Moreover, "<CV-qualifiers> <some type>" being a <type>, both
"<CV-qualifiers> <some type>" and "<some type>" are subject to
substitution.
For clarity, let <type> be an unqualified type below. So we
have to write:
<pointer-to-member-type> ::= [<CV-qualifiers>] M [<CV-qualifiers>] <type1> [<CV-qualifiers>] <type2>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pointer-to-member-type ____/ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
class type ____/ member type ____/
and subsitution members are:
<type1>
<CV-qualifiers> <type1>
<type2>
<CV-qualifiers> <type2>
M <CV-qualifiers> <type1> <CV-qualifiers> <type2>
<CV-qualifiers> M <CV-qualifiers> <type1> <CV-qualifiers> <type2>
As an example, <type2> has qualifiers in this case:
--------------------
struct A {
int volatile member;
};
int volatile (A::*member_pointer) = &A::member;
--------------------
We can use the following test program to find what g++-3.0 makes of it:
--------------------
#include <iostream>
#include <typeinfo>
struct A {
int volatile member;
};
int volatile (A::*member_pointer) = &A::member;
int main(void)
{
std::cout << typeid(member_pointer).name() << '\n';
return 0;
}
--------------------
which gives:
M1AVi
Now note that "A const::*" is incorrect C++.
The following test case:
--------------------
#include <iostream>
#include <typeinfo>
struct A {
int volatile member;
};
template<typename T>
struct const_test {
static int volatile (T::*member_pointer);
};
template<typename T>
int volatile (T::*const_test<T>::member_pointer) = &T::member;
int main(void)
{
std::cout << typeid(const_test<A const>::member_pointer).name() << '\n';
return 0;
}
--------------------
Still return "M1AVi", because the 'const' is simply dropped.
The only way to get a qualifier before <type1> is when <type2> is a member *function*
that is `const'. Please not that even:
--------------------
#include <iostream>
#include <typeinfo>
struct A {
int member(void) { }
};
template<typename T>
struct const_test {
typedef int (member_type)(void);
member_type (T::*member_pointer);
};
int main(void)
{
std::cout << typeid(const_test<A const>::member_pointer).name() << '\n';
return 0;
}
--------------------
Returns "MK1AFivE", where "1A" is <type1> and "FivE" is <type2>. There is no
'const' qualifier for "1A".
This seems to indicate that qualifiers directly after the "M" really
belong to the member *function*. For example:
--------------------
#include <iostream>
#include <typeinfo>
struct A {
int member(void) const { }
};
int (A::*member_pointer)(void) const = &A::member;
int main(void)
{
std::cout << typeid(member_pointer).name() << '\n';
return 0;
}
--------------------
returns "MK1AFivE", with a 'K' in front of the <type1> -- which as we saw before
really can't BE there *unless* <type2> is a function.
[ Note that this is very equivalent with how qualifiers work with nested functions,
for example:
--------------------
struct A {
int f1(float);
int f2(float) const volatile;
};
int A::f1(float) { }
int A::f2(float) const volatile { }
--------------------
results in the mangled names:
00000000 T _ZN1A2f1Ef
00000010 T _ZNVK1A2f2Ef
very similar like
--------------------
struct A;
void f1p(int (A::*)(float)) { }
void f2p(int (A::*)(float) const volatile) { }
--------------------
results in the mangled names
00000000 T _Z3f1pM1AFifE
00000020 T _Z3f2pMVK1AFifE
]
Imho, the draft is wrong and should have defined <pointer-to-member> like
it defines <nested-name>:
<pointer-to-member-type> ::= M [CV-qualifiers] <class type> <member type>
stripping off qualifiers that otherwise *errornous* seem to belong to the
class type (which is not possible).
Another argument for this is found by looking at what happens when
<class type> is a <nested-name> itself. For example:
--------------------
#include <iostream>
#include <typeinfo>
struct A {
struct B {
int member(void) const { }
};
};
int (A::B::*member_pointer)(void) const = &A::B::member;
int main(void)
{
std::cout << typeid(member_pointer).name() << '\n';
return 0;
}
--------------------
prints "MKN1A1BEFivE", as it should (imho) and NOT "MN1AK1BEFivE", or
"MNK1A1BEFivE" for that matter.
The demangler in libiberty is already *heavily* broken concerning qualifiers
(as I reported before), but how does the above affect the mangling of g++?
It does because it has effect on the used substitutions, after all - when using
<pointer-to-member-type> ::= M [CV-qualifiers] <class type> <member type>
the resulting substitutions would be:
<type1> <-- unqualified, even when being a <nested-name>
<type2>
<CV-qualifiers> <type2>
M <CV-qualifiers> <type1> <CV-qualifiers> <type2>
<CV-qualifiers> M <CV-qualifiers> <type1> <CV-qualifiers> <type2>
And "<CV-qualifiers> <type1>" is gone from the list.
Now before you say 'yes, but this is at most a bug in the reference and not in g++',
let me point out an inconsistency in the reference related to this. It states:
"substitutable components are the represented symbolic constructs, not their
associated mangling character strings". This would mean that a substitution
for "<CV-qualifiers> <type1>" would result in storing and re-using a string like
"A::B const", but it is possible to get:
MS3_FivE
for example, where S3_ represents the mentioned qualified <type1>. Following the
reference literally we'd HAVE to demangle that as:
"void (A::B const::*)(int)"
where the string "A::B const" (S3_) appears literally.
==========
CONCLUSION
==========
This is why I am convinced that this substitution is wrong, it shouldn't exist.
The correct way to mangle the above is as follows:
with for example:
S2_ == "A::B"
S3_ == "A::B const"
"void (A::B::*)(int) const"
should mangle as
"MKS2_FviE" and not as "MS3_FviE".
g++-3.0 makes of this:
----------------------
struct A {
struct B {
int member(void) const { }
static int (A::B::* const member_pointer)(void) const = &A::B::member;
void foo(A::B const*, typeof(member_pointer));
};
};
void A::B::foo(A::B const*, typeof(A::B::member_pointer)) { }
----------------------
where 'A::B::foo' is mangled as "_ZN1A1B3fooEPKS0_MS1_FivE".
this should be "_ZN1A1B3fooEPKS0_MKS0_FivE" imho.
--
Carlo Wood <carlo@alinoe.com>
=====================================================================================
PS Note that the demangler in libiberty chokes on this as well:
/usr/src/gcc/gcc-cvs-3.0/libiberty>c++filt _ZN1A1B3fooEPKS0_MKS0_FivE
-> mangled-name at position 0
-> encoding at position 2
-> name at position 2
-> nested-name at position 2
-> prefix at position 3
-> unqualified-name at position 3
-> source-name at position 3
-> number at position 3
-> number* at position 3
-> identifier at position 4
SUBSTITUTIONS:
S_ : A
-> unqualified-name at position 5
-> source-name at position 5
-> number at position 5
-> number* at position 5
-> identifier at position 6
SUBSTITUTIONS:
S_ : A
S0_ : A::B
-> unqualified-name at position 7
-> source-name at position 7
-> number at position 7
-> number* at position 7
-> identifier at position 8
-> bare-function-type at position 12
-> type at position 12
-> type* at position 12
-> type* at position 13
-> type at position 13
-> CV-qualifiers at position 13
-> type at position 14
-> substitution at position 14
-> number at position 15
-> number* at position 15
SUBSTITUTIONS:
S_ : A
S0_ : A::B
S1_ : A::B const
SUBSTITUTIONS:
S_ : A
S0_ : A::B
S1_ : A::B const
S2_ : A::B const*
-> type at position 17
-> type* at position 17
-> type at position 18
-> CV-qualifiers at position 18
-> type at position 19
-> substitution at position 19
-> number at position 20
-> number* at position 20
SUBSTITUTIONS:
S_ : A
S0_ : A::B
S1_ : A::B const
S2_ : A::B const*
S3_ : A::B const
-> type* at position 22
-> function-type at position 22
-> bare-function-type at position 23
-> type at position 23
-> builtin-type at position 23
SUBSTITUTIONS:
S_ : A
S0_ : A::B
S1_ : A::B const
S2_ : A::B const*
S3_ : A::B const
S4_ : int ()()
SUBSTITUTIONS:
S_ : A
S0_ : A::B
S1_ : A::B const
S2_ : A::B const*
S3_ : A::B const
S4_ : int ()()
S5_ : int (A::B const::*)()
A::B::foo(A::B const*, int (A::B const::*)())
Where "A::B const" appears TWICE in the substitution list, which is a definite bug.
Moreover, I am not convinved that "int ()()" should be there (it can neither be
used as a literal replacement; same argument). Finally, the "A::B const::*"
is syntactical nonsense.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2001-11-19 16:26 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-06-17 9:56 c++/3211: Incorrect, substitution related mangling carlo
2001-06-17 10:06 Carlo Wood
2001-06-17 17:36 Carlo Wood
2001-06-18 16:56 Carlo Wood
2001-11-13 15:16 loewis
2001-11-13 15:16 loewis
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).