From 59e621fcddabe616abdf2e113b3418fb1770ad00 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 11 Jul 1998 16:20:54 +0000 Subject: [PATCH] cplus-dem.c (string): Move definition before work_stuff. * cplus-dem.c (string): Move definition before work_stuff. (work_stuff): Add volatile_type, forgetting_types, previous_argument, and nrepeats fields. (SCOPE_STRING): New macro. (demangle_template): Add `remember' parameter. Add comment. Register the `B' code type here, if remembering. Tidy. Fix crash on NULL tmpl_argvec. Be consistent with use of tname/trawname. (demangle_nested_args): New function. (internal_cplus_demangle): Handle volatile-qualified member functions. (mop_up): Delete the previous_argument string if present. (demangle_signature): Tidy. Handle volatile-qualified member functions. Handle back-references using the `B' code. Use extra parameter to demangle_template and SCOPE_STRING where appropriate. (demangle_template_value_parm): Fix thinko; 'B' is not an integral code. (demangle_class): Use SCOPE_STRING. (gnu_special): Pass additional argument to demangle_template. Use SCOPE_STRING. (demangle_qualified): Save qualified types for later back-references. Handle constructors and destructors for template types correctly. (do_type): Tidy. Use SCOPE_STRING. Pass extra argument to demangle_template. Use demangled_nested_args. Don't remember qualified types here; that's now done in demangle_qualified. Similarly for templates. (do_arg): Improve commment. Handle 'n' repeat code. (remember_type): Check forgetting_types. (demangle_args): Deal with 'n' repeat codes. Tidy. * method.c (flush_repeats): Add nrepeats parameter. (issue_nrepeats): Likewise. (is_back_referenceable_type): New function. Don't back-reference TEMPLATE_TYPE_PARMs as well as simple types like integers. (build_mangled_name_for_type): Likewise. (build_mangled_name_for_type_with_Gcode): Likewise. (lasttype): Remove. (nrepeats): Likewise. (Nrepeats): Likewise. (start_squangling): Don't clear the variables removed above. (end_squangling): Likewise. (flush_repeats): Tidy. Use nrepeats parameter rather than Nrepeats global. (issue_nrepeats): Likewise, but with nrepeats global. Use is_backreferenceable_type. (build_overload_nested_name): Tidy. Add comment. Use build_mangled_name_for_type. (build_underscore_int): Comment. (build_overload_scope_ref): Use build_mangled_name_for_type. (build_overload_int): Likewise. (build_template_template_parm_names): Tidy. (build_template_parm_names): Use build_mangled_name_for_type. (build_overload_identifier): Add comments. (build_mangled_name_for_type_with_Gcode): Split out from build_mangled_name. (build_mangled_name_for_type): Use it. (build_mangled_name): Rework to use build_mangled_name_for_type and to not use global nrepeats/Nrepeats. Tidy. (process_modifiers): Tidy. (check_btype): Use is_backreferenceable_type. Add comment. Rename `node' to `type'. (process_overload_item): Set numeric_output_need_bar here. Use build_mangled_name_for_type. Tidy. (build_decl_overload_real): Tidy. Don't use Nrepeats. Use build_mangled_name_for_type. From-SVN: r21062 --- gcc/ChangeLog | 32 +++ gcc/cp/ChangeLog | 36 ++++ gcc/cp/method.c | 549 +++++++++++++++++++++++++---------------------- gcc/cplus-dem.c | 360 +++++++++++++++++++++---------- 4 files changed, 601 insertions(+), 376 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6d193264c509..472cbd3cb15b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +Sat Jul 11 16:19:48 1998 Mark Mitchell + + * cplus-dem.c (string): Move definition before work_stuff. + (work_stuff): Add volatile_type, forgetting_types, + previous_argument, and nrepeats fields. + (SCOPE_STRING): New macro. + (demangle_template): Add `remember' parameter. Add comment. + Register the `B' code type here, if remembering. Tidy. Fix crash + on NULL tmpl_argvec. Be consistent with use of tname/trawname. + (demangle_nested_args): New function. + (internal_cplus_demangle): Handle volatile-qualified member + functions. + (mop_up): Delete the previous_argument string if present. + (demangle_signature): Tidy. Handle volatile-qualified member + functions. Handle back-references using the `B' code. Use extra + parameter to demangle_template and SCOPE_STRING where appropriate. + (demangle_template_value_parm): Fix thinko; 'B' is not an integral + code. + (demangle_class): Use SCOPE_STRING. + (gnu_special): Pass additional argument to demangle_template. + Use SCOPE_STRING. + (demangle_qualified): Save qualified types for later + back-references. Handle constructors and destructors for template + types correctly. + (do_type): Tidy. Use SCOPE_STRING. Pass extra argument to + demangle_template. Use demangled_nested_args. Don't remember + qualified types here; that's now done in demangle_qualified. + Similarly for templates. + (do_arg): Improve commment. Handle 'n' repeat code. + (remember_type): Check forgetting_types. + (demangle_args): Deal with 'n' repeat codes. Tidy. + Sat Jul 11 02:59:08 1998 Richard Earnshaw * arm.md (extendhisi2_mem, movhi, movhi_bytes): Propagate the volatile diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index eac51c99adfe..d72b442df2b3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,41 @@ 1998-07-11 Mark Mitchell + * method.c (flush_repeats): Add nrepeats parameter. + (issue_nrepeats): Likewise. + (is_back_referenceable_type): New function. Don't back-reference + TEMPLATE_TYPE_PARMs as well as simple types like integers. + (build_mangled_name_for_type): Likewise. + (build_mangled_name_for_type_with_Gcode): Likewise. + (lasttype): Remove. + (nrepeats): Likewise. + (Nrepeats): Likewise. + (start_squangling): Don't clear the variables removed above. + (end_squangling): Likewise. + (flush_repeats): Tidy. Use nrepeats parameter rather than + Nrepeats global. + (issue_nrepeats): Likewise, but with nrepeats global. Use + is_backreferenceable_type. + (build_overload_nested_name): Tidy. Add comment. Use + build_mangled_name_for_type. + (build_underscore_int): Comment. + (build_overload_scope_ref): Use build_mangled_name_for_type. + (build_overload_int): Likewise. + (build_template_template_parm_names): Tidy. + (build_template_parm_names): Use build_mangled_name_for_type. + (build_overload_identifier): Add comments. + (build_mangled_name_for_type_with_Gcode): Split out from + build_mangled_name. + (build_mangled_name_for_type): Use it. + (build_mangled_name): Rework to use build_mangled_name_for_type + and to not use global nrepeats/Nrepeats. Tidy. + (process_modifiers): Tidy. + (check_btype): Use is_backreferenceable_type. Add comment. + Rename `node' to `type'. + (process_overload_item): Set numeric_output_need_bar here. + Use build_mangled_name_for_type. Tidy. + (build_decl_overload_real): Tidy. Don't use Nrepeats. Use + build_mangled_name_for_type. + * pt.c (push_template_decl_real): Don't look at DECL_TEMPLATE_INFO for TYPE_DECLs. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 51a4abaab8d7..23f52c2679d9 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -57,14 +57,14 @@ static char *scratch_firstobj; static void icat PROTO((HOST_WIDE_INT)); static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT)); -static void flush_repeats PROTO((tree)); +static void flush_repeats PROTO((int, tree)); static void build_overload_identifier PROTO((tree)); static void build_overload_nested_name PROTO((tree)); static void build_overload_int PROTO((tree, int)); static void build_overload_identifier PROTO((tree)); static void build_qualified_name PROTO((tree)); static void build_overload_value PROTO((tree, tree, int)); -static void issue_nrepeats PROTO((tree)); +static void issue_nrepeats PROTO((int, tree)); static char *build_mangled_name PROTO((tree,int,int)); static void process_modifiers PROTO((tree)); static void process_overload_item PROTO((tree,int)); @@ -82,7 +82,10 @@ static int check_ktype PROTO((tree, int)); static int issue_ktype PROTO((tree)); static void build_overload_scope_ref PROTO((tree)); static void build_mangled_template_parm_index PROTO((char *, tree)); +static int is_back_referenceable_type PROTO((tree)); static int check_btype PROTO((tree)); +static void build_mangled_name_for_type PROTO((tree)); +static void build_mangled_name_for_type_with_Gcode PROTO((tree, int)); # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) @@ -173,7 +176,6 @@ do_inline_function_hair (type, friend_list) /* type tables for K and B type compression */ static tree *btypelist = NULL; static tree *ktypelist = NULL; -static tree lasttype = NULL; static int maxbsize = 0; static int maxksize = 0; @@ -181,9 +183,6 @@ static int maxksize = 0; static int maxbtype = 0; static int maxktype = 0; -/* Number of occurrences of last b type seen. */ -static int nrepeats = 0; - /* Array of types seen so far in top-level call to `build_mangled_name'. Allocated and deallocated by caller. */ static tree *typevec = NULL; @@ -192,9 +191,6 @@ static int typevec_size; /* Number of types interned by `build_mangled_name' so far. */ static int maxtype = 0; -/* Number of occurrences of last type seen. */ -static int Nrepeats = 0; - /* Nonzero if we should not try folding parameter types. */ static int nofold; @@ -207,9 +203,7 @@ start_squangling () { if (flag_do_squangling) { - lasttype = NULL; nofold = 0; - nrepeats = 0; maxbtype = 0; maxktype = 0; maxbsize = 50; @@ -224,7 +218,6 @@ end_squangling () { if (flag_do_squangling) { - lasttype = NULL; if (ktypelist) free (ktypelist); if (btypelist) @@ -305,8 +298,9 @@ dicat (lo, hi) OB_PUTC ('0' + ulo); } -static __inline void -flush_repeats (type) +__inline void +flush_repeats (nrepeats, type) + int nrepeats; tree type; { int tindex = 0; @@ -314,50 +308,73 @@ flush_repeats (type) while (typevec[tindex] != type) tindex++; - if (Nrepeats > 1) + if (nrepeats > 1) { OB_PUTC ('N'); - icat (Nrepeats); - if (Nrepeats > 9) + icat (nrepeats); + if (nrepeats > 9) OB_PUTC ('_'); } else OB_PUTC ('T'); - Nrepeats = 0; icat (tindex); if (tindex > 9) OB_PUTC ('_'); } +/* Returns nonzero iff this is a type to which we will want to make + back-references (using the `B' code). */ -/* issue squangling type repeating */ -static void -issue_nrepeats (lasttype) - tree lasttype; +int +is_back_referenceable_type (type) + tree type; { - if (nrepeats == 1) + if (btypelist == NULL) + /* We're not generating any back-references. */ + return 0; + + switch (TREE_CODE (type)) { - switch (TREE_CODE (lasttype)) - { - case INTEGER_TYPE: - case REAL_TYPE: - case VOID_TYPE: - case BOOLEAN_TYPE: - process_overload_item (lasttype, FALSE); - nrepeats = 0; - return; - - default: - break; - } + case INTEGER_TYPE: + case REAL_TYPE: + case VOID_TYPE: + case BOOLEAN_TYPE: + /* These types have single-character manglings, so there's no + point in generating back-references. */ + return 0; + + case TEMPLATE_TYPE_PARM: + /* It would be a bit complex to demangle signatures correctly if + we generated back-references to these, and the manglings of + type parameters are short. */ + return 0; + + default: + return 1; } - OB_PUTC ('n'); - icat (nrepeats); - if (nrepeats > 9) - OB_PUTC ('_'); - nrepeats = 0; } +/* Issue the squangling code indicating NREPEATS repetitions of TYPE, + which was the last parameter type output. */ + +static void +issue_nrepeats (nrepeats, type) + int nrepeats; + tree type; +{ + if (nrepeats == 1 && !is_back_referenceable_type (type)) + /* For types whose manglings are short, don't bother using the + repetition code if there's only one repetition, since the + repetition code will be about as long as the ordinary mangling. */ + build_mangled_name_for_type (type); + else + { + OB_PUTC ('n'); + icat (nrepeats); + if (nrepeats > 9) + OB_PUTC ('_'); + } +} /* Check to see if a tree node has been entered into the Kcode typelist */ /* if not, add it. Return -1 if it isn't found, otherwise return the index */ @@ -410,12 +427,16 @@ issue_ktype (decl) } return FALSE; } + +/* Build a representation for DECL, which may be an entity not at + global scope. If so, a marker indicating that the name is + qualified has already been output, but the qualifying context has + not. */ static void build_overload_nested_name (decl) tree decl; { - tree context; if (ktypelist && issue_ktype (decl)) @@ -433,7 +454,7 @@ build_overload_nested_name (decl) rather than 'T' or some such. */ if (TREE_CODE (context) == TEMPLATE_TYPE_PARM || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM) - build_mangled_name (context, 0, 0); + build_mangled_name_for_type (context); else { if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') @@ -462,6 +483,9 @@ build_overload_nested_name (decl) build_overload_identifier (decl); } +/* Output the decimal representation of I. If I > 9, the decimal + representation is preceeded and followed by an underscore. */ + static void build_underscore_int (i) int i; @@ -479,7 +503,7 @@ build_overload_scope_ref (value) { OB_PUTC2 ('Q', '2'); numeric_output_need_bar = 0; - build_mangled_name (TREE_OPERAND (value, 0), 0, 0); + build_mangled_name_for_type (TREE_OPERAND (value, 0)); build_overload_identifier (TREE_OPERAND (value, 1)); } @@ -539,7 +563,7 @@ build_overload_int (value, in_template) /* We can get here with sizeof, e.g.: template void f(A); */ - process_overload_item (operand, 0); + build_mangled_name_for_type (operand); else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) build_overload_int (operand, in_template); else @@ -825,10 +849,8 @@ build_template_template_parm_names (parmlist) build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm)); } else - { - /* It's a PARM_DECL. */ - build_mangled_name (TREE_TYPE (parm), 0, 0); - } + /* It's a PARM_DECL. */ + build_mangled_name_for_type (TREE_TYPE (parm)); } } @@ -853,14 +875,14 @@ build_template_parm_names (parmlist, arglist) { /* This parameter is a type. */ OB_PUTC ('Z'); - build_mangled_name (arg, 0, 0); + build_mangled_name_for_type (arg); } else if (TREE_CODE (parm) == TEMPLATE_DECL) { /* This parameter is a template. */ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) /* Output parameter declaration, argument index and level */ - build_mangled_name (arg, 0, 0); + build_mangled_name_for_type (arg); else { /* A TEMPLATE_DECL node, output the parameter declaration @@ -876,12 +898,14 @@ build_template_parm_names (parmlist, arglist) { parm = tsubst (parm, arglist, NULL_TREE); /* It's a PARM_DECL. */ - build_mangled_name (TREE_TYPE (parm), 0, 0); + build_mangled_name_for_type (TREE_TYPE (parm)); build_overload_value (parm, arg, uses_template_parms (arglist)); } } } +/* Output the representation for NAME, which is either a TYPE_DECL or + an IDENTIFIER. */ static void build_overload_identifier (name) @@ -895,6 +919,7 @@ build_overload_identifier (name) (TREE_TYPE (name)))) == FUNCTION_DECL))) { + /* NAME is the TYPE_DECL for a template specialization. */ tree template, parmlist, arglist, tname; template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); arglist = innermost_args (TREE_VALUE (template), 0); @@ -969,6 +994,32 @@ build_qualified_name (decl) build_overload_nested_name (decl); } +/* Output the mangled representation for TYPE. If EXTRA_GCODE is + non-zero, mangled names for structure/union types are intentionally + mangled differently from the method described in the ARM. */ + +void +build_mangled_name_for_type_with_Gcode (type, extra_Gcode) + tree type; + int extra_Gcode; +{ + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + type = CANONICAL_TYPE_VARIANT (type); + process_modifiers (type); + process_overload_item (type, extra_Gcode); +} + +/* Like build_mangled_name_for_type_with_Gcode, but never outputs the + `G'. */ + +void +build_mangled_name_for_type (type) + tree type; +{ + build_mangled_name_for_type_with_Gcode (type, 0); +} + /* Given a list of parameters in PARMTYPES, create an unambiguous overload string. Should distinguish any type that C (or C++) can distinguish. I.e., pointers to functions are treated correctly. @@ -993,107 +1044,116 @@ build_overload_name (parmtypes, begin, end) return ret ; } +/* Output the mangled representation for PARMTYPES. If PARMTYPES is a + TREE_LIST, then it is a list of parameter types. Otherwise, + PARMTYPES must be a single type. */ + static char * build_mangled_name (parmtypes, begin, end) tree parmtypes; int begin, end; { - tree parmtype; - if (begin) OB_INIT (); - numeric_output_need_bar = 0; - if (TREE_CODE (parmtypes) != TREE_LIST) /* just one item */ + if (TREE_CODE (parmtypes) != TREE_LIST) + /* There is only one type. */ + build_mangled_name_for_type (parmtypes); + else { - if (TYPE_PTRMEMFUNC_P (parmtypes)) - parmtypes = TYPE_PTRMEMFUNC_FN_TYPE (parmtypes); - parmtypes = CANONICAL_TYPE_VARIANT (parmtypes); - process_modifiers (parmtypes); - process_overload_item (parmtypes, FALSE); - } - else { - for ( ; parmtypes!=NULL; parmtypes = TREE_CHAIN (parmtypes)) - { - parmtype = CANONICAL_TYPE_VARIANT (TREE_VALUE (parmtypes)); - if (flag_do_squangling) /* squangling style repeats */ - { - if (parmtype == lasttype) - { - nrepeats++; - continue; - } - else - if (nrepeats != 0) - { - issue_nrepeats (lasttype); - } - lasttype = parmtype; - } - else - if (!nofold && typevec) - { - /* Every argument gets counted. */ + /* There are several types in a parameter list. */ + int nrepeats = 0; + int old_style_repeats = !flag_do_squangling && !nofold && typevec; + tree last_type = NULL_TREE; + + for (; parmtypes && parmtypes != void_list_node; + parmtypes = TREE_CHAIN (parmtypes)) + { + tree parmtype = CANONICAL_TYPE_VARIANT (TREE_VALUE (parmtypes)); + + if (old_style_repeats) + { + /* Every argument gets counted. */ my_friendly_assert (maxtype < typevec_size, 387); - typevec[maxtype++] = parmtype; + typevec[maxtype++] = parmtype; + } - if (TREE_USED (parmtype) && parmtype == typevec[maxtype-2] - && ! TYPE_FOR_JAVA (parmtype)) - { - Nrepeats++; - continue; - } + if (parmtype == last_type) + { + if (flag_do_squangling + || (old_style_repeats && TREE_USED (parmtype) + && !TYPE_FOR_JAVA (parmtype))) + { + /* The next type is the same as this one. Keep + track of the repetition, and output the repeat + count later. */ + nrepeats++; + continue; + } + } + else if (nrepeats != 0) + { + /* Indicate how many times the previous parameter was + repeated. */ + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + last_type = parmtype; - if (Nrepeats) - flush_repeats (typevec[maxtype-2]); + if (old_style_repeats) + { + if (nrepeats) + { + flush_repeats (nrepeats, last_type); + nrepeats = 0; + } - if (TREE_USED (parmtype)) - { + if (TREE_USED (parmtype)) + { #if 0 - /* We can turn this on at some point when we want - improved symbol mangling. */ - Nrepeats++; + /* We can turn this on at some point when we want + improved symbol mangling. */ + nrepeats++; #else - /* This is bug compatible with 2.7.x */ - flush_repeats (parmtype); + /* This is bug compatible with 2.7.x */ + flush_repeats (nrepeats, parmtype); #endif - continue; - } - - /* Only cache types which take more than one character. */ - if ((parmtype != TYPE_MAIN_VARIANT (parmtype) + nrepeats = 0; + continue; + } + + /* Only cache types which take more than one character. */ + if ((parmtype != TYPE_MAIN_VARIANT (parmtype) || (TREE_CODE (parmtype) != INTEGER_TYPE && TREE_CODE (parmtype) != REAL_TYPE)) && ! TYPE_FOR_JAVA (parmtype)) - TREE_USED (parmtype) = 1; - } - if (TYPE_PTRMEMFUNC_P (parmtype)) - parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype); - process_modifiers (parmtype); - if (TREE_CODE(parmtype)==VOID_TYPE) - { -#if 0 - extern tree void_list_node; + TREE_USED (parmtype) = 1; + } + + /* Output the PARMTYPE. */ + build_mangled_name_for_type_with_Gcode (parmtype, 1); + } + + /* Output the repeat count for the last parameter, if + necessary. */ + if (nrepeats != 0) + { + if (old_style_repeats) + flush_repeats (nrepeats, last_type); + else + issue_nrepeats (nrepeats, last_type); + nrepeats = 0; + } + + if (!parmtypes) + /* The parameter list ends in an ellipsis. */ + OB_PUTC ('e'); + } - /* See if anybody is wasting memory. */ - my_friendly_assert (parmtypes == void_list_node, 247); -#endif - /* This is the end of a parameter list. */ - if (end) - OB_FINISH (); - return (char *)obstack_base (&scratch_obstack); - } - process_overload_item (parmtype, TRUE); - } - if (flag_do_squangling && nrepeats != 0) - issue_nrepeats (lasttype); - else - if (Nrepeats && typevec) - flush_repeats (typevec[maxtype-1]); - - /* To get here, parms must end with `...'. */ - OB_PUTC ('e'); - } if (end) OB_FINISH (); return (char *)obstack_base (&scratch_obstack); @@ -1104,63 +1164,57 @@ void process_modifiers (parmtype) tree parmtype; { - - if (TREE_READONLY (parmtype)) OB_PUTC ('C'); if (TREE_CODE (parmtype) == INTEGER_TYPE && (TYPE_MAIN_VARIANT (parmtype) == unsigned_type (TYPE_MAIN_VARIANT (parmtype))) && ! TYPE_FOR_JAVA (parmtype)) - { - OB_PUTC ('U'); - } + OB_PUTC ('U'); if (TYPE_VOLATILE (parmtype)) OB_PUTC ('V'); } -/* Check to see if a tree node has been entered into the Bcode typelist - if not, add it. Otherwise emit the code and return TRUE */ -static int -check_btype (node) - tree node; +/* Check to see if TYPE has been entered into the Bcode typelist. If + so, return 1 and emit a backreference to TYPE. Otherwise, add TYPE + to the list of back-referenceable types and return 0. */ + +int +check_btype (type) + tree type; { int x; if (btypelist == NULL) return 0; - switch (TREE_CODE (node)) - { - case INTEGER_TYPE: - case REAL_TYPE: - case VOID_TYPE: - case BOOLEAN_TYPE: - return 0; /* don't compress single char basic types */ + if (!is_back_referenceable_type (type)) + return 0; - default: - break; - } + /* We assume that our caller has put out any necessary + qualifiers. */ + type = TYPE_MAIN_VARIANT (type); - node = TYPE_MAIN_VARIANT (node); for (x = 0; x < maxbtype; x++) - { - if (node == btypelist[x]) - { - OB_PUTC ('B'); - icat (x); - if (x > 9) - OB_PUTC ('_'); - return 1 ; - } - } - /* didn't find it, so add it here */ + if (type == btypelist[x]) + { + OB_PUTC ('B'); + icat (x); + if (x > 9) + OB_PUTC ('_'); + return 1 ; + } + if (maxbsize <= maxbtype) { + /* Enlarge the table. */ maxbsize = maxbsize * 3 / 2; btypelist = (tree *)xrealloc (btypelist, sizeof (tree) * maxbsize); } - btypelist[maxbtype++] = node; + + /* Register the TYPE. */ + btypelist[maxbtype++] = type; + return 0; } @@ -1170,6 +1224,7 @@ process_overload_item (parmtype, extra_Gcode) tree parmtype; int extra_Gcode; { + numeric_output_need_bar = 0; /* These tree types are considered modifiers for B code squangling , */ /* and therefore should not get entries in the Btypelist */ @@ -1206,7 +1261,7 @@ process_overload_item (parmtype, extra_Gcode) case POINTER_TYPE: OB_PUTC ('P'); more: - build_mangled_name (TREE_TYPE (parmtype), 0, 0); + build_mangled_name_for_type (TREE_TYPE (parmtype)); return; break; @@ -1214,77 +1269,57 @@ process_overload_item (parmtype, extra_Gcode) break; } - /* check if type is already in the typelist. If not, add it now */ - - if (flag_do_squangling && btypelist != NULL) { - if (check_btype (parmtype)) /* emits the code if it finds it */ - return; - } + if (flag_do_squangling && check_btype (parmtype)) + /* If PARMTYPE is already in the list of back-referenceable types, + then check_btype will output the appropriate reference, and + there's nothing more to do. */ + return; switch (TREE_CODE (parmtype)) { case OFFSET_TYPE: OB_PUTC ('O'); - build_mangled_name (TYPE_OFFSET_BASETYPE (parmtype), 0, 0); + build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype)); OB_PUTC ('_'); - build_mangled_name (TREE_TYPE (parmtype), 0, 0); + build_mangled_name_for_type (TREE_TYPE (parmtype)); break; case FUNCTION_TYPE: case METHOD_TYPE: { - tree firstarg = TYPE_ARG_TYPES (parmtype); - /* Otherwise have to implement reentrant typevecs, - unmark and remark types, etc. */ - int old_nofold = nofold; - if (!flag_do_squangling) { - nofold = 1; - if (Nrepeats) - flush_repeats (typevec[maxtype-1]); - } - else - if (nrepeats != 0) - issue_nrepeats (lasttype); + tree parms = TYPE_ARG_TYPES (parmtype); - /* @@ It may be possible to pass a function type in - which is not preceded by a 'P'. */ - if (TREE_CODE (parmtype) == FUNCTION_TYPE) - { - OB_PUTC ('F'); - if (firstarg == NULL_TREE) - OB_PUTC ('e'); - else if (firstarg == void_list_node) - OB_PUTC ('v'); - else - build_mangled_name (firstarg, 0, 0); - } - else - { - int constp = TYPE_READONLY (TREE_TYPE (TREE_VALUE (firstarg))); - int volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (firstarg))); + /* Rather than implementing a reentrant TYPEVEC, we turn off + repeat codes here, unless we're squangling. Squangling + doesn't make use of the TYPEVEC, so there's no reentrancy + problem. */ + int old_nofold = nofold; + if (!flag_do_squangling) + nofold = 1; + + if (TREE_CODE (parmtype) == METHOD_TYPE) + { + /* Mark this as a method. */ OB_PUTC ('M'); - firstarg = TREE_CHAIN (firstarg); - - build_mangled_name (TYPE_METHOD_BASETYPE (parmtype), 0, 0); - if (constp) - OB_PUTC ('C'); - if (volatilep) - OB_PUTC ('V'); - - /* For cfront 2.0 compatibility. */ - OB_PUTC ('F'); - - if (firstarg == NULL_TREE) - OB_PUTC ('e'); - else if (firstarg == void_list_node) - OB_PUTC ('v'); - else - build_mangled_name (firstarg, 0, 0); - } + /* Output the class of which this method is a member. */ + build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype)); + /* Output any qualifiers for the `this' parameter. */ + process_modifiers (TREE_TYPE (TREE_VALUE (parms))); + } - /* Separate args from return type. */ + /* Output the parameter types. */ + OB_PUTC ('F'); + if (parms == NULL_TREE) + OB_PUTC ('e'); + else if (parms == void_list_node) + OB_PUTC ('v'); + else + build_mangled_name (parms, 0, 0); + + /* Output the return type. */ OB_PUTC ('_'); - build_mangled_name (TREE_TYPE (parmtype), 0, 0); + build_mangled_name_for_type (TREE_TYPE (parmtype)); + nofold = old_nofold; break; } @@ -1350,7 +1385,7 @@ process_overload_item (parmtype, extra_Gcode) case COMPLEX_TYPE: OB_PUTC ('J'); - build_mangled_name (TREE_TYPE (parmtype), 0, 0); + build_mangled_name_for_type (TREE_TYPE (parmtype)); break; case VOID_TYPE: @@ -1492,41 +1527,20 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs, and figure out its name without any extra encoding. */ OB_PUTC2 ('_', '_'); - if (for_method) - { -#if 0 - /* We can get away without doing this. */ - OB_PUTC ('M'); -#endif - if (tparms != NULL_TREE) - OB_PUTC ('H'); - { - tree this_type = TREE_VALUE (parms); - - if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ - parms = temp_tree_cons (NULL_TREE, SIGNATURE_TYPE (this_type), - TREE_CHAIN (parms)); - else - parms = temp_tree_cons (NULL_TREE, TREE_TYPE (this_type), - TREE_CHAIN (parms)); - } - } - else if (tparms) - OB_PUTC ('H'); - /* XXX this works only if we call this in the same namespace - as the declaration. Unfortunately, we don't have the _DECL, - only its name */ - else if (current_namespace == global_namespace) - OB_PUTC ('F'); if (tparms) { + OB_PUTC ('H'); build_template_parm_names (tparms, targs); OB_PUTC ('_'); } - - /* qualify with namespace */ - if (!for_method && current_namespace != global_namespace) + else if (!for_method && current_namespace == global_namespace) + /* XXX this works only if we call this in the same namespace + as the declaration. Unfortunately, we don't have the _DECL, + only its name */ + OB_PUTC ('F'); + else if (!for_method) + /* qualify with namespace */ build_qualified_name (current_namespace); if (parms == NULL_TREE) @@ -1538,7 +1552,6 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs, if (!flag_do_squangling) /* Allocate typevec array. */ { maxtype = 0; - Nrepeats = 0; typevec_size = list_length (parms); if (!for_method && current_namespace != global_namespace) /* the namespace of a global function needs one slot */ @@ -1546,15 +1559,29 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs, typevec = (tree *)alloca (typevec_size * sizeof (tree)); } nofold = 0; + if (for_method) { - build_mangled_name (TREE_VALUE (parms), 0, 0); + tree this_type = TREE_VALUE (parms); - if (!flag_do_squangling) { - my_friendly_assert (maxtype < typevec_size, 387); - typevec[maxtype++] = TREE_VALUE (parms); - TREE_USED (TREE_VALUE (parms)) = 1; - } + if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ + this_type = SIGNATURE_TYPE (this_type); + else + this_type = TREE_TYPE (this_type); + + build_mangled_name_for_type (this_type); + + if (!flag_do_squangling) + { + my_friendly_assert (maxtype < typevec_size, 387); + typevec[maxtype++] = this_type; + TREE_USED (this_type) = 1; + + /* By setting up PARMS in this way, the loop below will + automatically clear TREE_USED on THIS_TYPE. */ + parms = temp_tree_cons (NULL_TREE, this_type, + TREE_CHAIN (parms)); + } if (TREE_CHAIN (parms)) build_mangled_name (TREE_CHAIN (parms), 0, 0); @@ -1594,7 +1621,7 @@ build_decl_overload_real (dname, parms, ret_type, tparms, targs, { /* Add the return type. */ OB_PUTC ('_'); - build_mangled_name (ret_type, 0, 0); + build_mangled_name_for_type (ret_type); } OB_FINISH (); diff --git a/gcc/cplus-dem.c b/gcc/cplus-dem.c index b05c948481bb..ce67d2288e4e 100644 --- a/gcc/cplus-dem.c +++ b/gcc/cplus-dem.c @@ -94,6 +94,13 @@ set_cplus_marker_for_demangling (ch) cplus_markers[0] = ch; } +typedef struct string /* Beware: these aren't required to be */ +{ /* '\0' terminated. */ + char *b; /* pointer to start of string */ + char *p; /* pointer after last character */ + char *e; /* pointer after end of allocated space */ +} string; + /* Stuff that is shared between sub-routines. Using a shared structure allows cplus_demangle to be reentrant. */ @@ -113,8 +120,14 @@ struct work_stuff int destructor; int static_type; /* A static member function */ int const_type; /* A const member function */ + int volatile_type; /* A volatile member function */ char **tmpl_argvec; /* Template function arguments. */ int ntmpl_args; /* The number of template function arguments. */ + int forgetting_types; /* Nonzero if we are not remembering the types + we see. */ + string* previous_argument; /* The last function argument demangled. */ + int nrepeats; /* The number of times to repeat the previous + argument. */ }; #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) @@ -208,13 +221,6 @@ static const struct optable }; -typedef struct string /* Beware: these aren't required to be */ -{ /* '\0' terminated. */ - char *b; /* pointer to start of string */ - char *p; /* pointer after last character */ - char *e; /* pointer after end of allocated space */ -} string; - #define STRING_EMPTY(str) ((str) -> b == (str) -> p) #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ string_prepend(str, " ");} @@ -222,6 +228,10 @@ typedef struct string /* Beware: these aren't required to be */ string_append(str, " ");} #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b)) +/* The scope separator appropriate for the language being demangled. */ +#define SCOPE_STRING(work) \ + (((work)->options & DMGL_JAVA) ? "." : "::") + #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ @@ -247,7 +257,7 @@ demangle_template_template_parm PARAMS ((struct work_stuff *work, static int demangle_template PARAMS ((struct work_stuff *work, const char **, string *, - string *, int)); + string *, int, int)); static int arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **, @@ -325,6 +335,9 @@ consume_count_with_underscores PARAMS ((const char**)); static int demangle_args PARAMS ((struct work_stuff *, const char **, string *)); +static int +demangle_nested_args PARAMS ((struct work_stuff*, const char**, string*)); + static int do_type PARAMS ((struct work_stuff *, const char **, string *)); @@ -631,12 +644,15 @@ internal_cplus_demangle (work, mangled) int success = 0; char *demangled = NULL; int s1,s2,s3,s4; + int saved_volatile_type; s1 = work->constructor; s2 = work->destructor; s3 = work->static_type; s4 = work->const_type; + saved_volatile_type = work->volatile_type; work->constructor = work->destructor = 0; work->static_type = work->const_type = 0; + work->volatile_type = 0; if ((mangled != NULL) && (*mangled != '\0')) { @@ -677,6 +693,7 @@ internal_cplus_demangle (work, mangled) work->destructor = s2; work->static_type = s3; work->const_type = s4; + work->volatile_type = saved_volatile_type; return (demangled); } @@ -727,6 +744,11 @@ mop_up (work, declp, success) free ((char*) work->tmpl_argvec); work->tmpl_argvec = NULL; } + if (work->previous_argument) + { + string_delete (work->previous_argument); + free ((char*) work->previous_argument); + } /* If demangling was successful, ensure that the demangled string is null terminated and return it. Otherwise, free the demangling decl. */ @@ -795,13 +817,9 @@ demangle_signature (work, mangled, declp) oldmangled = *mangled; success = demangle_qualified (work, mangled, declp, 1, 0); if (success) - { - remember_type (work, oldmangled, *mangled - oldmangled); - } + remember_type (work, oldmangled, *mangled - oldmangled); if (AUTO_DEMANGLING || GNU_DEMANGLING) - { - expect_func = 1; - } + expect_func = 1; oldmangled = NULL; break; @@ -826,13 +844,16 @@ demangle_signature (work, mangled, declp) break; case 'C': - /* a const member function */ + case 'V': + if (**mangled == 'C') + work -> const_type = 1; + else + work->volatile_type = 1; + + /* a qualified member function */ if (oldmangled == NULL) - { - oldmangled = *mangled; - } + oldmangled = *mangled; (*mangled)++; - work -> const_type = 1; break; case '0': case '1': case '2': case '3': case '4': @@ -852,7 +873,21 @@ demangle_signature (work, mangled, declp) } oldmangled = NULL; break; - + + case 'B': + { + string s; + success = do_type (work, mangled, &s); + if (success) + { + string_append (&s, SCOPE_STRING (work)); + string_prepends (declp, &s); + } + oldmangled = NULL; + expect_func = 1; + } + break; + case 'F': /* Function */ /* ARM style demangling includes a specific 'F' character after @@ -884,12 +919,13 @@ demangle_signature (work, mangled, declp) { oldmangled = *mangled; } - success = demangle_template (work, mangled, &tname, &trawname, 1); + success = demangle_template (work, mangled, &tname, + &trawname, 1, 1); if (success) { remember_type (work, oldmangled, *mangled - oldmangled); } - string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append(&tname, SCOPE_STRING (work)); string_prepends(declp, &tname); if (work -> destructor & 1) { @@ -936,7 +972,8 @@ demangle_signature (work, mangled, declp) if (GNU_DEMANGLING) { /* A G++ template function. Read the template arguments. */ - success = demangle_template (work, mangled, declp, 0, 0); + success = demangle_template (work, mangled, declp, 0, 0, + 0); if (!(work->constructor & 1)) expect_return_type = 1; (*mangled)++; @@ -993,13 +1030,12 @@ demangle_signature (work, mangled, declp) } } if (success && work -> static_type && PRINT_ARG_TYPES) - { - string_append (declp, " static"); - } + string_append (declp, " static"); if (success && work -> const_type && PRINT_ARG_TYPES) - { - string_append (declp, " const"); - } + string_append (declp, " const"); + else if (success && work->volatile_type && PRINT_ARG_TYPES) + string_append (declp, " volatile"); + return (success); } @@ -1211,12 +1247,10 @@ demangle_template_value_parm (work, mangled, s) continue; case 'E': /* expression */ case 'Q': /* qualified name */ - case 'K': /* qualified name */ - done = is_integral = 1; - break; - case 'B': /* squangled name */ + case 'K': /* qualified name */ done = is_integral = 1; break; + case 'B': /* remembered type */ case 'T': /* remembered type */ abort (); break; @@ -1360,13 +1394,22 @@ demangle_template_value_parm (work, mangled, s) return success; } +/* Demangle the template name in MANGLED. The full name of the + template (e.g., S) is placed in TNAME. The name without the + template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is + non-NULL. If IS_TYPE is nonzero, this template is a type template, + not a function template. If both IS_TYPE and REMEMBER are nonzero, + the tmeplate is remembered in the list of back-referenceable + types. */ + static int -demangle_template (work, mangled, tname, trawname, is_type) +demangle_template (work, mangled, tname, trawname, is_type, remember) struct work_stuff *work; const char **mangled; string *tname; string *trawname; int is_type; + int remember; { int i; int r; @@ -1375,10 +1418,13 @@ demangle_template (work, mangled, tname, trawname, is_type) const char *start; int is_java_array = 0; string temp; + int bindex; (*mangled)++; if (is_type) { + if (remember) + bindex = register_Btype (work); start = *mangled; /* get template name */ if (**mangled == 'z') @@ -1391,9 +1437,8 @@ demangle_template (work, mangled, tname, trawname, is_type) if (idx == -1 || (work->tmpl_argvec && idx >= work->ntmpl_args) || consume_count_with_underscores (mangled) == -1) - { - return (0); - } + return (0); + if (work->tmpl_argvec) { string_append (tname, work->tmpl_argvec[idx]); @@ -1406,7 +1451,7 @@ demangle_template (work, mangled, tname, trawname, is_type) sprintf(buf, "T%d", idx); string_append (tname, buf); if (trawname) - string_append (trawname, work->tmpl_argvec[idx]); + string_append (trawname, buf); } } else @@ -1415,13 +1460,13 @@ demangle_template (work, mangled, tname, trawname, is_type) { return (0); } - if (trawname) - string_appendn (trawname, *mangled, r); is_java_array = (work -> options & DMGL_JAVA) && strncmp (*mangled, "JArray1Z", 8) == 0; if (! is_java_array) { string_appendn (tname, *mangled, r); + if (trawname) + string_appendn (trawname, *mangled, r); } *mangled += r; } @@ -1565,6 +1610,9 @@ demangle_template (work, mangled, tname, trawname, is_type) string_append (tname, ">"); } + if (is_type && remember) + remember_Btype (work, tname->b, LEN_STRING (tname), bindex); + /* if (work -> static_type) { @@ -1722,7 +1770,7 @@ demangle_class (work, mangled, declp) } remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); - string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::"); + string_prepend (declp, SCOPE_STRING (work)); string_prepends (declp, &class_name); success = 1; } @@ -1996,7 +2044,8 @@ gnu_special (work, mangled, declp) success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0, 1); + success = demangle_template (work, mangled, declp, 0, 1, + 1); break; default: if (isdigit(*mangled[0])) @@ -2024,8 +2073,7 @@ gnu_special (work, mangled, declp) { if (p != NULL) { - string_append (declp, - (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (declp, SCOPE_STRING (work)); (*mangled)++; } } @@ -2051,7 +2099,7 @@ gnu_special (work, mangled, declp) success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0, 1); + success = demangle_template (work, mangled, declp, 0, 1, 1); break; default: n = consume_count (mangled); @@ -2063,7 +2111,7 @@ gnu_special (work, mangled, declp) /* Consumed everything up to the cplus_marker, append the variable name. */ (*mangled)++; - string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (declp, SCOPE_STRING (work)); n = strlen (*mangled); string_appendn (declp, *mangled, n); (*mangled) += n; @@ -2104,7 +2152,7 @@ gnu_special (work, mangled, declp) success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0, 1); + success = demangle_template (work, mangled, declp, 0, 1, 1); break; default: success = demangle_fund_type (work, mangled, declp); @@ -2236,13 +2284,20 @@ demangle_qualified (work, mangled, result, isfuncname, append) int append; { int qualifiers = 0; - int namelength; int success = 1; const char *p; char num[2]; string temp; + string last_name; + int bindex = register_Btype (work); + + /* We only make use of ISFUNCNAME if the entity is a constructor or + destructor. */ + isfuncname = (isfuncname + && ((work->constructor & 1) || (work->destructor & 1))); string_init (&temp); + string_init (&last_name); if ((*mangled)[0] == 'K') { @@ -2315,18 +2370,24 @@ demangle_qualified (work, mangled, result, isfuncname, append) while (qualifiers-- > 0) { int remember_K = 1; + string_clear (&last_name); + if (*mangled[0] == '_') - *mangled = *mangled + 1; + (*mangled)++; + if (*mangled[0] == 't') { - success = demangle_template(work, mangled, &temp, 0, 1); - if (!success) break; - } - else if (*mangled[0] == 'X') - { - success = do_type (work, mangled, &temp); - if (!success) break; - } + /* Here we always append to TEMP since we will want to use + the template name without the template parameters as a + constructor or destructor name. The appropriate + (parameter-less) value is returned by demangle_template + in LAST_NAME. We do not remember the template type here, + in order to match the G++ mangling algorithm. */ + success = demangle_template(work, mangled, &temp, + &last_name, 1, 0); + if (!success) + break; + } else if (*mangled[0] == 'K') { int idx; @@ -2341,60 +2402,48 @@ demangle_qualified (work, mangled, result, isfuncname, append) if (!success) break; } else - { - namelength = consume_count (mangled); - if (strlen (*mangled) < namelength) - { - /* Simple sanity check failed */ - success = 0; - break; - } - string_appendn (&temp, *mangled, namelength); - *mangled += namelength; + { + success = do_type (work, mangled, &last_name); + if (!success) + break; + string_appends (&temp, &last_name); } if (remember_K) - { - remember_Ktype (work, temp.b, LEN_STRING (&temp)); - } + remember_Ktype (work, temp.b, LEN_STRING (&temp)); if (qualifiers > 0) - { - string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); - } + string_append (&temp, SCOPE_STRING (work)); } + remember_Btype (work, temp.b, LEN_STRING (&temp), bindex); + /* If we are using the result as a function name, we need to append the appropriate '::' separated constructor or destructor name. We do this here because this is the most convenient place, where we already have a pointer to the name and the length of the name. */ - if (isfuncname && (work->constructor & 1 || work->destructor & 1)) + if (isfuncname) { - string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (&temp, SCOPE_STRING (work)); if (work -> destructor & 1) - { - string_append (&temp, "~"); - } - string_appendn (&temp, (*mangled) - namelength, namelength); + string_append (&temp, "~"); + string_appends (&temp, &last_name); } /* Now either prepend the temp buffer to the result, or append it, depending upon the state of the append flag. */ if (append) - { - string_appends (result, &temp); - } + string_appends (result, &temp); else { if (!STRING_EMPTY (result)) - { - string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); - } + string_append (&temp, SCOPE_STRING (work)); string_prepends (result, &temp); } + string_delete (&last_name); string_delete (&temp); return (success); } @@ -2542,15 +2591,14 @@ do_type (work, mangled, result) /* After picking off the function args, we expect to either find the function return type (preceded by an '_') or the end of the string. */ - if (!demangle_args (work, mangled, &decl) + if (!demangle_nested_args (work, mangled, &decl) || (**mangled != '_' && **mangled != '\0')) { success = 0; + break; } if (success && (**mangled == '_')) - { - (*mangled)++; - } + (*mangled)++; break; case 'M': @@ -2568,7 +2616,7 @@ do_type (work, mangled, result) } string_append (&decl, ")"); - string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::"); + string_prepend (&decl, SCOPE_STRING (work)); if (isdigit (**mangled)) { n = consume_count (mangled); @@ -2584,7 +2632,8 @@ do_type (work, mangled, result) { string temp; string_init (&temp); - success = demangle_template (work, mangled, &temp, NULL, 1); + success = demangle_template (work, mangled, &temp, + NULL, 1, 1); if (success) { string_prependn (&decl, temp.b, temp.p - temp.b); @@ -2612,7 +2661,7 @@ do_type (work, mangled, result) break; } } - if ((member && !demangle_args (work, mangled, &decl)) + if ((member && !demangle_nested_args (work, mangled, &decl)) || **mangled != '_') { success = 0; @@ -2673,10 +2722,7 @@ do_type (work, mangled, result) case 'Q': case 'K': { - int btype = register_Btype (work); success = demangle_qualified (work, mangled, result, 0, 1); - remember_Btype (work, result->b, LEN_STRING (result), btype); - break; } @@ -2906,9 +2952,7 @@ demangle_fund_type (work, mangled, result) } case 't': { - int bindex= register_Btype (work); - success = demangle_template (work, mangled, &btype, 0, 1); - remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); + success = demangle_template (work, mangled, &btype, 0, 1, 1); string_appends (result, &btype); break; } @@ -2920,7 +2964,9 @@ demangle_fund_type (work, mangled, result) return (success); } -/* `result' will be initialized in do_type; it will be freed on failure */ +/* Demangle the next argument, given by MANGLED into RESULT, which + *should be an uninitialized* string. It will be initialized here, + and free'd should anything go wrong. */ static int do_arg (work, mangled, result) @@ -2928,17 +2974,67 @@ do_arg (work, mangled, result) const char **mangled; string *result; { + /* Remember where we started so that we can record the type, for + non-squangling type remembering. */ const char *start = *mangled; - if (!do_type (work, mangled, result)) + string_init (result); + + if (work->nrepeats > 0) { - return (0); + --work->nrepeats; + + if (work->previous_argument == 0) + return 0; + + /* We want to reissue the previous type in this argument list. */ + string_appends (result, work->previous_argument); + return 1; + } + + if (**mangled == 'n') + { + /* A squangling-style repeat. */ + (*mangled)++; + work->nrepeats = consume_count(mangled); + + if (work->nrepeats == 0) + /* This was not a repeat count after all. */ + return 0; + + if (work->nrepeats > 9) + { + if (**mangled != '_') + /* The repeat count should be followed by an '_' in this + case. */ + return 0; + else + (*mangled)++; + } + + /* Now, the repeat is all set up. */ + return do_arg (work, mangled, result); } + + /* Save the result in WORK->previous_argument so that we can find it + if it's repeated. Note that saving START is not good enough: we + do not want to add additional types to the back-referenceable + type vector when processing a repeated type. */ + if (work->previous_argument) + string_clear (work->previous_argument); else { - remember_type (work, start, *mangled - start); - return (1); + work->previous_argument = (string*) xmalloc (sizeof (string)); + string_init (work->previous_argument); } + + if (!do_type (work, mangled, work->previous_argument)) + return 0; + + string_appends (result, work->previous_argument); + + remember_type (work, start, *mangled - start); + return 1; } static void @@ -2949,6 +3045,9 @@ remember_type (work, start, len) { char *tem; + if (work->forgetting_types) + return; + if (work -> ntypes >= work -> typevec_size) { if (work -> typevec_size == 0) @@ -3160,7 +3259,8 @@ demangle_args (work, mangled, declp) } } - while (**mangled != '_' && **mangled != '\0' && **mangled != 'e') + while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e') + || work->nrepeats > 0) { if ((**mangled == 'N') || (**mangled == 'T')) { @@ -3207,7 +3307,7 @@ demangle_args (work, mangled, declp) { return (0); } - while (--r >= 0) + while (work->nrepeats > 0 || --r >= 0) { tem = work -> typevec[t]; if (need_comma && PRINT_ARG_TYPES) @@ -3228,18 +3328,12 @@ demangle_args (work, mangled, declp) } else { - if (need_comma & PRINT_ARG_TYPES) - { - string_append (declp, ", "); - } + if (need_comma && PRINT_ARG_TYPES) + string_append (declp, ", "); if (!do_arg (work, mangled, &arg)) - { - return (0); - } + return (0); if (PRINT_ARG_TYPES) - { - string_appends (declp, &arg); - } + string_appends (declp, &arg); string_delete (&arg); need_comma = 1; } @@ -3265,6 +3359,42 @@ demangle_args (work, mangled, declp) return (1); } +/* Like demangle_args, but for demangling the argument lists of function + and method pointers or references, not top-level declarations. */ + +int +demangle_nested_args (work, mangled, declp) + struct work_stuff *work; + const char **mangled; + string *declp; +{ + string* saved_previous_argument; + int result; + int saved_nrepeats; + + /* The G++ name-mangling algorithm does not remember types on nested + argument lists, unless -fsquangling is used, and in that case the + type vector updated by remember_type is not used. So, we turn + off remembering of types here. */ + ++work->forgetting_types; + + /* For the repeat codes used with -fsquangling, we must keep track of + the last argument. */ + saved_previous_argument = work->previous_argument; + saved_nrepeats = work->nrepeats; + work->previous_argument = 0; + work->nrepeats = 0; + + /* Actually demangle the arguments. */ + result = demangle_args (work, mangled, declp); + + /* Restore the previous_argument field. */ + if (work->previous_argument) + string_delete (work->previous_argument); + work->previous_argument = saved_previous_argument; + work->nrepeats = saved_nrepeats; +} + static void demangle_function_name (work, mangled, declp, scan) struct work_stuff *work; -- 2.47.2