diff options
Diffstat (limited to 'libiberty/d-demangle.c')
-rw-r--r-- | libiberty/d-demangle.c | 101 |
1 files changed, 74 insertions, 27 deletions
diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c index 4d14a4a0e4c..e53990ef4f3 100644 --- a/libiberty/d-demangle.c +++ b/libiberty/d-demangle.c @@ -191,7 +191,8 @@ static const char *dlang_function_args (string *, const char *, static const char *dlang_type (string *, const char *, struct dlang_info *); -static const char *dlang_value (string *, const char *, const char *, char); +static const char *dlang_value (string *, const char *, const char *, char, + struct dlang_info *); static const char *dlang_parse_qualified (string *, const char *, struct dlang_info *, int); @@ -252,15 +253,15 @@ dlang_hexdigit (const char *mangled, char *ret) c = mangled[0]; if (!ISDIGIT (c)) - (*ret) = (c - (ISUPPER (c) ? 'A' : 'a') + 10); + *ret = c - (ISUPPER (c) ? 'A' : 'a') + 10; else - (*ret) = (c - '0'); + *ret = c - '0'; c = mangled[1]; if (!ISDIGIT (c)) - (*ret) = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10); + *ret = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10); else - (*ret) = (*ret << 4) | (c - '0'); + *ret = (*ret << 4) | (c - '0'); mangled += 2; @@ -337,7 +338,7 @@ dlang_decode_backref (const char *mangled, long *ret) static const char * dlang_backref (const char *mangled, const char **ret, struct dlang_info *info) { - (*ret) = NULL; + *ret = NULL; if (mangled == NULL || *mangled != 'Q') return NULL; @@ -355,7 +356,7 @@ dlang_backref (const char *mangled, const char **ret, struct dlang_info *info) return NULL; /* Set the position of the back reference. */ - (*ret) = qpos - refpos; + *ret = qpos - refpos; return mangled; } @@ -380,7 +381,7 @@ dlang_symbol_backref (string *decl, const char *mangled, /* Must point to a simple identifier. */ backref = dlang_number (backref, &len); - if (backref == NULL) + if (backref == NULL || strlen(backref) < len) return NULL; backref = dlang_lname (decl, backref, len); @@ -573,9 +574,11 @@ dlang_attributes (string *decl, const char *mangled) case 'g': case 'h': case 'k': + case 'n': /* inout parameter is represented as 'Ng'. vector parameter is represented as 'Nh'. - return paramenter is represented as 'Nk'. + return parameter is represented as 'Nk'. + typeof(*null) parameter is represented as 'Nn'. If we see this, then we know we're really in the parameter list. Rewind and break. */ mangled--; @@ -787,6 +790,12 @@ dlang_type (string *decl, const char *mangled, struct dlang_info *info) string_append (decl, ")"); return mangled; } + else if (*mangled == 'n') /* typeof(*null) */ + { + mangled++; + string_append (decl, "typeof(*null)"); + return mangled; + } else return NULL; case 'A': /* dynamic array (T[]) */ @@ -866,7 +875,7 @@ dlang_type (string *decl, const char *mangled, struct dlang_info *info) szmods = string_length (&mods); /* Back referenced function type. */ - if (*mangled == 'Q') + if (mangled && *mangled == 'Q') mangled = dlang_type_backref (decl, mangled, info, 1); else mangled = dlang_function_type (decl, mangled, info); @@ -884,7 +893,7 @@ dlang_type (string *decl, const char *mangled, struct dlang_info *info) /* Basic types */ case 'n': mangled++; - string_append (decl, "none"); + string_append (decl, "typeof(null)"); return mangled; case 'v': mangled++; @@ -1035,6 +1044,25 @@ dlang_identifier (string *decl, const char *mangled, struct dlang_info *info) && (mangled[2] == 'T' || mangled[2] == 'U')) return dlang_parse_template (decl, mangled, info, len); + /* There can be multiple different declarations in the same function that have + the same mangled name. To make the mangled names unique, a fake parent in + the form `__Sddd' is added to the symbol. */ + if (len >= 4 && mangled[0] == '_' && mangled[1] == '_' && mangled[2] == 'S') + { + const char *numptr = mangled + 3; + while (numptr < (mangled + len) && ISDIGIT (*numptr)) + numptr++; + + if (mangled + len == numptr) + { + /* Skip over the fake parent. */ + mangled += len; + return dlang_identifier (decl, mangled, info); + } + + /* else demangle it as a plain identifier. */ + } + return dlang_lname (decl, mangled, len); } @@ -1378,7 +1406,8 @@ dlang_parse_string (string *decl, const char *mangled) /* Extract the static array value from MANGLED and append it to DECL. Return the remaining string on success or NULL on failure. */ static const char * -dlang_parse_arrayliteral (string *decl, const char *mangled) +dlang_parse_arrayliteral (string *decl, const char *mangled, + struct dlang_info *info) { unsigned long elements; @@ -1389,7 +1418,7 @@ dlang_parse_arrayliteral (string *decl, const char *mangled) string_append (decl, "["); while (elements--) { - mangled = dlang_value (decl, mangled, NULL, '\0'); + mangled = dlang_value (decl, mangled, NULL, '\0', info); if (mangled == NULL) return NULL; @@ -1404,7 +1433,8 @@ dlang_parse_arrayliteral (string *decl, const char *mangled) /* Extract the associative array value from MANGLED and append it to DECL. Return the remaining string on success or NULL on failure. */ static const char * -dlang_parse_assocarray (string *decl, const char *mangled) +dlang_parse_assocarray (string *decl, const char *mangled, + struct dlang_info *info) { unsigned long elements; @@ -1415,12 +1445,12 @@ dlang_parse_assocarray (string *decl, const char *mangled) string_append (decl, "["); while (elements--) { - mangled = dlang_value (decl, mangled, NULL, '\0'); + mangled = dlang_value (decl, mangled, NULL, '\0', info); if (mangled == NULL) return NULL; string_append (decl, ":"); - mangled = dlang_value (decl, mangled, NULL, '\0'); + mangled = dlang_value (decl, mangled, NULL, '\0', info); if (mangled == NULL) return NULL; @@ -1435,7 +1465,8 @@ dlang_parse_assocarray (string *decl, const char *mangled) /* Extract the struct literal value for NAME from MANGLED and append it to DECL. Return the remaining string on success or NULL on failure. */ static const char * -dlang_parse_structlit (string *decl, const char *mangled, const char *name) +dlang_parse_structlit (string *decl, const char *mangled, const char *name, + struct dlang_info *info) { unsigned long args; @@ -1449,7 +1480,7 @@ dlang_parse_structlit (string *decl, const char *mangled, const char *name) string_append (decl, "("); while (args--) { - mangled = dlang_value (decl, mangled, NULL, '\0'); + mangled = dlang_value (decl, mangled, NULL, '\0', info); if (mangled == NULL) return NULL; @@ -1464,7 +1495,8 @@ dlang_parse_structlit (string *decl, const char *mangled, const char *name) /* Extract the value from MANGLED and append it to DECL. Return the remaining string on success or NULL on failure. */ static const char * -dlang_value (string *decl, const char *mangled, const char *name, char type) +dlang_value (string *decl, const char *mangled, const char *name, char type, + struct dlang_info *info) { if (mangled == NULL || *mangled == '\0') return NULL; @@ -1525,15 +1557,24 @@ dlang_value (string *decl, const char *mangled, const char *name, char type) case 'A': mangled++; if (type == 'H') - mangled = dlang_parse_assocarray (decl, mangled); + mangled = dlang_parse_assocarray (decl, mangled, info); else - mangled = dlang_parse_arrayliteral (decl, mangled); + mangled = dlang_parse_arrayliteral (decl, mangled, info); break; /* Struct values. */ case 'S': mangled++; - mangled = dlang_parse_structlit (decl, mangled, name); + mangled = dlang_parse_structlit (decl, mangled, name, info); + break; + + /* Function literal symbol. */ + case 'f': + mangled++; + if (strncmp (mangled, "_D", 2) != 0 + || !dlang_symbol_name_p (mangled + 2, info)) + return NULL; + mangled = dlang_parse_mangle (decl, mangled, info); break; default: @@ -1609,13 +1650,19 @@ dlang_parse_qualified (string *decl, const char *mangled, size_t n = 0; do { + /* Skip over anonymous symbols. */ + if (*mangled == '0') + { + do + mangled++; + while (*mangled == '0'); + + continue; + } + if (n++) string_append (decl, "."); - /* Skip over anonymous symbols. */ - while (*mangled == '0') - mangled++; - mangled = dlang_identifier (decl, mangled, info); /* Consume the encoded arguments. However if this is not followed by the @@ -1806,7 +1853,7 @@ dlang_template_args (string *decl, const char *mangled, struct dlang_info *info) string_need (&name, 1); *(name.p) = '\0'; - mangled = dlang_value (decl, mangled, name.b, type); + mangled = dlang_value (decl, mangled, name.b, type, info); string_delete (&name); break; } |