From 448545cb51bdf3d74c3d75f3b88dbf8c7a8de984 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 17 Mar 2009 19:31:18 -0400 Subject: [PATCH] decl.c (grokfndecl): Set DECL_CONTEXT on parms. cp/: * decl.c (grokfndecl): Set DECL_CONTEXT on parms. (duplicate_decls): Adjust DECL_CONTEXT of newdecl's parms. * pt.c (check_explicit_specialization): Likewise. (tsubst_copy) [PARM_DECL]: Return a dummy parm if we don't have a local specialization. * tree.c (cp_tree_equal) [PARM_DECL]: Check type and index, not name. * decl2.c (parm_index): New fn. * semantics.c (finish_decltype_type): Don't use describable_type. * mangle.c (write_expression): Likewise. Mangle ALIGNOF_EXPR. Give a sorry for unsupported codes rather than crash. Mangle conversions with other than 1 operand. New mangling for PARM_DECL. * operators.def (ALIGNOF_EXPR): Mangle as az. * include/demangle.h (enum demangle_component_type): Add DEMANGLE_COMPONENT_FUNCTION_PARAM. * libiberty/cp-demangle.c (d_make_function_param): new fn. (cplus_demangle_mangled_name): Work around abi v2 bug. (d_expr_primary): Likewise. (cplus_demangle_operators): Add alignof ops. (d_expression): Handle function parameters and conversions with other than 1 operand. (d_print_comp): Handle function parameters. Fix bug with function used in type of function. From-SVN: r144924 --- gcc/cp/ChangeLog | 15 ++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 22 ++++++-- gcc/cp/decl2.c | 23 ++++++++ gcc/cp/mangle.c | 75 +++++++++++++++------------ gcc/cp/operators.def | 2 +- gcc/cp/pt.c | 30 ++++++----- gcc/cp/semantics.c | 2 - gcc/cp/tree.c | 5 +- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/cpp0x/auto12.C | 12 ++--- gcc/testsuite/g++.dg/cpp0x/auto6.C | 16 +++--- include/ChangeLog | 5 ++ include/demangle.h | 6 ++- libiberty/ChangeLog | 12 +++++ libiberty/cp-demangle.c | 71 ++++++++++++++++++++++--- libiberty/testsuite/demangle-expected | 18 ++++--- 17 files changed, 231 insertions(+), 88 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a925c5ddfe8..1f5dd9d75f5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2009-03-17 Jason Merrill + + * decl.c (grokfndecl): Set DECL_CONTEXT on parms. + (duplicate_decls): Adjust DECL_CONTEXT of newdecl's parms. + * pt.c (check_explicit_specialization): Likewise. + (tsubst_copy) [PARM_DECL]: Return a dummy parm if we don't have a + local specialization. + * tree.c (cp_tree_equal) [PARM_DECL]: Check type and index, not name. + * decl2.c (parm_index): New fn. + * semantics.c (finish_decltype_type): Don't use describable_type. + * mangle.c (write_expression): Likewise. Mangle ALIGNOF_EXPR. + Give a sorry for unsupported codes rather than crash. Mangle + conversions with other than 1 operand. New mangling for PARM_DECL. + * operators.def (ALIGNOF_EXPR): Mangle as "az". + 2009-03-17 Jing Yu PR middle-end/39378 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0b1d7c61cdc..1745ede53c3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4436,6 +4436,7 @@ extern bool decl_needed_p (tree); extern void note_vague_linkage_fn (tree); extern tree build_artificial_parm (tree, tree); extern bool possibly_inlined_p (tree); +extern int parm_index (tree); /* in error.c */ extern void init_error (void); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 03e65d0f9db..9a6ab02e36e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1684,8 +1684,14 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) = DECL_SOURCE_LOCATION (newdecl); DECL_INITIAL (old_result) = DECL_INITIAL (new_result); if (DECL_FUNCTION_TEMPLATE_P (newdecl)) - DECL_ARGUMENTS (old_result) - = DECL_ARGUMENTS (new_result); + { + tree parm; + DECL_ARGUMENTS (old_result) + = DECL_ARGUMENTS (new_result); + for (parm = DECL_ARGUMENTS (old_result); parm; + parm = TREE_CHAIN (parm)) + DECL_CONTEXT (parm) = old_result; + } } return olddecl; @@ -1918,6 +1924,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) if (TREE_CODE (newdecl) == FUNCTION_DECL) { + tree parm; + if (DECL_TEMPLATE_INSTANTIATION (olddecl) && !DECL_TEMPLATE_INSTANTIATION (newdecl)) { @@ -1974,6 +1982,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) /* Preserve abstractness on cloned [cd]tors. */ DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl); + /* Update newdecl's parms to point at olddecl. */ + for (parm = DECL_ARGUMENTS (newdecl); parm; + parm = TREE_CHAIN (parm)) + DECL_CONTEXT (parm) = olddecl; + if (! types_match) { SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); @@ -2006,7 +2019,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) } DECL_RESULT (newdecl) = DECL_RESULT (olddecl); - /* Don't clear out the arguments if we're redefining a function. */ + /* Don't clear out the arguments if we're just redeclaring a + function. */ if (DECL_ARGUMENTS (olddecl)) DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); } @@ -6555,6 +6569,8 @@ grokfndecl (tree ctype, parms = parm; } DECL_ARGUMENTS (decl) = parms; + for (t = parms; t; t = TREE_CHAIN (t)) + DECL_CONTEXT (t) = decl; /* Propagate volatile out from type to decl. */ if (TYPE_VOLATILE (type)) TREE_THIS_VOLATILE (decl) = 1; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d57015005b4..deba8b4e01c 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3907,4 +3907,27 @@ mark_used (tree decl) processing_template_decl = saved_processing_template_decl; } +/* Given function PARM_DECL PARM, return its index in the function's list + of parameters, beginning with 1. */ + +int +parm_index (tree parm) +{ + int index; + tree arg; + + for (index = 1, arg = DECL_ARGUMENTS (DECL_CONTEXT (parm)); + arg; + ++index, arg = TREE_CHAIN (arg)) + { + if (DECL_NAME (parm) == DECL_NAME (arg)) + break; + if (DECL_ARTIFICIAL (arg)) + --index; + } + + gcc_assert (arg); + return index; +} + #include "gt-cp-decl2.h" diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index c72747c768e..eabab7fb510 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2143,27 +2143,6 @@ write_expression (tree expr) { enum tree_code code = TREE_CODE (expr); - /* Inside decltype we can simplify some expressions, since we're only - interested in the type. */ - if (skip_evaluation) - { - tree type = describable_type (expr); - if (type == NULL_TREE) - ; - else if (TREE_CODE (type) == REFERENCE_TYPE) - { - write_string ("sT"); - write_type (TREE_TYPE (type)); - return; - } - else - { - write_string ("sR"); - write_type (type); - return; - } - } - /* Skip NOP_EXPRs. They can occur when (say) a pointer argument is converted (via qualification conversions) to another type. */ @@ -2210,10 +2189,12 @@ write_expression (tree expr) write_template_arg_literal (expr); else if (code == PARM_DECL) { - /* A function parameter used under decltype in a late-specified - return type. Represented with a type placeholder. */ - write_string ("sT"); - write_type (non_reference (TREE_TYPE (expr))); + /* A function parameter used in a late-specified return type. */ + int index = parm_index (expr); + write_string ("fp"); + if (index > 1) + write_unsigned_number (index - 2); + write_char ('_'); } else if (DECL_P (expr)) { @@ -2231,6 +2212,12 @@ write_expression (tree expr) write_string ("st"); write_type (TREE_OPERAND (expr, 0)); } + else if (TREE_CODE (expr) == ALIGNOF_EXPR + && TYPE_P (TREE_OPERAND (expr, 0))) + { + write_string ("at"); + write_type (TREE_OPERAND (expr, 0)); + } else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF) { tree scope = TREE_OPERAND (expr, 0); @@ -2298,9 +2285,16 @@ write_expression (tree expr) write_template_args (template_args); } } + else if (TREE_CODE (expr) == INDIRECT_REF + && TREE_TYPE (TREE_OPERAND (expr, 0)) + && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE) + { + write_expression (TREE_OPERAND (expr, 0)); + } else { int i; + const char *name; /* When we bind a variable or function to a non-type template argument with reference type, we create an ADDR_EXPR to show @@ -2338,7 +2332,14 @@ write_expression (tree expr) } /* If it wasn't any of those, recursively expand the expression. */ - write_string (operator_name_info[(int) code].mangled_name); + name = operator_name_info[(int) code].mangled_name; + if (name == NULL) + { + sorry ("mangling %C", code); + return; + } + else + write_string (name); switch (code) { @@ -2351,23 +2352,29 @@ write_expression (tree expr) case CAST_EXPR: write_type (TREE_TYPE (expr)); - /* There is no way to mangle a zero-operand cast like - "T()". */ - if (!TREE_OPERAND (expr, 0)) - sorry ("zero-operand casts cannot be mangled due to a defect " - "in the C++ ABI"); - else if (list_length (TREE_OPERAND (expr, 0)) > 1) - sorry ("mangling function-style cast with more than one argument"); - else + if (list_length (TREE_OPERAND (expr, 0)) == 1) write_expression (TREE_VALUE (TREE_OPERAND (expr, 0))); + else + { + tree args = TREE_OPERAND (expr, 0); + write_char ('_'); + for (; args; args = TREE_CHAIN (args)) + write_expression (TREE_VALUE (args)); + write_char ('E'); + } break; + /* FIXME these should have a distinct mangling. */ case STATIC_CAST_EXPR: case CONST_CAST_EXPR: write_type (TREE_TYPE (expr)); write_expression (TREE_OPERAND (expr, 0)); break; + case NEW_EXPR: + sorry ("mangling new-expression"); + break; + /* Handle pointers-to-members specially. */ case SCOPE_REF: write_type (TREE_OPERAND (expr, 0)); diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def index 698f0de43f4..20d811b812b 100644 --- a/gcc/cp/operators.def +++ b/gcc/cp/operators.def @@ -94,7 +94,7 @@ DEF_SIMPLE_OPERATOR ("++", PREINCREMENT_EXPR, "pp", 1) DEF_SIMPLE_OPERATOR ("--", PREDECREMENT_EXPR, "mm", 1) DEF_SIMPLE_OPERATOR ("sizeof", SIZEOF_EXPR, "sz", 1) /* These are extensions. */ -DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "v17alignof", 1) +DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", 1) DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", 1) DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8ae4ed511cc..62a7b882015 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2217,17 +2217,21 @@ check_explicit_specialization (tree declarator, the specialization of it. */ if (tsk == tsk_template) { + tree result = DECL_TEMPLATE_RESULT (tmpl); SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); - DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE; + DECL_INITIAL (result) = NULL_TREE; if (have_def) { + tree parm; DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl); - DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl)) + DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (decl); /* We want to use the argument list specified in the definition, not in the original declaration. */ - DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (tmpl)) - = DECL_ARGUMENTS (decl); + DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl); + for (parm = DECL_ARGUMENTS (result); parm; + parm = TREE_CHAIN (parm)) + DECL_CONTEXT (parm) = result; } return tmpl; } @@ -9898,16 +9902,14 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (r == NULL) { /* This can happen for a parameter name used later in a function - declaration (such as in a late-specified return type). - Replace it with an arbitrary expression with the same type - (*(T*)0). This should only occur in an unevaluated context - (i.e. decltype). */ - gcc_assert (skip_evaluation); - r = non_reference (TREE_TYPE (t)); - r = tsubst (r, args, complain, in_decl); - r = build_pointer_type (r); - r = build_c_cast (r, null_node); - return cp_build_indirect_ref (r, NULL, tf_warning_or_error); + declaration (such as in a late-specified return type). Just + make a dummy decl, since it's only used for its type. */ + gcc_assert (skip_evaluation); + r = tsubst_decl (t, args, complain); + /* Give it the template pattern as its context; its true context + hasn't been instantiated yet and this is good enough for + mangling. */ + DECL_CONTEXT (r) = DECL_CONTEXT (t); } if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 82a67971047..c7289700728 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4585,8 +4585,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) break; } } - else - type = describable_type (expr); if (type && !type_uses_auto (type)) return type; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 82f3b89e402..2287f11f04b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1881,9 +1881,8 @@ cp_tree_equal (tree t1, tree t2) case PARM_DECL: /* For comparing uses of parameters in late-specified return types with an out-of-class definition of the function. */ - if ((!DECL_CONTEXT (t1) || !DECL_CONTEXT (t2)) - && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) - && DECL_NAME (t1) == DECL_NAME (t2)) + if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) + && parm_index (t1) == parm_index (t2)) return true; else return false; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 235259478cb..b59350c5444 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-03-17 Jason Merrill + + * g++.dg/cpp0x/auto6.C, auto12.C: Update mangling. + 2009-03-17 Paolo Carlini PR c++/39475 diff --git a/gcc/testsuite/g++.dg/cpp0x/auto12.C b/gcc/testsuite/g++.dg/cpp0x/auto12.C index 437088d654c..45ceedfdc88 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto12.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto12.C @@ -37,16 +37,16 @@ auto A::f(U u) -> decltype (u + i) int main() { - // { dg-final { scan-assembler "_ZN1AIiE1fIiEEDTplsTT_sTiES2_" } } + // { dg-final { scan-assembler "_ZN1AIiE1fIiEEDTplfp_L_ZNS0_1iEEET_" } } A().f(1); - // { dg-final { scan-assembler "_ZN1AIiE2frIiEEDTplsTT_sTiES2_" } } + // { dg-final { scan-assembler "_ZN1AIiE2frIiEEDTplfp_L_ZNS0_2irEEET_" } } A().fr(1); - // { dg-final { scan-assembler "_ZN1AIiE3frrIiEEDTplsTT_sTiES2_" } } + // { dg-final { scan-assembler "_ZN1AIiE3frrIiEEDTplfp_L_ZNS0_3irrEEET_" } } A().frr(1); - // { dg-final { scan-assembler "_ZN1AIiE1gIiEEDTplsTT_sR.ES2_" } } + // { dg-final { scan-assembler "_ZN1AIiE1gIiEEDTplfp_szL_ZNS0_1iEEET_" } } A().g(1); - // { dg-final { scan-assembler "_ZN1AIiE1hIiEEDTplsTT_sr1BIS2_E1iES2_" } } + // { dg-final { scan-assembler "_ZN1AIiE1hIiEEDTplfp_sr1BIT_E1iES3_" } } A().h(1); - // { dg-final { scan-assembler "_ZN1AIiE1jIiEEDTplsTT_sRiES2_" } } + // { dg-final { scan-assembler "_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_" } } A().j(1); } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto6.C b/gcc/testsuite/g++.dg/cpp0x/auto6.C index 7d659c7236a..dfd6a202698 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto6.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto6.C @@ -95,21 +95,21 @@ A a, *p; int main() { - // { dg-final { scan-assembler "_Z3addIidEDTplsTT_sTT0_ES0_S1_" } } + // { dg-final { scan-assembler "_Z3addIidEDTplfp_fp0_ET_T0_" } } auto i = add(1, 2.0); - // { dg-final { scan-assembler "_Z4add4IidEDTplsTT_sTT0_ES0_S1_" } } + // { dg-final { scan-assembler "_Z4add4IidEDTpldecvPT_Li0EdecvPT0_Li0EES0_S2_" } } auto i4 = add4(1, 2.0); - // { dg-final { scan-assembler "_Z4add2IidEDTplsRT_sRT0_ES0_S1_" } } + // { dg-final { scan-assembler "_Z4add2IidEDTplcvT__EcvT0__EES0_S1_" } } auto i2 = add2(1, 2.0); - // { dg-final { scan-assembler "_Z4add3IidEDTclL_Z2agEsTT_sTT0_EES0_S1_" } } + // { dg-final { scan-assembler "_Z4add3IidEDTclL_Z2agEfp_fp0_EET_T0_" } } auto i3 = add3(1, 2.0); - // { dg-final { scan-assembler "_Z1fI1AIiEEDTclptsTPT_1fEES3_" } } + // { dg-final { scan-assembler "_Z1fI1AIiEEDTclptfp_1fEEPT_" } } f(p); - // { dg-final { scan-assembler "_Z1gI1AIiEEDTcldtsTT_1fEES2_" } } + // { dg-final { scan-assembler "_Z1gI1AIiEEDTcldtfp_1fEET_" } } g(a); - // { dg-final { scan-assembler "_Z1hI1AIiEdEDTcldtsTT_1gIT0_EEES2_S3_" } } + // { dg-final { scan-assembler "_Z1hI1AIiEdEDTcldtfp_1gIT0_EEET_S2_" } } h(a,1.0); - // { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtsTT_srNT0_1BIT1_EE3MEMES4_S5_S7_" } } + // { dg-final { scan-assembler "_Z1kI1C1AIiE1DEDtdtfp_srNT0_1BIT1_EE3MEMET_S4_S6_" } } k( C(), A(), D() ); // { dg-final { scan-assembler "_Z1lIiET_S0_" } } l(1); diff --git a/include/ChangeLog b/include/ChangeLog index a07e075f713..64dd0d962af 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2009-03-17 Jason Merrill + + * demangle.h (enum demangle_component_type): Add + DEMANGLE_COMPONENT_FUNCTION_PARAM. + 2008-12-10 Jason Merrill * demangle.h (enum demangle_component_type): Add diff --git a/include/demangle.h b/include/demangle.h index 28c69f5e78c..eb39c7c13c4 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -221,6 +221,8 @@ enum demangle_component_type /* A template parameter. This holds a number, which is the template parameter index. */ DEMANGLE_COMPONENT_TEMPLATE_PARAM, + /* A function parameter. This holds a number, which is the index. */ + DEMANGLE_COMPONENT_FUNCTION_PARAM, /* A constructor. This holds a name and the kind of constructor. */ DEMANGLE_COMPONENT_CTOR, @@ -466,10 +468,10 @@ struct demangle_component int len; } s_string; - /* For DEMANGLE_COMPONENT_TEMPLATE_PARAM. */ + /* For DEMANGLE_COMPONENT_*_PARAM. */ struct { - /* Template parameter index. */ + /* Parameter index. */ long number; } s_number; diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index db7d2878bc0..00aa57a84e4 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,15 @@ +2009-03-17 Jason Merrill + + * cp-demangle.c (d_make_function_param): new fn. + (cplus_demangle_mangled_name): Work around abi v2 bug. + (d_expr_primary): Likewise. + (cplus_demangle_operators): Add alignof ops. + (d_expression): Handle function parameters and conversions + with other than 1 operand. + (d_print_comp): Handle function parameters. Fix bug with + function used in type of function. + * testsuite/demangle-expected: Upate tests. + 2009-02-21 Mark Mitchell * make-temp-file.c (): Include on Windows. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 0b4e05c6e5c..e6d3d5ea902 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -964,6 +964,22 @@ d_make_template_param (struct d_info *di, long i) return p; } +/* Add a new function parameter. */ + +static struct demangle_component * +d_make_function_param (struct d_info *di, long i) +{ + struct demangle_component *p; + + p = d_make_empty (di); + if (p != NULL) + { + p->type = DEMANGLE_COMPONENT_FUNCTION_PARAM; + p->u.s_number.number = i; + } + return p; +} + /* Add a new standard substitution component. */ static struct demangle_component * @@ -989,7 +1005,11 @@ CP_STATIC_IF_GLIBCPP_V3 struct demangle_component * cplus_demangle_mangled_name (struct d_info *di, int top_level) { - if (! d_check_char (di, '_')) + if (! d_check_char (di, '_') + /* Allow missing _ if not at toplevel to work around a + bug in G++ abi-version=2 mangling; see the comment in + write_template_arg. */ + && top_level) return NULL; if (! d_check_char (di, 'Z')) return NULL; @@ -1481,6 +1501,8 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "rs", NL (">>"), 2 }, { "st", NL ("sizeof "), 1 }, { "sz", NL ("sizeof "), 1 }, + { "at", NL ("alignof "), 1 }, + { "az", NL ("alignof "), 1 }, { NULL, NULL, 0, 0 } }; @@ -2564,12 +2586,25 @@ d_expression (struct d_info *di) d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, d_template_args (di))); } - else if (peek == 's' - && (d_peek_next_char (di) == 'T' || d_peek_next_char (di) == 'R')) + else if (peek == 'f' && d_peek_next_char (di) == 'p') { - /* Just demangle a parameter placeholder as its type. */ + /* Function parameter used in a late-specified return type. */ + int index; d_advance (di, 2); - return cplus_demangle_type (di); + if (d_peek_char (di) == '_') + index = 1; + else + { + index = d_number (di); + if (index < 0) + return NULL; + index += 2; + } + + if (! d_check_char (di, '_')) + return NULL; + + return d_make_function_param (di, index); } else if (IS_DIGIT (peek)) { @@ -2619,8 +2654,16 @@ d_expression (struct d_info *di) switch (args) { case 1: - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - d_expression (di)); + { + struct demangle_component *operand; + if (op->type == DEMANGLE_COMPONENT_CAST + && d_check_char (di, '_')) + operand = d_exprlist (di); + else + operand = d_expression (di); + return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, + operand); + } case 2: { struct demangle_component *left; @@ -2671,7 +2714,9 @@ d_expr_primary (struct d_info *di) if (! d_check_char (di, 'L')) return NULL; - if (d_peek_char (di) == '_') + if (d_peek_char (di) == '_' + /* Workaround for G++ bug; see comment in write_template_arg. */ + || d_peek_char (di) == 'Z') ret = cplus_demangle_mangled_name (di, 0); else { @@ -3293,6 +3338,7 @@ d_print_comp (struct d_print_info *dpi, the right place for the type. We also have to pass down any CV-qualifiers, which apply to the this parameter. */ hold_modifiers = dpi->modifiers; + dpi->modifiers = 0; i = 0; typed_name = d_left (dc); while (typed_name != NULL) @@ -3981,6 +4027,15 @@ d_print_comp (struct d_print_info *dpi, } return; + case DEMANGLE_COMPONENT_FUNCTION_PARAM: + { + char buf[25]; + d_append_string (dpi, "parm#"); + sprintf(buf,"%ld", dc->u.s_number.number); + d_append_string (dpi, buf); + return; + } + default: d_print_error (dpi); return; diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index d9efbc0d24e..cded6b5d71a 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -3723,7 +3723,7 @@ foo # This used to crash the demangler--PR 16240 --format=gnu-v3 --no-params _ZN13PatternDriver23StringScalarDeleteValueC1ERKNS_25ConflateStringScalarValueERKNS_25AbstractStringScalarValueERKNS_12TemplateEnumINS_12pdcomplementELZNS_16complement_namesEELZNS_14COMPLEMENTENUMEEEE -_ZN13PatternDriver23StringScalarDeleteValueC1ERKNS_25ConflateStringScalarValueERKNS_25AbstractStringScalarValueERKNS_12TemplateEnumINS_12pdcomplementELZNS_16complement_namesEELZNS_14COMPLEMENTENUMEEEE +PatternDriver::StringScalarDeleteValue::StringScalarDeleteValue(PatternDriver::ConflateStringScalarValue const&, PatternDriver::AbstractStringScalarValue const&, PatternDriver::TemplateEnum const&) PatternDriver::StringScalarDeleteValue::StringScalarDeleteValue # # This used to cause the demangler to walk into undefined memory--PR 22268 @@ -3884,12 +3884,12 @@ _ZGr32_java$Sutil$Siso4217$_properties java resource java/util/iso4217.properties # decltype/param placeholder test --format=gnu-v3 -_Z3addIidEDTplsTT_sTT0_ES0_S1_ -decltype ((int)+(double)) add(int, double) +_Z3addIidEDTplfp_fp0_ET_T0_ +decltype ((parm#1)+(parm#2)) add(int, double) # decltype/fn call test --format=gnu-v3 -_Z4add3IidEDTclL_Z1gEsTT_sTT0_EES0_S1_ -decltype (g(int, double)) add3(int, double) +_Z4add3IidEDTclL_Z1gEfp_fp0_EET_T0_ +decltype (g(parm#1, parm#2)) add3(int, double) # new (2008) built in types test --format=gnu-v3 _Z1fDfDdDeDhDsDi @@ -3900,5 +3900,9 @@ _Z1fIIPiPfPdEEvDpT_ void f(int*, float*, double*) # '.' test --format=gnu-v3 -_Z1hI1AIiEdEDTcldtsTT_1gIT0_EEES2_S3_ -decltype (((A).(g))()) h, double>(A, double) +_Z1hI1AIiEdEDTcldtfp_1gIT0_EEET_S2_ +decltype (((parm#1).(g))()) h, double>(A, double) +# test for typed function in decltype +--format=gnu-v3 +_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_ +decltype ((parm#1)+((x())())) A::j(int) -- 2.30.2