mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-02 16:23:56 +08:00
re PR libstdc++/12947 (Demangler bug)
PR libstdc++/12947 * bits/demangle.h (_GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS): Added. (_GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME): Added. (session<Allocator>::next_peek() const): Added. (decode_non_negative_decimal_integer(string_type&)): Renamed from decode_decimal_integer(string_type&). (session<Allocator>::decode_nested_name): Decode <template_param> as well. (session<Allocator>::add_substitution): Handle <template-param> for <nested-name>'s. (enum xary_nt): Added. (struct entry_st): Added member `xary_nt type' instead of `bool unary'. (symbol_name_table_c): Updated for `entry_st::type' and additional operators (unary `operator+' and `sizeof(type)'). (offset_table_c): Updated for new operators (causing a new hash map). (decode_operator_name): Match the updated hash map. (session<Allocator>::decode_expression): Support for `sizeof ([typename] type)' (st), dependent names (sr) and casting operator (cv). Handle `entry_st::type'. Handle _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS and _GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME. (session<Allocator>::decode_type_with_postfix): Support `extern "C"' function types (FY). * testsuite/demangle/regression/cw-16.cc: Added tests for the added functionality. * testsuite/demangle/regression/3111-2.cc: sizeof now has a space appended. From-SVN: r73480
This commit is contained in:
parent
729bf8ab4a
commit
22e5c8fa3c
@ -1,3 +1,34 @@
|
||||
2003-11-12 Carlo Wood <carlo@alinoe.com>
|
||||
|
||||
PR libstdc++/12947
|
||||
* bits/demangle.h
|
||||
(_GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS): Added.
|
||||
(_GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME): Added.
|
||||
(session<Allocator>::next_peek() const): Added.
|
||||
(decode_non_negative_decimal_integer(string_type&)):
|
||||
Renamed from decode_decimal_integer(string_type&).
|
||||
(session<Allocator>::decode_nested_name):
|
||||
Decode <template_param> as well.
|
||||
(session<Allocator>::add_substitution):
|
||||
Handle <template-param> for <nested-name>'s.
|
||||
(enum xary_nt): Added.
|
||||
(struct entry_st): Added member `xary_nt type' instead of `bool unary'.
|
||||
(symbol_name_table_c): Updated for `entry_st::type' and additional
|
||||
operators (unary `operator+' and `sizeof(type)').
|
||||
(offset_table_c): Updated for new operators (causing a new hash map).
|
||||
(decode_operator_name): Match the updated hash map.
|
||||
(session<Allocator>::decode_expression):
|
||||
Support for `sizeof ([typename] type)' (st),
|
||||
dependent names (sr) and casting operator (cv). Handle
|
||||
`entry_st::type'. Handle _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
|
||||
and _GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME.
|
||||
(session<Allocator>::decode_type_with_postfix):
|
||||
Support `extern "C"' function types (FY).
|
||||
* testsuite/demangle/regression/cw-16.cc: Added tests for the
|
||||
added functionality.
|
||||
* testsuite/demangle/regression/3111-2.cc: sizeof now has a space
|
||||
appended.
|
||||
|
||||
2003-11-11 Paolo Carlini <pcarlini@suse.de>
|
||||
|
||||
PR libstdc++/12875
|
||||
|
@ -28,6 +28,10 @@
|
||||
// invalidate any other reasons why the executable file might be covered by
|
||||
// the GNU General Public License.
|
||||
|
||||
// This file implements demangling of "C++ ABI for Itanium"-mangled symbol
|
||||
// and type names as described in Revision 1.73 of the C++ ABI as can be found
|
||||
// at http://www.codesourcery.com/cxx-abi/abi.html#mangling
|
||||
|
||||
#ifndef _DEMANGLER_H
|
||||
#define _DEMANGLER_H 1
|
||||
|
||||
@ -67,6 +71,15 @@
|
||||
// Default behaviour: 4
|
||||
// Use also an explicit cast for int in literals: (int)4
|
||||
|
||||
// _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
|
||||
// Default behaviour: (i) < (3), sizeof (int)
|
||||
// Don't output spaces around operators in expressions: (i)<(3), sizeof(int)
|
||||
|
||||
// _GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME
|
||||
// Default behaviour: sizeof (X::t)
|
||||
// Put 'typename' infront of <nested-name> types
|
||||
// inside a 'sizeof': sizeof (typename X::t)
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
namespace demangler
|
||||
@ -362,6 +375,10 @@ namespace __gnu_cxx
|
||||
current(void) const
|
||||
{ return (M_pos > M_maxpos) ? 0 : M_str[M_pos]; }
|
||||
|
||||
char
|
||||
next_peek(void) const
|
||||
{ return (M_pos >= M_maxpos) ? 0 : M_str[M_pos + 1]; }
|
||||
|
||||
char
|
||||
next(void)
|
||||
{ return (M_pos >= M_maxpos) ? 0 : M_str[++M_pos]; }
|
||||
@ -406,7 +423,7 @@ namespace __gnu_cxx
|
||||
qualifier_list<Allocator>* qualifiers = NULL);
|
||||
bool decode_unqualified_name(string_type& output);
|
||||
bool decode_unscoped_name(string_type& output);
|
||||
bool decode_decimal_integer(string_type& output);
|
||||
bool decode_non_negative_decimal_integer(string_type& output);
|
||||
bool decode_special_name(string_type& output);
|
||||
};
|
||||
|
||||
@ -465,6 +482,8 @@ namespace __gnu_cxx
|
||||
subst += "::";
|
||||
if (current() == 'S')
|
||||
decode_substitution(subst);
|
||||
else if (current() == 'T')
|
||||
decode_template_param(subst);
|
||||
else
|
||||
decode_unqualified_name(subst);
|
||||
}
|
||||
@ -500,13 +519,14 @@ namespace __gnu_cxx
|
||||
inline char tolower(char c) { return isupper(c) ? c - 'A' + 'a' : c; }
|
||||
|
||||
//
|
||||
// <decimal-integer> ::= 0
|
||||
// <non-negative decimal integer> ::= 0
|
||||
// ::= 1|2|3|4|5|6|7|8|9 [<digit>+]
|
||||
// <digit> ::= 0|1|2|3|4|5|6|7|8|9
|
||||
//
|
||||
template<typename Allocator>
|
||||
bool
|
||||
session<Allocator>::decode_decimal_integer(string_type& output)
|
||||
session<Allocator>::
|
||||
decode_non_negative_decimal_integer(string_type& output)
|
||||
{
|
||||
char c = current();
|
||||
if (c == '0')
|
||||
@ -527,7 +547,7 @@ namespace __gnu_cxx
|
||||
return M_result;
|
||||
}
|
||||
|
||||
// <number> ::= [n] <decimal-integer>
|
||||
// <number> ::= [n] <non-negative decimal integer>
|
||||
//
|
||||
template<typename Allocator>
|
||||
bool
|
||||
@ -535,12 +555,12 @@ namespace __gnu_cxx
|
||||
{
|
||||
_GLIBCXX_DEMANGLER_DOUT_ENTERING("decode_number");
|
||||
if (current() != 'n')
|
||||
decode_decimal_integer(output);
|
||||
decode_non_negative_decimal_integer(output);
|
||||
else
|
||||
{
|
||||
output += '-';
|
||||
eat_current();
|
||||
decode_decimal_integer(output);
|
||||
decode_non_negative_decimal_integer(output);
|
||||
}
|
||||
_GLIBCXX_DEMANGLER_RETURN;
|
||||
}
|
||||
@ -924,6 +944,7 @@ namespace __gnu_cxx
|
||||
// na # new[]
|
||||
// dl # delete
|
||||
// da # delete[]
|
||||
// ps # + (unary)
|
||||
// ng # - (unary)
|
||||
// ad # & (unary)
|
||||
// de # * (unary)
|
||||
@ -966,36 +987,35 @@ namespace __gnu_cxx
|
||||
// cl # ()
|
||||
// ix # []
|
||||
// qu # ?
|
||||
// sz # sizeof
|
||||
// sr # scope resolution (::), see below
|
||||
// st # sizeof (a type)
|
||||
// sz # sizeof (an expression)
|
||||
// cv <type> # (cast)
|
||||
// v <digit> <source-name> # vendor extended operator
|
||||
//
|
||||
//
|
||||
// Symbol operator codes exist of two characters, we need to find a
|
||||
// quick hash so that their names can be looked up in a table.
|
||||
//
|
||||
// The puzzle :)
|
||||
// Shift the rows so that there is at most one character per column.
|
||||
//
|
||||
// A perfect solution:
|
||||
// A perfect solution (Oh no, it's THE MATRIX!):
|
||||
// horizontal
|
||||
// ..................................... offset + 'a'
|
||||
// a, ||a||d|||||||||n||||s|||||||||||||||||| 2
|
||||
// c, || || ||lm|o||| |||| |||||||||||||||||| -3
|
||||
// d, || a| |e | ||l |||| |||v|||||||||||||| 3
|
||||
// e, || | | o q| |||| ||| |||||||||||||| -4
|
||||
// g, |e | | | t||| ||| |||||||||||||| -3
|
||||
// i, | | | | ||| ||| ||||||||||x||| 12
|
||||
// l, | | | e ||| ||| ||st|||||| ||| 9
|
||||
// m, | | | ||| ||| |i lm|||| ||| 18
|
||||
// n, a e g ||t |w| | |||| ||| 0
|
||||
// o, || | | | ||o| r|| 19
|
||||
// p, lm p | t || | || 6
|
||||
// q, | || u || 14
|
||||
// r, | |m |s 20
|
||||
// s, r z | 6
|
||||
// .....................................
|
||||
// ....................................... offset + 'a'
|
||||
// a, a||d|||||||||n||||s|||||||||||||||||||| 0
|
||||
// c, || |||||||lm o||| |||||||||||||||||||| 0
|
||||
// d, || a|||e|| l|| ||||||v||||||||||||| 4
|
||||
// e, || ||| || || |||o|q ||||||||||||| 8
|
||||
// g, || ||| || || e|| | ||||||||t|||| 15
|
||||
// i, || ||| || || || | |||||||| |||x 15
|
||||
// l, |e ||| || st || | |||||||| ||| -2
|
||||
// m, | |i| lm || | |||||||| ||| -2
|
||||
// n, a e g t| w |||||||| ||| 1
|
||||
// o, | ||||o||r ||| 16
|
||||
// p, | ||lm |p st| 17
|
||||
// q, | u| | | 6
|
||||
// r, m s | | 9
|
||||
// s, t z 12
|
||||
// .......................................
|
||||
// ^ ^__ second character
|
||||
// |___ first character
|
||||
//
|
||||
@ -1021,65 +1041,71 @@ namespace __gnu_cxx
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// a b c d e f g h i j k
|
||||
0, -95, 0,-100, -94,-101, 0,-100, 0, -85, 0, 0,
|
||||
0, -97, 0, -97, -93, -89, 0, -82, 0, -82, 0, 0,
|
||||
// l m n o p q r s t u v
|
||||
-88, -79, -97, -78, -91, -83, -77, -91, 0, 0, 0,
|
||||
-99, -99, -96, -81, -80, -91, -88, -85, 0, 0, 0,
|
||||
#else
|
||||
// a b c d e f g h i j k
|
||||
0, 161, 0, 156, 162, 155, 0, 156, 0, 171, 0, 0,
|
||||
0, 159, 0, 159, 163, 167, 0, 174, 0, 174, 0, 0,
|
||||
// l m n o p q r s t u v
|
||||
168, 177, 159, 178, 165, 173, 179, 165, 0, 0, 0,
|
||||
157, 157, 160, 175, 176, 165, 168, 171, 0, 0, 0,
|
||||
#endif
|
||||
// ... more zeros
|
||||
};
|
||||
|
||||
enum xary_nt {
|
||||
unary,
|
||||
binary,
|
||||
trinary
|
||||
};
|
||||
|
||||
struct entry_st
|
||||
{
|
||||
char const* opcode;
|
||||
char const* symbol_name;
|
||||
bool unary;
|
||||
xary_nt type;
|
||||
};
|
||||
|
||||
entry_st const symbol_name_table_c[39] = {
|
||||
{ "na", "operator new[]", true },
|
||||
{ "ge", "operator>=", false },
|
||||
{ "aa", "operator&&", false },
|
||||
{ "da", "operator delete[]", true },
|
||||
{ "ne", "operator!=", false },
|
||||
{ "ad", "operator&", true }, // unary
|
||||
{ "ng", "operator-", true }, // unary
|
||||
{ "de", "operator*", true }, // unary
|
||||
{ "cl", "operator()", true },
|
||||
{ "cm", "operator,", false },
|
||||
{ "eo=", "operator^", false },
|
||||
{ "co", "operator~", false },
|
||||
{ "eq", "operator==", false },
|
||||
{ "le", "operator<=", false },
|
||||
{ "dl", "operator delete", true },
|
||||
{ "an=", "operator&", false },
|
||||
{ "gt", "operator>", false },
|
||||
{ "pl=", "operator+", false },
|
||||
{ "pm", "operator->*", false },
|
||||
{ "nt", "operator!", true },
|
||||
{ "as=", "operator", false },
|
||||
{ "pp", "operator++", true },
|
||||
{ "nw", "operator new", true },
|
||||
{ "sr", "::", true },
|
||||
{ "dv=", "operator/", false },
|
||||
{ "pt", "operator->", false },
|
||||
{ "mi=", "operator-", false },
|
||||
{ "ls=", "operator<<", false },
|
||||
{ "lt", "operator<", false },
|
||||
{ "ml=", "operator*", false },
|
||||
{ "mm", "operator--", true },
|
||||
{ "sz", "sizeof", true },
|
||||
{ "rm=", "operator%", false },
|
||||
{ "oo", "operator||", false },
|
||||
{ "qu", "operator?", false },
|
||||
{ "ix", "operator[]", true },
|
||||
{ "or=", "operator|", false },
|
||||
{ "", NULL, false },
|
||||
{ "rs=", "operator>>", false }
|
||||
{ "aa", "operator&&", binary },
|
||||
{ "na", "operator new[]", unary },
|
||||
{ "le", "operator<=", binary },
|
||||
{ "ad", "operator&", unary },
|
||||
{ "da", "operator delete[]", unary },
|
||||
{ "ne", "operator!=", binary },
|
||||
{ "mi=", "operator-", binary },
|
||||
{ "ng", "operator-", unary },
|
||||
{ "de", "operator*", unary },
|
||||
{ "ml=", "operator*", binary },
|
||||
{ "mm", "operator--", unary },
|
||||
{ "cl", "operator()", unary },
|
||||
{ "cm", "operator,", binary },
|
||||
{ "an=", "operator&", binary },
|
||||
{ "co", "operator~", binary },
|
||||
{ "dl", "operator delete", unary },
|
||||
{ "ls=", "operator<<", binary },
|
||||
{ "lt", "operator<", binary },
|
||||
{ "as=", "operator", binary },
|
||||
{ "ge", "operator>=", binary },
|
||||
{ "nt", "operator!", unary },
|
||||
{ "rm=", "operator%", binary },
|
||||
{ "eo=", "operator^", binary },
|
||||
{ "nw", "operator new", unary },
|
||||
{ "eq", "operator==", binary },
|
||||
{ "dv=", "operator/", binary },
|
||||
{ "qu", "operator?", trinary },
|
||||
{ "rs=", "operator>>", binary },
|
||||
{ "pl=", "operator+", binary },
|
||||
{ "pm", "operator->*", binary },
|
||||
{ "oo", "operator||", binary },
|
||||
{ "st", "sizeof", unary },
|
||||
{ "pp", "operator++", unary },
|
||||
{ "or=", "operator|", binary },
|
||||
{ "gt", "operator>", binary },
|
||||
{ "ps", "operator+", unary },
|
||||
{ "pt", "operator->", binary },
|
||||
{ "sz", "sizeof", unary },
|
||||
{ "ix", "operator[]", unary }
|
||||
};
|
||||
|
||||
template<typename Allocator>
|
||||
@ -1110,11 +1136,11 @@ namespace __gnu_cxx
|
||||
if (opcode1 != current())
|
||||
output += '=';
|
||||
eat_current();
|
||||
if (hash == 27 || hash == 28)
|
||||
if (hash == 16 || hash == 17)
|
||||
M_template_args_need_space = true;
|
||||
_GLIBCXX_DEMANGLER_RETURN;
|
||||
}
|
||||
else if (opcode0 == 'c' && opcode1 == 'v')
|
||||
else if (opcode0 == 'c' && opcode1 == 'v') // casting operator
|
||||
{
|
||||
eat_current();
|
||||
output += "operator ";
|
||||
@ -1141,10 +1167,15 @@ namespace __gnu_cxx
|
||||
//
|
||||
// <expression> ::= <unary operator-name> <expression>
|
||||
// ::= <binary operator-name> <expression> <expression>
|
||||
// ::= <trinary operator-name> <expression> <expression> <expression>
|
||||
// ::= st <type>
|
||||
// ::= <template-param>
|
||||
// ::= sr <type> <unqualified-name> # dependent name
|
||||
// ::= sr <type> <unqualified-name> <template-args> # dependent template-id
|
||||
// ::= <expr-primary>
|
||||
//
|
||||
// <expr-primary> ::= <template-param> # Starts with a T
|
||||
// ::= L <type> <value number> E # literal
|
||||
// <expr-primary> ::= L <type> <value number> E # integer literal
|
||||
// ::= L <type> <value float> E # floating literal
|
||||
// ::= L <mangled-name> E # external name
|
||||
//
|
||||
template<typename Allocator>
|
||||
@ -1167,6 +1198,86 @@ namespace __gnu_cxx
|
||||
eat_current();
|
||||
_GLIBCXX_DEMANGLER_RETURN;
|
||||
}
|
||||
else if (current() == 's')
|
||||
{
|
||||
char opcode1 = next();
|
||||
if (opcode1 == 't' || opcode1 == 'z')
|
||||
{
|
||||
eat_current();
|
||||
#ifdef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
|
||||
output += "sizeof(";
|
||||
#else
|
||||
output += "sizeof (";
|
||||
#endif
|
||||
if (opcode1 == 't')
|
||||
{
|
||||
// I cannot think of a mangled name that is valid for both cases
|
||||
// when just replacing the 't' by a 'z' or vica versa, which
|
||||
// indicates that there is no ambiguity that dictates the need
|
||||
// for a seperate "st" case, except to be able catch invalid
|
||||
// mangled names. However there CAN be ambiguity in the demangled
|
||||
// name when there are both a type and a symbol of the same name,
|
||||
// which then leads to different encoding (of course) with
|
||||
// sizeof (type) or sizeof (expression) respectively, but that
|
||||
// ambiguity is not per se related to "sizeof" except that that
|
||||
// is the only place where both a type AND an expression are valid
|
||||
// in as part of a (template function) type.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// struct B { typedef int t; };
|
||||
// struct A : public B { static int t[2]; };
|
||||
// template<int i, int j> struct C { typedef int q; };
|
||||
// template<int i, typename T>
|
||||
// void f(typename C<sizeof (typename T::t),
|
||||
// sizeof (T::t)>::q) { }
|
||||
// void instantiate() { f<5, A>(0); }
|
||||
//
|
||||
// Leads to _Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE which
|
||||
// demangles as
|
||||
// void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)
|
||||
//
|
||||
// This is ambiguity is very unlikely to happen and it is kind
|
||||
// of fuzzy to detect when adding a 'typename' makes sense.
|
||||
//
|
||||
#ifdef _GLIBCXX_DEMANGLER_STYLE_SIZEOF_TYPENAME
|
||||
// We can only get here inside a template parameter,
|
||||
// so this is syntactically correct if the given type is
|
||||
// a typedef. The only disadvantage is that it is inconsistent
|
||||
// with all other places where the 'typename' keyword should be
|
||||
// used and we don't.
|
||||
// With this, the above example will demangle as
|
||||
// void f<5, A>(C<sizeof (typename T::t), sizeof (T::t)>::q)
|
||||
if (current() == 'N' || // <nested-name>
|
||||
// This should be a safe bet.
|
||||
(current() == 'S' &&
|
||||
next_peek() == 't')) // std::something, guess that
|
||||
// this involves a typedef.
|
||||
output += "typename ";
|
||||
#endif
|
||||
if (!decode_type(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!decode_expression(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
}
|
||||
output += ')';
|
||||
_GLIBCXX_DEMANGLER_RETURN;
|
||||
}
|
||||
else if (current() == 'r')
|
||||
{
|
||||
eat_current();
|
||||
if (!decode_type(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
output += "::";
|
||||
if (!decode_unqualified_name(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
if (current() != 'I' || decode_template_args(output))
|
||||
_GLIBCXX_DEMANGLER_RETURN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char opcode0 = current();
|
||||
@ -1187,31 +1298,57 @@ namespace __gnu_cxx
|
||||
if (entry.opcode[0] == opcode0 && entry.opcode[1] == opcode1
|
||||
&& (opcode1 == current() || entry.opcode[2] == '='))
|
||||
{
|
||||
char const* p = entry.symbol_name;
|
||||
if (!strncmp("operator", p, 8))
|
||||
p += 8;
|
||||
if (*p == ' ')
|
||||
++p;
|
||||
if (entry.unary)
|
||||
output += p;
|
||||
char const* op = entry.symbol_name + 8; // Skip "operator".
|
||||
if (*op == ' ') // operator new and delete.
|
||||
++op;
|
||||
if (entry.type == unary)
|
||||
output += op;
|
||||
bool is_eq = (opcode1 != current());
|
||||
eat_current();
|
||||
output += '(';
|
||||
if (!decode_expression(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
output += ')';
|
||||
if (!entry.unary)
|
||||
if (entry.type != unary)
|
||||
{
|
||||
#ifndef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
|
||||
output += ' ';
|
||||
output += p;
|
||||
#endif
|
||||
output += op;
|
||||
if (is_eq)
|
||||
output += '=';
|
||||
#ifndef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
|
||||
output += ' ';
|
||||
#endif
|
||||
output += '(';
|
||||
if (!decode_expression(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
output += ')';
|
||||
if (entry.type == trinary)
|
||||
{
|
||||
#ifdef _GLIBCXX_DEMANGLER_STYLE_COMPACT_EXPR_OPS
|
||||
output += ":(";
|
||||
#else
|
||||
output += " : (";
|
||||
#endif
|
||||
if (!decode_expression(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
output += ')';
|
||||
}
|
||||
}
|
||||
_GLIBCXX_DEMANGLER_RETURN;
|
||||
}
|
||||
else if (opcode0 == 'c' &&
|
||||
opcode1 == 'v') // casting operator.
|
||||
{
|
||||
eat_current();
|
||||
output += '(';
|
||||
if (!decode_type(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
output += ")(";
|
||||
if (!decode_expression(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
output += ')';
|
||||
_GLIBCXX_DEMANGLER_RETURN;
|
||||
}
|
||||
}
|
||||
@ -1223,8 +1360,9 @@ namespace __gnu_cxx
|
||||
//
|
||||
// <template-args> ::= I <template-arg>+ E
|
||||
// <template-arg> ::= <type> # type or template
|
||||
// ::= L <type> <value number> E # literal
|
||||
// ::= L_Z <encoding> E # external name
|
||||
// ::= L <type> <value number> E # integer literal
|
||||
// ::= L <type> <value float> E # floating literal
|
||||
// ::= L <mangled-name> E # external name
|
||||
// ::= X <expression> E # expression
|
||||
template<typename Allocator>
|
||||
bool
|
||||
@ -1282,7 +1420,12 @@ namespace __gnu_cxx
|
||||
}
|
||||
|
||||
// <bare-function-type> ::=
|
||||
// <signature type>+ # types are parameter types
|
||||
// <signature type>+ # Types are parameter types.
|
||||
//
|
||||
// Note that the possible return type of the <bare-function-type>
|
||||
// has already been eaten before we call this function. This makes
|
||||
// our <bare-function-type> slightly different from the one in
|
||||
// the C++-ABI description.
|
||||
//
|
||||
template<typename Allocator>
|
||||
bool
|
||||
@ -1673,6 +1816,7 @@ namespace __gnu_cxx
|
||||
}
|
||||
case 'M':
|
||||
{
|
||||
// <pointer-to-member-type> ::= M <class type> <member type>
|
||||
// <Q>M<C> or <Q>M<C><Q2>F<R><B>E
|
||||
eat_current();
|
||||
string_type class_type;
|
||||
@ -1773,9 +1917,17 @@ namespace __gnu_cxx
|
||||
{
|
||||
case 'F':
|
||||
{
|
||||
// <function-type> ::= F [Y] <bare-function-type> E
|
||||
//
|
||||
// Note that g++ never generates the 'Y', but we try to
|
||||
// demangle it anyway.
|
||||
bool extern_C = (next() == 'Y');
|
||||
if (extern_C)
|
||||
eat_current();
|
||||
|
||||
// <Q>F<R><B>E ==> R (Q)B
|
||||
// substitution: "<R>", "<B>" (<B> recursive) and "F<R><B>E".
|
||||
eat_current();
|
||||
|
||||
// Return type.
|
||||
if (!decode_type_with_postfix(prefix, postfix))
|
||||
// Substitution: "<R>".
|
||||
@ -1802,6 +1954,8 @@ namespace __gnu_cxx
|
||||
qualifiers->decode_qualifiers(prefix, postfix);
|
||||
// substitution: all qualified types, if any.
|
||||
prefix += ")";
|
||||
if (extern_C)
|
||||
prefix += " [extern \"C\"] ";
|
||||
prefix += bare_function_type;
|
||||
break;
|
||||
}
|
||||
@ -1925,10 +2079,12 @@ namespace __gnu_cxx
|
||||
//
|
||||
// <prefix> ::= <prefix> <unqualified-name>
|
||||
// ::= <template-prefix> <template-args>
|
||||
// ::= <template-param>
|
||||
// ::= # empty
|
||||
// ::= <substitution>
|
||||
//
|
||||
// <template-prefix> ::= <prefix> <template unqualified-name>
|
||||
// ::= <template-param>
|
||||
// ::= <substitution>
|
||||
//
|
||||
template<typename Allocator>
|
||||
@ -1982,7 +2138,12 @@ namespace __gnu_cxx
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!decode_unqualified_name(output))
|
||||
if (current() == 'T')
|
||||
{
|
||||
if (!decode_template_param(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
}
|
||||
else if (!decode_unqualified_name(output))
|
||||
_GLIBCXX_DEMANGLER_FAILURE;
|
||||
if (current() != 'E')
|
||||
{
|
||||
|
@ -22,13 +22,25 @@
|
||||
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
// libcwd tests
|
||||
// Torturing by Carlo Wood.
|
||||
int main()
|
||||
{
|
||||
using namespace __gnu_test;
|
||||
|
||||
// 2003/11/07, libstdc++/12736
|
||||
verify_demangle("_Z3fooIA6_KiEvA9_KT_rVPrS4_",
|
||||
"void foo<int const [6]>(int const [9][6], int const restrict (* volatile restrict) [9][6])");
|
||||
// 2003/11/12, libstdc++/12947
|
||||
verify_demangle("_Z1fILi5E1AEvN1CIXqugtT_Li0ELi1ELi2EEE1qE",
|
||||
"void f<5, A>(C<((5) > (0)) ? (1) : (2)>::q)");
|
||||
verify_demangle("_Z1fILi5EEvN1AIXcvimlT_Li22EEE1qE",
|
||||
"void f<5>(A<(int)((5) * (22))>::q)");
|
||||
verify_demangle("_Z1fPFYPFiiEiE",
|
||||
"f(int (*)(int) (*) [extern \"C\"] (int))");
|
||||
verify_demangle("_Z1fI1XENT_1tES2_",
|
||||
"X::t f<X>(X::t)");
|
||||
verify_demangle("_Z1fILi5E1AEvN1CIXstN1T1tEEXszsrS2_1tEE1qE",
|
||||
"void f<5, A>(C<sizeof (T::t), sizeof (T::t)>::q)");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user