diff options
author | Jason Merrill <jason@redhat.com> | 2008-10-06 18:29:42 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2008-10-06 18:29:42 -0400 |
commit | 38179091cc37de50c92d821b3670e94943d41bfc (patch) | |
tree | bc6ed12ab486e9243fadc7deb1fa88cc3d721bdf /gcc | |
parent | ecbeb53b5654ccc6efdbdbdb47ef6e29271bb120 (diff) | |
download | gcc-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/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 116 | ||||
-rw-r--r-- | gcc/cp/operators.def | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/mangle30.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/auto6.C | 71 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic4.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic42.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/utf-mangle.C | 8 | ||||
-rw-r--r-- | gcc/tree.h | 2 |
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:" } } @@ -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 |