diff --git a/dlls/msvcrt/tests/cpp.c b/dlls/msvcrt/tests/cpp.c index 92301ff6d4a..f36641e4591 100644 --- a/dlls/msvcrt/tests/cpp.c +++ b/dlls/msvcrt/tests/cpp.c @@ -1312,6 +1312,9 @@ static void test_demangle(void) /* 123 */ {"?vtordisp_thunk@std@@$4PPPPPPPM@3EAA_NXZ", "[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{4294967292,4}' (void) __ptr64", "[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{-4,4}' (void) __ptr64"}, +/* 124 */ {"??_9CView@@$BBII@AE", + "[thunk]: __thiscall CView::`vcall'{392,{flat}}' }'", + "[thunk]: __thiscall CView::`vcall'{392,{flat}}' "}, }; int i, num_test = (sizeof(test)/sizeof(test[0])); char* name; diff --git a/dlls/msvcrt/undname.c b/dlls/msvcrt/undname.c index dfcf2abda78..bc2a6fbdd2f 100644 --- a/dlls/msvcrt/undname.c +++ b/dlls/msvcrt/undname.c @@ -1067,6 +1067,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) { char accmem; const char* access = NULL; + int access_id = -1; const char* member_type = NULL; struct datatype_t ct_ret; const char* call_conv; @@ -1074,7 +1075,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) const char* exported; const char* args_str = NULL; const char* name = NULL; - BOOL ret = FALSE; + BOOL ret = FALSE, has_args = TRUE, has_ret = TRUE; unsigned mark; struct array array_pmt; @@ -1111,48 +1112,58 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) * "$3" protected: thunk vtordisp * "$4" public: thunk vtordisp * "$5" public: thunk vtordisp + * "$B" vcall thunk */ accmem = *sym->current++; if (accmem == '$') { - accmem = *sym->current++; - if (accmem < '0' || accmem > '5') goto done; + if (*sym->current >= '0' && *sym->current <= '5') + access_id = (*sym->current - '0') / 2; + else if (*sym->current != 'B') + goto done; } - else if (accmem < 'A' || accmem > 'Z') goto done; + else if (accmem >= 'A' && accmem <= 'Z') + access_id = (accmem - 'A') / 8; + else + goto done; - if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS)) + switch (access_id) { - switch (accmem >= '0' && accmem <= '5' ? (accmem - '0') / 2 : (accmem - 'A') / 8) + case 0: access = "private: "; break; + case 1: access = "protected: "; break; + case 2: access = "public: "; break; + } + if (accmem == '$' || (accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7) + access = str_printf(sym, "[thunk]:%s", access ? access : " "); + + if (accmem == '$' && *sym->current >= '0' && *sym->current <= '5') + member_type = "virtual "; + else if (accmem <= 'X') + { + switch ((accmem - 'A') % 8) { - case 0: access = "private: "; break; - case 1: access = "protected: "; break; - case 2: access = "public: "; break; - } - } - if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE)) - { - if (accmem >= '0' && accmem <= '5') - { - access = str_printf(sym, "[thunk]:%s", access); - member_type = "virtual "; - } - else if (accmem <= 'X') - { - switch ((accmem - 'A') % 8) - { - case 2: case 3: member_type = "static "; break; - case 4: case 5: member_type = "virtual "; break; - case 6: case 7: - access = str_printf(sym, "[thunk]:%s", access); - member_type = "virtual "; - break; - } + case 2: case 3: member_type = "static "; break; + case 4: case 5: case 6: case 7: member_type = "virtual "; break; } } + if (sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS) + access = NULL; + if (sym->flags & UNDNAME_NO_MEMBER_TYPE) + member_type = NULL; + name = get_class_string(sym, 0); - if (accmem >= '0' && accmem <='5') /* vtordisp thunk */ + if (accmem == '$' && *sym->current++ == 'B') /* vcall thunk */ + { + const char *n = get_number(sym); + + if(!n || *sym->current++ != 'A') goto done; + name = str_printf(sym, "%s{%s,{flat}}' }'", name, n); + has_args = FALSE; + has_ret = FALSE; + } + else if (accmem == '$') /* vtordisp thunk */ { const char *n1 = get_number(sym); const char *n2 = get_number(sym); @@ -1163,16 +1174,14 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) else if ((accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7) /* a thunk */ name = str_printf(sym, "%s`adjustor{%s}' ", name, get_number(sym)); - if (accmem <= 'X') + if (has_args && (accmem == '$' || + (accmem <= 'X' && (accmem - 'A') % 8 != 2 && (accmem - 'A') % 8 != 3))) { - if (((accmem - 'A') % 8) != 2 && ((accmem - 'A') % 8) != 3) - { - const char *ptr_modif; - /* Implicit 'this' pointer */ - /* If there is an implicit this pointer, const modifier follows */ - if (!get_modifier(sym, &modifier, &ptr_modif)) goto done; - if (modifier || ptr_modif) modifier = str_printf(sym, "%s %s", modifier, ptr_modif); - } + const char *ptr_modif; + /* Implicit 'this' pointer */ + /* If there is an implicit this pointer, const modifier follows */ + if (!get_modifier(sym, &modifier, &ptr_modif)) goto done; + if (modifier || ptr_modif) modifier = str_printf(sym, "%s %s", modifier, ptr_modif); } if (!get_calling_convention(*sym->current++, &call_conv, &exported, @@ -1182,18 +1191,18 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) str_array_init(&array_pmt); /* Return type, or @ if 'void' */ - if (*sym->current == '@') + if (has_ret && *sym->current == '@') { ct_ret.left = "void"; ct_ret.right = NULL; sym->current++; } - else + else if (has_ret) { if (!demangle_datatype(sym, &ct_ret, &array_pmt, FALSE)) goto done; } - if (sym->flags & UNDNAME_NO_FUNCTION_RETURNS) + if (!has_ret || sym->flags & UNDNAME_NO_FUNCTION_RETURNS) ct_ret.left = ct_ret.right = NULL; if (cast_op) { @@ -1202,7 +1211,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) } mark = sym->stack.num; - if (!(args_str = get_args(sym, &array_pmt, TRUE, '(', ')'))) goto done; + if (has_args && !(args_str = get_args(sym, &array_pmt, TRUE, '(', ')'))) goto done; if (sym->flags & UNDNAME_NAME_ONLY) args_str = modifier = NULL; sym->stack.num = mark; @@ -1210,7 +1219,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) * Yet!!! FIXME */ sym->result = str_printf(sym, "%s%s%s%s%s%s%s%s%s%s%s", - access, member_type, ct_ret.left, + access, member_type, ct_ret.left, (ct_ret.left && !ct_ret.right) ? " " : NULL, call_conv, call_conv ? " " : NULL, exported, name, args_str, modifier, ct_ret.right);