aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2008-10-06 18:29:42 -0400
committerJason Merrill <jason@gcc.gnu.org>2008-10-06 18:29:42 -0400
commit38179091cc37de50c92d821b3670e94943d41bfc (patch)
treebc6ed12ab486e9243fadc7deb1fa88cc3d721bdf /gcc
parentecbeb53b5654ccc6efdbdbdb47ef6e29271bb120 (diff)
downloadgcc-38179091cc37de50c92d821b3670e94943d41bfc.zip
gcc-38179091cc37de50c92d821b3670e94943d41bfc.tar.gz
gcc-38179091cc37de50c92d821b3670e94943d41bfc.tar.bz2
PR c++/37376, other mangling issues
gcc/cp/: PR c++/37376, other mangling issues * mangle.c (write_type): Update TYPE_PACK_EXPANSION mangling. (write_member_name): Break out from... (write_expression): ...here. Handle dependent COMPONENT_REF. (write_template_arg): Wrap an argument pack in 'I'/'E'. (write_builtin_type): Update char16/32_t mangling. (write_nested_name, write_prefix): Don't forget template args for typename types. * operators.def: Add ARROW_EXPR, update COMPONENT_REF and EXPR_PACK_EXPANSION. libstdc++-v3/: * config/abi/pre/gnu.ver: Update char16/32_t manglings. include/: * demangle.h (enum demangle_component_type): Add DEMANGLE_COMPONENT_PACK_EXPANSION. libiberty/: * cp-demangle.c (struct d_print_info): Add pack_index. (d_dump): Add DEMANGLE_COMPONENT_PACK_EXPANSION. (d_make_comp): Likewise. DEMANGLE_COMPONENT_ARGLIST and DEMANGLE_COMPONENT_TEMPLATE_ARGLIST can have two null args. (cplus_demangle_builtin_types): Add char16/32_t. (cplus_demangle_type): Recognize them. (d_template_args): Handle empty argument packs. (d_template_arg): Handle argument packs. (d_expression): Handle dependent name. (d_index_template_argument): New fn. (d_lookup_template_argument): New fn. (d_find_pack, d_pack_length): New fn. (d_print_subexpr): Split out... (d_print_comp): ...from here. Use d_*_template_argument. Handle empty arg lists. Support pack expansions. * cp-demangle.h (D_BUILTIN_TYPE_COUNT): Increase to 32. From-SVN: r140916
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/mangle.c116
-rw-r--r--gcc/cp/operators.def5
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle30.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto6.C71
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic4.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic42.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-mangle.C8
-rw-r--r--gcc/tree.h2
9 files changed, 206 insertions, 43 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index dc18acc..222693f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2008-10-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/37376, other mangling issues
+ * mangle.c (write_type): Update TYPE_PACK_EXPANSION mangling.
+ (write_member_name): Break out from...
+ (write_expression): ...here. Handle dependent COMPONENT_REF.
+ (write_template_arg): Wrap an argument pack in 'I'/'E'.
+ (write_builtin_type): Update char16/32_t mangling.
+ (write_nested_name, write_prefix): Don't forget template args
+ for typename types.
+ * operators.def: Add ARROW_EXPR, update COMPONENT_REF and
+ EXPR_PACK_EXPANSION.
+
2008-10-06 Aldy Hernandez <aldyh@redhat.com>
* typeck.c (build_x_indirect_ref): Add location argument.
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 7b4c303..c0282d8 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -887,6 +887,20 @@ write_nested_name (const tree decl)
write_template_prefix (decl);
write_template_args (TI_ARGS (template_info));
}
+ else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
+ {
+ tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ write_template_prefix (decl);
+ write_template_args (TREE_OPERAND (name, 1));
+ }
+ else
+ {
+ write_prefix (CP_DECL_CONTEXT (decl));
+ write_unqualified_name (decl);
+ }
+ }
else
{
/* No, just use <prefix> */
@@ -953,6 +967,20 @@ write_prefix (const tree node)
write_template_prefix (decl);
write_template_args (TI_ARGS (template_info));
}
+ else if (TREE_CODE (TREE_TYPE (decl)) == TYPENAME_TYPE)
+ {
+ tree name = TYPENAME_TYPE_FULLNAME (TREE_TYPE (decl));
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ write_template_prefix (decl);
+ write_template_args (TREE_OPERAND (name, 1));
+ }
+ else
+ {
+ write_prefix (CP_DECL_CONTEXT (decl));
+ write_unqualified_name (decl);
+ }
+ }
else
/* Not templated. */
{
@@ -982,6 +1010,9 @@ write_template_prefix (const tree node)
/* Find the template decl. */
if (decl_is_template_id (decl, &template_info))
templ = TI_TEMPLATE (template_info);
+ else if (TREE_CODE (type) == TYPENAME_TYPE)
+ /* For a typename type, all we have is the name. */
+ templ = DECL_NAME (decl);
else
{
gcc_assert (CLASSTYPE_TEMPLATE_ID_P (type));
@@ -1020,11 +1051,13 @@ write_template_prefix (const tree node)
return;
/* In G++ 3.2, the name of the template template parameter was used. */
- if (TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM
+ if (TREE_TYPE (templ)
+ && TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM
&& !abi_version_at_least (2))
G.need_abi_warning = true;
- if (TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM
+ if (TREE_TYPE (templ)
+ && TREE_CODE (TREE_TYPE (templ)) == TEMPLATE_TEMPLATE_PARM
&& abi_version_at_least (2))
write_template_param (TREE_TYPE (templ));
else
@@ -1636,7 +1669,7 @@ write_type (tree type)
break;
case TYPE_PACK_EXPANSION:
- write_string ("U10__variadic");
+ write_string ("Dp");
write_type (PACK_EXPANSION_PATTERN (type));
break;
@@ -1750,9 +1783,9 @@ write_builtin_type (tree type)
if (type == wchar_type_node)
write_char ('w');
else if (type == char16_type_node)
- write_string ("u8char16_t");
+ write_string ("Ds");
else if (type == char32_type_node)
- write_string ("u8char32_t");
+ write_string ("Di");
else if (TYPE_FOR_JAVA (type))
write_java_integer_type_codes (type);
else
@@ -2009,6 +2042,35 @@ write_template_args (tree args)
write_char ('E');
}
+/* Write out the
+ <unqualified-name>
+ <unqualified-name> <template-args>
+ part of SCOPE_REF or COMPONENT_REF mangling. */
+
+static void
+write_member_name (tree member)
+{
+ if (TREE_CODE (member) == IDENTIFIER_NODE)
+ write_source_name (member);
+ else if (DECL_P (member))
+ {
+ /* G++ 3.2 incorrectly put out both the "sr" code and
+ the nested name of the qualified name. */
+ G.need_abi_warning = 1;
+ write_unqualified_name (member);
+ }
+ else if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
+ {
+ tree name = TREE_OPERAND (member, 0);
+ if (TREE_CODE (name) == OVERLOAD)
+ name = OVL_FUNCTION (name);
+ write_member_name (name);
+ write_template_args (TREE_OPERAND (member, 1));
+ }
+ else
+ write_expression (member);
+}
+
/* <expression> ::= <unary operator-name> <expression>
::= <binary operator-name> <expression> <expression>
::= <expr-primary>
@@ -2161,6 +2223,20 @@ write_expression (tree expr)
write_template_args (template_args);
}
}
+ else if (code == COMPONENT_REF)
+ {
+ tree ob = TREE_OPERAND (expr, 0);
+
+ if (TREE_CODE (ob) == ARROW_EXPR)
+ {
+ code = ARROW_EXPR;
+ ob = TREE_OPERAND (ob, 0);
+ }
+
+ write_string (operator_name_info[(int)code].mangled_name);
+ write_expression (ob);
+ write_member_name (TREE_OPERAND (expr, 1));
+ }
else
{
int i;
@@ -2198,8 +2274,12 @@ write_expression (tree expr)
case CAST_EXPR:
write_type (TREE_TYPE (expr));
if (!TREE_OPERAND (expr, 0))
- /* "T()" is mangled as "T(void)". */
+ /* "T()" is mangled as "T(void)". */
write_char ('v');
+ else if (list_length (TREE_OPERAND (expr, 0)) > 1)
+ /* FIXME the above hack for T() needs to be replaced with
+ something more general. */
+ sorry ("mangling function-style cast with more than one argument");
else
write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
break;
@@ -2213,27 +2293,7 @@ write_expression (tree expr)
/* Handle pointers-to-members specially. */
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 if (TREE_CODE (TREE_OPERAND (expr, 1)) == TEMPLATE_ID_EXPR)
- {
- tree template_id;
- tree name;
-
- template_id = TREE_OPERAND (expr, 1);
- name = TREE_OPERAND (template_id, 0);
- /* FIXME: What about operators? */
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
- write_source_name (TREE_OPERAND (template_id, 0));
- write_template_args (TREE_OPERAND (template_id, 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));
- }
+ write_member_name (TREE_OPERAND (expr, 1));
break;
default:
@@ -2338,8 +2398,10 @@ write_template_arg (tree node)
/* Expand the template argument pack. */
tree args = ARGUMENT_PACK_ARGS (node);
int i, 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');
}
else if (TYPE_P (node))
write_type (node);
diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def
index 9c2dd8b..20c74d8 100644
--- a/gcc/cp/operators.def
+++ b/gcc/cp/operators.def
@@ -125,7 +125,8 @@ DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2)
DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2)
DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2)
DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2)
-DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2)
+DEF_SIMPLE_OPERATOR ("->", ARROW_EXPR, "pt", 2)
+DEF_SIMPLE_OPERATOR (".", COMPONENT_REF, "dt", 2)
DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2)
DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2)
DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", 2)
@@ -152,4 +153,4 @@ DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", 3)
DEF_SIMPLE_OPERATOR ("()", CALL_EXPR, "cl", -1)
/* Variadic templates extension. */
-DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "pu", 1)
+DEF_SIMPLE_OPERATOR ("...", EXPR_PACK_EXPANSION, "sp", 1)
diff --git a/gcc/testsuite/g++.dg/abi/mangle30.C b/gcc/testsuite/g++.dg/abi/mangle30.C
new file mode 100644
index 0000000..f0b83db
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle30.C
@@ -0,0 +1,22 @@
+// Test for mangling of template args in a typename type.
+
+struct A
+{
+ template <class T>
+ struct B
+ {
+ typedef T myT;
+ };
+};
+
+struct C {};
+
+template <class T>
+void f (T t, typename T::template B<C>::myT u, typename T::template B<int>::myT v);
+
+int main()
+{
+ f (A(), C(), 1);
+}
+
+// { dg-final { scan-assembler "_Z1fI1AEvT_NS1_1BI1CE3myTENS2_IiE3myTE" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto6.C b/gcc/testsuite/g++.dg/cpp0x/auto6.C
index 713583a..d2bcfed 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto6.C
@@ -1,3 +1,4 @@
+// Tests for late-specified return type.
// { dg-options "-std=c++0x" }
auto f() -> int
@@ -12,17 +13,81 @@ auto add(T t, U u) -> decltype (t+u)
}
template<class T, class U>
-decltype(T()+U()) add2(T t, U u);
+decltype(T()+U()) add2(T t, U u)
+{
+ return t+u;
+}
template <class T, class U>
-U g (T, U);
+U ag (T, U)
+{
+ return U();
+}
template<class T, class U>
-auto add3(T t, U u) -> decltype (g(t,u));
+auto add3(T t, U u) -> decltype (ag(t,u))
+{
+ return ag(t,u);
+}
+
+template <class T>
+struct A
+{
+ T f() {}
+ template <class U>
+ T g() {}
+ template <class V>
+ struct B
+ {
+ int MEM;
+ };
+};
+
+template <class T>
+auto f(T* t) -> decltype (t->f())
+{
+ return t->f();
+}
+
+template <class T>
+auto g(T t) -> decltype (t.f())
+{
+ return t.f();
+}
+
+template <class T, class U>
+auto h(T t, U u) -> decltype (t.template g<U>())
+{
+ return t.template g<U>();
+}
+
+struct D { };
+struct C: public A<int>::B<D>
+{
+};
+
+template <class T, class U, class V>
+auto k(T t, U u, V v) -> decltype (t.U::template B<V>::MEM)
+{
+ return t.U::template B<V>::MEM;
+}
+
+A<int> a, *p;
int main()
{
+ // { dg-final { scan-assembler "_Z3addIidEDTplsTT_sTT0_ES0_S1_" } }
auto i = add(1, 2.0);
+ // { dg-final { scan-assembler "_Z4add2IidEDTplcvT_vcvT0_vES0_S1_" } }
auto i2 = add2(1, 2.0);
+ // { dg-final { scan-assembler "_Z4add3IidEDTclL_Z2agEsTT_sTT0_EES0_S1_" } }
auto i3 = add3(1, 2.0);
+ // { dg-final { scan-assembler "_Z1fI1AIiEEDTclptsTPT_1fEES3_" } }
+ f(p);
+ // { dg-final { scan-assembler "_Z1gI1AIiEEDTcldtsTT_1fEES2_" } }
+ g(a);
+ // { dg-final { scan-assembler "_Z1hI1AIiEdEDTcldtsTT_1gIT0_EEES2_S3_" } }
+ h(a,1.0);
+ // { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtsTT_srNT0_1BIT1_EE3MEMES4_S5_S7_" } }
+ k( C(), A<int>(), D() );
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic4.C b/gcc/testsuite/g++.dg/cpp0x/variadic4.C
index 6c15a6d..9257a92 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic4.C
@@ -9,7 +9,7 @@ void f_two(tuple<int, float>) {}
void f_nested(tuple<int, tuple<double, char>, float>) { }
-// { dg-final { scan-assembler "_Z6f_none5tupleIE" } }
-// { dg-final { scan-assembler "_Z5f_one5tupleIiE" } }
-// { dg-final { scan-assembler "_Z5f_two5tupleIifE" } }
-// { dg-final { scan-assembler "_Z8f_nested5tupleIiS_IdcEfE" } }
+// { dg-final { scan-assembler "_Z6f_none5tupleIIEE" } }
+// { dg-final { scan-assembler "_Z5f_one5tupleIIiEE" } }
+// { dg-final { scan-assembler "_Z5f_two5tupleIIifEE" } }
+// { dg-final { scan-assembler "_Z8f_nested5tupleIIiS_IIdcEEfEE" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic42.C b/gcc/testsuite/g++.dg/cpp0x/variadic42.C
index 4c6c767..47d9b66 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic42.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic42.C
@@ -8,5 +8,5 @@ void g()
f<int*, float*, double*>(0, 0, 0);
f<int*>(0,0,0);
}
-// { dg-final { scan-assembler "_Z1fIPiPfPdEvU10__variadicT_" } }
-// { dg-final { scan-assembler "_Z1fIPiiiEvU10__variadicT_" } }
+// { dg-final { scan-assembler "_Z1fIIPiPfPdEEvDpT_" } }
+// { dg-final { scan-assembler "_Z1fIIPiiiEEvDpT_" } }
diff --git a/gcc/testsuite/g++.dg/ext/utf-mangle.C b/gcc/testsuite/g++.dg/ext/utf-mangle.C
index bb5e382..a131887 100644
--- a/gcc/testsuite/g++.dg/ext/utf-mangle.C
+++ b/gcc/testsuite/g++.dg/ext/utf-mangle.C
@@ -8,7 +8,7 @@ void f1 (char32_t c) {}
void f2 (char16_t *s) {}
void f3 (char32_t *s) {}
-// { dg-final { scan-assembler "_Z2f0u8char16_t:" } }
-// { dg-final { scan-assembler "_Z2f1u8char32_t:" } }
-// { dg-final { scan-assembler "_Z2f2Pu8char16_t:" } }
-// { dg-final { scan-assembler "_Z2f3Pu8char32_t:" } }
+// { dg-final { scan-assembler "_Z2f0Ds:" } }
+// { dg-final { scan-assembler "_Z2f1Di:" } }
+// { dg-final { scan-assembler "_Z2f2PDs:" } }
+// { dg-final { scan-assembler "_Z2f3PDi:" } }
diff --git a/gcc/tree.h b/gcc/tree.h
index 85704e6..44bc3f0 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2559,7 +2559,7 @@ struct tree_memory_partition_tag GTY(())
/* For a FUNCTION_DECL, holds the tree of BINDINGs.
For a TRANSLATION_UNIT_DECL, holds the namespace's BLOCK.
For a VAR_DECL, holds the initial value.
- For a PARM_DECL, not used--default
+ For a PARM_DECL, used for DECL_ARG_TYPE--default
values for parameters are encoded in the type of the function,
not in the PARM_DECL slot.
For a FIELD_DECL, this is used for enumeration values and the C