From 00fe194baccfcd63ce4b29824ed07864c8980f70 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Wed, 19 Nov 2003 16:19:14 +0000 Subject: merge from gcc --- libiberty/cp-demangle.c | 145 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 125 insertions(+), 20 deletions(-) (limited to 'libiberty/cp-demangle.c') diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index bd4882239fb..a707a833402 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -1147,7 +1147,7 @@ demangle_name (dm, encode_return_type) /* Demangles and emits a . - ::= N [] E */ + ::= N [] E */ static status_t demangle_nested_name (dm, encode_return_type) @@ -1662,7 +1662,7 @@ demangle_operator_name (dm, short_name, num_args, type_arg) { "rS", ">>=" , 2 }, { "rm", "%" , 2 }, { "rs", ">>" , 2 }, - { "sz", " sizeof" , 1 } + { "sz", "sizeof" , 1 } }; const int num_operators = @@ -2236,6 +2236,9 @@ demangle_type_ptr (dm, insert_pos, substitution_start) { /* A pointer-to-member. */ dyn_string_t class_type; + char peek; + int reset_caret = 0; + int old_caret_position; /* Eat the 'M'. */ advance_char (dm); @@ -2245,14 +2248,43 @@ demangle_type_ptr (dm, insert_pos, substitution_start) RETURN_IF_ERROR (demangle_type (dm)); class_type = (dyn_string_t) result_pop (dm); - if (peek_char (dm) == 'F') + peek = peek_char (dm); + old_caret_position = result_get_caret (dm); + if (peek == 'r' || peek == 'V' || peek == 'K') + { + dyn_string_t cv_qualifiers = dyn_string_new (24); + status_t status; + + if (cv_qualifiers == NULL) + return STATUS_ALLOCATION_FAILED; + + /* Decode all adjacent CV qualifiers. */ + demangle_CV_qualifiers (dm, cv_qualifiers); + + /* Emit them, and shift the caret left so that the + underlying type will be emitted before the + qualifiers. */ + status = result_add_string (dm, cv_qualifiers); + result_shift_caret (dm, -dyn_string_length (cv_qualifiers)); + + dyn_string_delete (cv_qualifiers); + RETURN_IF_ERROR (status); + /* Prepend a blank. */ + RETURN_IF_ERROR (result_add_char (dm, ' ')); + result_shift_caret (dm, -1); + + peek = peek_char (dm); + reset_caret = 1; + } + + if (peek == 'F') /* A pointer-to-member function. We want output along the lines of `void (C::*) (int, int)'. Demangle the function type, which would in this case give `void () (int, int)' and set *insert_pos to the spot between the first parentheses. */ status = demangle_type_ptr (dm, insert_pos, substitution_start); - else if (peek_char (dm) == 'A') + else if (peek == 'A') /* A pointer-to-member array variable. We want output that looks like `int (Klass::*) [10]'. Demangle the array type as `int () [10]', and set *insert_pos to the spot between @@ -2286,6 +2318,9 @@ demangle_type_ptr (dm, insert_pos, substitution_start) /* Clean up. */ dyn_string_delete (class_type); + if (reset_caret) + result_set_caret (dm, old_caret_position); + RETURN_IF_ERROR (status); } break; @@ -2317,6 +2352,39 @@ demangle_type_ptr (dm, insert_pos, substitution_start) RETURN_IF_ERROR (demangle_array_type (dm, insert_pos)); break; + case 'r': + case 'V': + case 'K': + /* Qualified base type. Pick up the qualifiers. */ + { + dyn_string_t cv_qualifiers = dyn_string_new (24); + + if (cv_qualifiers == NULL) + return STATUS_ALLOCATION_FAILED; + + /* Pick up all adjacent CV qualifiers. */ + demangle_CV_qualifiers (dm, cv_qualifiers); + + /* Demangle the underlying type. */ + status = demangle_type_ptr (dm, insert_pos, substitution_start); + + /* Insert the qualifiers where we're told to. */ + if (STATUS_NO_ERROR (status)) + { + status = result_insert_char (dm, *insert_pos, ' '); + ++(*insert_pos); + if (STATUS_NO_ERROR (status)) + status = result_insert_string (dm, *insert_pos, cv_qualifiers); + } + + /* The next character should go after the qualifiers. */ + *insert_pos += dyn_string_length (cv_qualifiers); + + dyn_string_delete (cv_qualifiers); + RETURN_IF_ERROR (status); + } + break; + default: /* No more pointer or reference tokens; this is therefore a pointer to data. Finish up by demangling the underlying @@ -2404,28 +2472,58 @@ demangle_type (dm) /* Decode all adjacent CV qualifiers. */ demangle_CV_qualifiers (dm, cv_qualifiers); - /* Emit them, and shift the caret left so that the - underlying type will be emitted before the qualifiers. */ - status = result_add_string (dm, cv_qualifiers); - result_shift_caret (dm, -dyn_string_length (cv_qualifiers)); - /* Clean up. */ - dyn_string_delete (cv_qualifiers); - RETURN_IF_ERROR (status); - /* Also prepend a blank, if needed. */ - RETURN_IF_ERROR (result_add_char (dm, ' ')); - result_shift_caret (dm, -1); - /* Demangle the underlying type. It will be emitted before - the CV qualifiers, since we moved the caret. */ - RETURN_IF_ERROR (demangle_type (dm)); + /* If the underlying type is a pointer or reference type, we + need to call demangle_type_ptr to find out where to put + the qualifiers. */ + peek = peek_char (dm); + if (peek == 'P' || peek == 'R' || peek == 'M') + { + status = demangle_type_ptr (dm, &insert_pos, + substitution_start (dm)); + if (STATUS_NO_ERROR (status)) + { + status = result_insert_char (dm, insert_pos, ' '); + if (STATUS_NO_ERROR (status)) + status = result_insert_string (dm, insert_pos + 1, + cv_qualifiers); + } + dyn_string_delete (cv_qualifiers); + RETURN_IF_ERROR (status); + } + else + { + /* Emit the qualifiers, and shift the caret left so that + the underlying type will be emitted first. */ + status = result_add_string (dm, cv_qualifiers); + result_shift_caret (dm, -dyn_string_length (cv_qualifiers)); + /* Clean up. */ + dyn_string_delete (cv_qualifiers); + RETURN_IF_ERROR (status); + /* Also prepend a blank, if needed. */ + RETURN_IF_ERROR (result_add_char (dm, ' ')); + result_shift_caret (dm, -1); - /* Put the caret back where it was previously. */ - result_set_caret (dm, old_caret_position); + /* Demangle the underlying type. It will be emitted before + the CV qualifiers, since we moved the caret. */ + RETURN_IF_ERROR (demangle_type (dm)); + + /* Put the caret back where it was previously. */ + result_set_caret (dm, old_caret_position); + } } break; case 'F': - return "Non-pointer or -reference function type."; + /* The return type should go at the current position. */ + insert_pos = result_caret_pos (dm); + /* Put in parentheses to indicate that this is a function. */ + RETURN_IF_ERROR (result_add (dm, "()")); + /* Demangle the function type. The return type will be + inserted before the '()', and the argument list will go + after it. */ + RETURN_IF_ERROR (demangle_function_type (dm, &insert_pos)); + break; case 'A': RETURN_IF_ERROR (demangle_array_type (dm, NULL)); @@ -3472,10 +3570,17 @@ static status_t demangle_local_name (dm) demangling_t dm; { + int old_caret_position = result_get_caret (dm); + DEMANGLE_TRACE ("local-name", dm); RETURN_IF_ERROR (demangle_char (dm, 'Z')); RETURN_IF_ERROR (demangle_encoding (dm)); + + /* Restore the caret to avoid being confused by any qualifiers we + may have found during the encoding. */ + result_set_caret (dm, old_caret_position); + RETURN_IF_ERROR (demangle_char (dm, 'E')); RETURN_IF_ERROR (result_add (dm, "::")); -- cgit v1.2.1