This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Mangling of dependent qualified names
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 15 Oct 2002 16:55:18 -0700
- Subject: C++ PATCH: Mangling of dependent qualified names
- Reply-to: mark at codesourcery dot com
This patch corrects the handling of a number of complex mangling
cases
For most of them, we just crashed; for one, we generated an incorrect
mangling.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2002-10-15 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (operator_name_info_t): Add arity.
* lex.c (init_operators): Initialize it.
* mangle.c (write_conversion_operator_name): New function.
(write_unqualified_name): Use it.
(write_template_args): Accept template arguments as a TREE_LIST.
(write_expression): Adjust handling of qualified names to match
specification.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.759
diff -c -5 -p -r1.759 cp-tree.h
*** cp/cp-tree.h 15 Oct 2002 18:06:48 -0000 1.759
--- cp/cp-tree.h 15 Oct 2002 22:54:59 -0000
*************** typedef struct operator_name_info_t
*** 3479,3488 ****
--- 3479,3490 ----
tree identifier;
/* The name of the operator. */
const char *name;
/* The mangled name of the operator. */
const char *mangled_name;
+ /* The arity of the operator. */
+ int arity;
} operator_name_info_t;
/* A mapping from tree codes to operator name information. */
extern operator_name_info_t operator_name_info[];
/* Similar, but for assignment operators. */
Index: cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.291
diff -c -5 -p -r1.291 lex.c
*** cp/lex.c 21 Sep 2002 12:51:54 -0000 1.291
--- cp/lex.c 15 Oct 2002 22:55:03 -0000
*************** init_operators ()
*** 261,271 ****
oni = (ASSN_P \
? &assignment_operator_name_info[(int) CODE] \
: &operator_name_info[(int) CODE]); \
oni->identifier = identifier; \
oni->name = NAME; \
! oni->mangled_name = MANGLING;
#include "operators.def"
#undef DEF_OPERATOR
operator_name_info[(int) ERROR_MARK].identifier
--- 261,272 ----
oni = (ASSN_P \
? &assignment_operator_name_info[(int) CODE] \
: &operator_name_info[(int) CODE]); \
oni->identifier = identifier; \
oni->name = NAME; \
! oni->mangled_name = MANGLING; \
! oni->arity = ARITY;
#include "operators.def"
#undef DEF_OPERATOR
operator_name_info[(int) ERROR_MARK].identifier
Index: cp/mangle.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/mangle.c,v
retrieving revision 1.60
diff -c -5 -p -r1.60 mangle.c
*** cp/mangle.c 4 Oct 2002 04:59:39 -0000 1.60
--- cp/mangle.c 15 Oct 2002 22:55:04 -0000
*************** static void write_unscoped_name PARAMS (
*** 164,173 ****
--- 164,174 ----
static void write_unscoped_template_name PARAMS ((tree));
static void write_nested_name PARAMS ((tree));
static void write_prefix PARAMS ((tree));
static void write_template_prefix PARAMS ((tree));
static void write_unqualified_name PARAMS ((tree));
+ static void write_conversion_operator_name (tree);
static void write_source_name PARAMS ((tree));
static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned));
static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
unsigned int));
static void write_integer_cst PARAMS ((tree));
*************** write_unqualified_name (decl)
*** 1014,1025 ****
NULL);
type = TREE_TYPE (fn_type);
}
else
type = TREE_TYPE (DECL_NAME (decl));
! write_string ("cv");
! write_type (type);
}
else if (DECL_OVERLOADED_OPERATOR_P (decl))
{
operator_name_info_t *oni;
if (DECL_ASSIGNMENT_OPERATOR_P (decl))
--- 1015,1025 ----
NULL);
type = TREE_TYPE (fn_type);
}
else
type = TREE_TYPE (DECL_NAME (decl));
! write_conversion_operator_name (type);
}
else if (DECL_OVERLOADED_OPERATOR_P (decl))
{
operator_name_info_t *oni;
if (DECL_ASSIGNMENT_OPERATOR_P (decl))
*************** write_unqualified_name (decl)
*** 1031,1040 ****
--- 1031,1049 ----
}
else
write_source_name (DECL_NAME (decl));
}
+ /* Write the unqualified-name for a conversion operator to TYPE. */
+
+ static void
+ write_conversion_operator_name (tree type)
+ {
+ write_string ("cv");
+ write_type (type);
+ }
+
/* Non-termial <source-name>. IDENTIFIER is an IDENTIFIER_NODE.
<source-name> ::= </length/ number> <identifier> */
static void
*************** write_class_enum_type (type)
*** 1778,1815 ****
static void
write_template_args (args)
tree args;
{
- int i;
- int length = TREE_VEC_LENGTH (args);
-
MANGLE_TRACE_TREE ("template-args", args);
! my_friendly_assert (length > 0, 20000422);
! if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
{
! /* We have nested template args. We want the innermost template
! argument list. */
! args = TREE_VEC_ELT (args, length - 1);
! length = TREE_VEC_LENGTH (args);
}
- write_char ('I');
- for (i = 0; i < length; ++i)
- write_template_arg (TREE_VEC_ELT (args, i));
write_char ('E');
}
/* <expression> ::= <unary operator-name> <expression>
::= <binary operator-name> <expression> <expression>
::= <expr-primary>
<expr-primary> ::= <template-param>
::= L <type> <value number> E # literal
! ::= L <mangled-name> E # external name */
static void
write_expression (expr)
tree expr;
{
--- 1787,1839 ----
static void
write_template_args (args)
tree args;
{
MANGLE_TRACE_TREE ("template-args", args);
! write_char ('I');
! if (TREE_CODE (args) == TREE_VEC)
{
! int i;
! int length = TREE_VEC_LENGTH (args);
! my_friendly_assert (length > 0, 20000422);
!
! if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
! {
! /* We have nested template args. We want the innermost template
! argument list. */
! args = TREE_VEC_ELT (args, length - 1);
! length = TREE_VEC_LENGTH (args);
! }
! for (i = 0; i < length; ++i)
! write_template_arg (TREE_VEC_ELT (args, i));
! }
! else
! {
! my_friendly_assert (TREE_CODE (args) == TREE_LIST, 20021014);
!
! while (args)
! {
! write_template_arg (TREE_VALUE (args));
! args = TREE_CHAIN (args);
! }
}
write_char ('E');
}
/* <expression> ::= <unary operator-name> <expression>
::= <binary operator-name> <expression> <expression>
::= <expr-primary>
<expr-primary> ::= <template-param>
::= L <type> <value number> E # literal
! ::= L <mangled-name> E # external name
! ::= sr <type> <unqualified-name>
! ::= sr <type> <unqualified-name> <template-args> */
static void
write_expression (expr)
tree expr;
{
*************** write_expression (expr)
*** 1857,1866 ****
--- 1881,1959 ----
&& TYPE_P (TREE_OPERAND (expr, 0)))
{
write_string ("st");
write_type (TREE_OPERAND (expr, 0));
}
+ else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (expr, 0);
+ tree member = TREE_OPERAND (expr, 1);
+
+ /* If the MEMBER is a real declaration, then the qualifying
+ scope was not dependent. Ideally, we would not have a
+ SCOPE_REF in those cases, but sometimes we do. If the second
+ argument is a DECL, then the name must not have been
+ dependent. */
+ if (DECL_P (member))
+ write_expression (member);
+ else
+ {
+ tree template_args;
+
+ write_string ("sr");
+ write_type (scope);
+ /* If MEMBER is a template-id, separate the template
+ from the arguments. */
+ if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
+ {
+ template_args = TREE_OPERAND (member, 1);
+ member = TREE_OPERAND (member, 0);
+ if (TREE_CODE (member) == LOOKUP_EXPR)
+ member = TREE_OPERAND (member, 0);
+ }
+ else
+ template_args = NULL_TREE;
+ /* Write out the name of the MEMBER. */
+ if (IDENTIFIER_TYPENAME_P (member))
+ write_conversion_operator_name (TREE_TYPE (member));
+ else if (IDENTIFIER_OPNAME_P (member))
+ {
+ int i;
+ const char *mangled_name = NULL;
+
+ /* Unfortunately, there is no easy way to go from the
+ name of the operator back to the corresponding tree
+ code. */
+ for (i = 0; i < LAST_CPLUS_TREE_CODE; ++i)
+ if (operator_name_info[i].identifier == member)
+ {
+ /* The ABI says that we prefer binary operator
+ names to unary operator names. */
+ if (operator_name_info[i].arity == 2)
+ {
+ mangled_name = operator_name_info[i].mangled_name;
+ break;
+ }
+ else if (!mangled_name)
+ mangled_name = operator_name_info[i].mangled_name;
+ }
+ else if (assignment_operator_name_info[i].identifier
+ == member)
+ {
+ mangled_name
+ = assignment_operator_name_info[i].mangled_name;
+ break;
+ }
+ write_string (mangled_name);
+ }
+ else
+ write_source_name (member);
+ /* Write out the template arguments. */
+ if (template_args)
+ write_template_args (template_args);
+ }
+ }
else
{
int i;
/* When we bind a variable or function to a non-type template
*************** write_expression (expr)
*** 1878,1888 ****
return;
}
code = TREE_CODE (expr);
}
!
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);
switch (code)
{
--- 1971,1981 ----
return;
}
code = TREE_CODE (expr);
}
!
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);
switch (code)
{
*************** write_expression (expr)
*** 1902,1912 ****
case SCOPE_REF:
write_type (TREE_OPERAND (expr, 0));
if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
write_source_name (TREE_OPERAND (expr, 1));
else
! write_encoding (TREE_OPERAND (expr, 1));
break;
default:
for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
write_expression (TREE_OPERAND (expr, i));
--- 1995,2010 ----
case SCOPE_REF:
write_type (TREE_OPERAND (expr, 0));
if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
write_source_name (TREE_OPERAND (expr, 1));
else
! {
! /* G++ 3.2 incorrectly put out both the "sr" code and
! the nested name of the qualified name. */
! G.need_abi_warning = 1;
! write_encoding (TREE_OPERAND (expr, 1));
! }
break;
default:
for (i = 0; i < TREE_CODE_LENGTH (code); ++i)
write_expression (TREE_OPERAND (expr, i));
Index: testsuite/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/ChangeLog,v
retrieving revision 1.2144
diff -c -5 -p -r1.2144 ChangeLog
*** testsuite/ChangeLog 15 Oct 2002 18:07:24 -0000 1.2144
--- testsuite/ChangeLog 15 Oct 2002 22:55:09 -0000
***************
*** 1,9 ****
2002-10-14 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/empty8.C: New test.
!
2002-10-15 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/init/ctor1.C: New test.
2002-10-15 Ulrich Weigand <uweigand@de.ibm.com>
--- 1,15 ----
+ 2002-10-15 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/abi/mangle13.C: Likewise.
+ * g++.dg/abi/mangle14.C: Likewise.
+ * g++.dg/abi/mangle15.C: Likewise.
+
2002-10-14 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/empty8.C: New test.
!
2002-10-15 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/init/ctor1.C: New test.
2002-10-15 Ulrich Weigand <uweigand@de.ibm.com>
Index: testsuite/g++.dg/abi/mangle13.C
===================================================================
RCS file: testsuite/g++.dg/abi/mangle13.C
diff -N testsuite/g++.dg/abi/mangle13.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/mangle13.C 15 Oct 2002 22:55:09 -0000
***************
*** 0 ****
--- 1,28 ----
+ // { dg-options "-fabi-version=0" }
+
+ struct A {
+ template <typename T> int f ();
+ int operator+();
+ operator int ();
+ template <typename T>
+ int operator-();
+ };
+
+ typedef int (A::*P)();
+
+ template <P> struct S {};
+
+ template <typename T> void g (S<&T::template f<int> >) {}
+ template <typename T> void g (S<&T::operator+ >) {}
+ template <typename T> void g (S<&T::operator int>) {}
+ template <typename T> void g (S<&T::template operator- <double> >) {}
+
+ template void g<A> (S<&A::f<int> >);
+ template void g<A> (S<&A::operator+>);
+ template void g<A> (S<&A::operator int>);
+ template void g<A> (S<&A::operator-<double> >);
+
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_1fIiEEE } }
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_plEE } }
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_cviEE } }
+ // { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_miIdEEE } }
Index: testsuite/g++.dg/abi/mangle14.C
===================================================================
RCS file: testsuite/g++.dg/abi/mangle14.C
diff -N testsuite/g++.dg/abi/mangle14.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/mangle14.C 15 Oct 2002 22:55:09 -0000
***************
*** 0 ****
--- 1,12 ----
+ // { dg-do compile }
+ // { dg-options "-Wabi" }
+
+ struct A {
+ template <typename T> int f ();
+ };
+
+ typedef int (A::*P)();
+
+ template <P> struct S {};
+
+ void g (S<&A::f<int> >) {} // { dg-warning "mangle" }
Index: testsuite/g++.dg/abi/mangle15.C
===================================================================
RCS file: testsuite/g++.dg/abi/mangle15.C
diff -N testsuite/g++.dg/abi/mangle15.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/mangle15.C 15 Oct 2002 22:55:09 -0000
***************
*** 0 ****
--- 1,14 ----
+ // { dg-do compile }
+ // { dg-options "-fabi-version=0" }
+
+ struct A {
+ template <typename T> int f ();
+ };
+
+ typedef int (A::*P)();
+
+ template <P> struct S {};
+
+ void g (S<&A::f<int> >) {}
+
+ // { dg-final { scan-assembler _Z1g1SIXadL_ZN1A1fIiEEivEEE } }