re PR c++/6057 (expression mangling doesn't work for operator new)
PR c++/6057 PR c++/48051 PR c++/50855 PR c++/51322 gcc/cp/ * mangle.c (write_expression): Support NEW_EXPR, DELETE_EXPR, THROW_EXPR, CONSTRUCTOR, OVERLOAD. Fix PREINCREMENT_EXPR and PREDECREMENT_EXPR. (write_template_arg): Fix mangling of class-scope functions and argument packs. (mangle_decl): Update suggested -fabi-version argument. * operators.def: Add DOTSTAR_EXPR, REINTERPRET_CAST_EXPR, DYNAMIC_CAST_EXPR; correct CONST_CAST_EXPR, STATIC_CAST_EXPR. * tree.c (dependent_name): No longer static. * cp-tree.h: Declare it. * pt.c (unify): Defer handling of unconverted functions. include/ * demangle.h (enum demangle_component_type): Add DEMANGLE_COMPONENT_INITIALIZER_LIST, DEMANGLE_COMPONENT_NULLARY. libiberty/ * cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_NULLARY and DEMANGLE_COMPONENT_INITIALIZER_LIST. (d_make_comp): Likewise. Allow null right arg for DEMANGLE_COMPONENT_TRINARY_ARG2. (cplus_demangle_operators): Adjust new/delete; add .*, :: and throw. (d_template_args, d_template_arg): Handle 'J' for argument packs. (d_exprlist): Add terminator parm. (d_expression, d_print_comp): Handle initializer lists, nullary expressions, prefix/suffix operators, and new. (d_print_subexpr): Avoid parens around DEMANGLE_COMPONENT_QUAL_NAME and DEMANGLE_COMPONENT_INITIALIZER_LIST. * testsuite/demangle-expected: Add tests. From-SVN: r182970
This commit is contained in:
parent
49f2da1a16
commit
4b6aaa996e
@ -782,7 +782,10 @@ Driver Undocumented
|
||||
; function parameters used in other parameters and the return type.
|
||||
; First selectable in G++ 4.6.
|
||||
;
|
||||
; 6: The version of the ABI that doesn't promote scoped enums to int.
|
||||
; 6: The version of the ABI that doesn't promote scoped enums to int and
|
||||
; changes the mangling of template argument packs, const/static_cast,
|
||||
; prefix ++ and --, and a class scope function used as a template
|
||||
; argument.
|
||||
; First selectable in G++ 4.7.
|
||||
;
|
||||
; Additional positive integers will be assigned as new versions of
|
||||
|
@ -1,5 +1,21 @@
|
||||
2012-01-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/6057
|
||||
PR c++/48051
|
||||
PR c++/50855
|
||||
PR c++/51322
|
||||
* mangle.c (write_expression): Support NEW_EXPR, DELETE_EXPR,
|
||||
THROW_EXPR, CONSTRUCTOR, OVERLOAD. Fix PREINCREMENT_EXPR and
|
||||
PREDECREMENT_EXPR.
|
||||
(write_template_arg): Fix mangling of class-scope functions and
|
||||
argument packs.
|
||||
(mangle_decl): Update suggested -fabi-version argument.
|
||||
* operators.def: Add DOTSTAR_EXPR, REINTERPRET_CAST_EXPR,
|
||||
DYNAMIC_CAST_EXPR; correct CONST_CAST_EXPR, STATIC_CAST_EXPR.
|
||||
* tree.c (dependent_name): No longer static.
|
||||
* cp-tree.h: Declare it.
|
||||
* pt.c (unify): Defer handling of unconverted functions.
|
||||
|
||||
* mangle.c (mangle_decl): Don't generate mangling aliases
|
||||
for maybe-in-charge [cd]tors.
|
||||
|
||||
|
@ -5674,6 +5674,7 @@ extern tree hash_tree_cons (tree, tree, tree);
|
||||
extern tree hash_tree_chain (tree, tree);
|
||||
extern tree build_qualified_name (tree, tree, tree, bool);
|
||||
extern int is_overloaded_fn (tree);
|
||||
extern tree dependent_name (tree);
|
||||
extern tree get_fns (tree);
|
||||
extern tree get_first_fn (tree);
|
||||
extern tree ovl_cons (tree, tree);
|
||||
|
141
gcc/cp/mangle.c
141
gcc/cp/mangle.c
@ -2646,6 +2646,102 @@ write_expression (tree expr)
|
||||
write_expression (TREE_OPERAND (expr, 0));
|
||||
write_expression (TREE_OPERAND (expr, 2));
|
||||
}
|
||||
else if (code == NEW_EXPR || code == VEC_NEW_EXPR)
|
||||
{
|
||||
/* ::= [gs] nw <expression>* _ <type> E
|
||||
::= [gs] nw <expression>* _ <type> <initializer>
|
||||
::= [gs] na <expression>* _ <type> E
|
||||
::= [gs] na <expression>* _ <type> <initializer>
|
||||
<initializer> ::= pi <expression>* E */
|
||||
tree placement = TREE_OPERAND (expr, 0);
|
||||
tree type = TREE_OPERAND (expr, 1);
|
||||
tree nelts = TREE_OPERAND (expr, 2);
|
||||
tree init = TREE_OPERAND (expr, 3);
|
||||
tree t;
|
||||
|
||||
gcc_assert (code == NEW_EXPR);
|
||||
if (TREE_OPERAND (expr, 2))
|
||||
code = VEC_NEW_EXPR;
|
||||
|
||||
if (NEW_EXPR_USE_GLOBAL (expr))
|
||||
write_string ("gs");
|
||||
|
||||
write_string (operator_name_info[(int) code].mangled_name);
|
||||
|
||||
for (t = placement; t; t = TREE_CHAIN (t))
|
||||
write_expression (TREE_VALUE (t));
|
||||
|
||||
write_char ('_');
|
||||
|
||||
if (nelts)
|
||||
{
|
||||
tree domain;
|
||||
++processing_template_decl;
|
||||
domain = compute_array_index_type (NULL_TREE, nelts,
|
||||
tf_warning_or_error);
|
||||
type = build_cplus_array_type (type, domain);
|
||||
--processing_template_decl;
|
||||
}
|
||||
write_type (type);
|
||||
|
||||
if (init && TREE_CODE (init) == TREE_LIST
|
||||
&& TREE_CODE (TREE_VALUE (init)) == CONSTRUCTOR
|
||||
&& CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))
|
||||
write_expression (TREE_VALUE (init));
|
||||
else
|
||||
{
|
||||
if (init)
|
||||
write_string ("pi");
|
||||
if (init && init != void_zero_node)
|
||||
for (t = init; t; t = TREE_CHAIN (t))
|
||||
write_expression (TREE_VALUE (t));
|
||||
write_char ('E');
|
||||
}
|
||||
}
|
||||
else if (code == DELETE_EXPR || code == VEC_DELETE_EXPR)
|
||||
{
|
||||
gcc_assert (code == DELETE_EXPR);
|
||||
if (DELETE_EXPR_USE_VEC (expr))
|
||||
code = VEC_DELETE_EXPR;
|
||||
|
||||
if (DELETE_EXPR_USE_GLOBAL (expr))
|
||||
write_string ("gs");
|
||||
|
||||
write_string (operator_name_info[(int) code].mangled_name);
|
||||
|
||||
write_expression (TREE_OPERAND (expr, 0));
|
||||
}
|
||||
else if (code == THROW_EXPR)
|
||||
{
|
||||
tree op = TREE_OPERAND (expr, 0);
|
||||
if (op)
|
||||
{
|
||||
write_string ("tw");
|
||||
write_expression (op);
|
||||
}
|
||||
else
|
||||
write_string ("tr");
|
||||
}
|
||||
else if (code == CONSTRUCTOR)
|
||||
{
|
||||
VEC(constructor_elt,gc)* elts = CONSTRUCTOR_ELTS (expr);
|
||||
unsigned i; tree val;
|
||||
|
||||
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
|
||||
write_string ("il");
|
||||
else
|
||||
{
|
||||
write_string ("tl");
|
||||
write_type (TREE_TYPE (expr));
|
||||
}
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val)
|
||||
write_expression (val);
|
||||
write_char ('E');
|
||||
}
|
||||
else if (dependent_name (expr))
|
||||
{
|
||||
write_unqualified_id (dependent_name (expr));
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, len;
|
||||
@ -2688,6 +2784,16 @@ write_expression (tree expr)
|
||||
|
||||
/* If it wasn't any of those, recursively expand the expression. */
|
||||
name = operator_name_info[(int) code].mangled_name;
|
||||
|
||||
/* We used to mangle const_cast and static_cast like a C cast. */
|
||||
if (!abi_version_at_least (6)
|
||||
&& (code == CONST_CAST_EXPR
|
||||
|| code == STATIC_CAST_EXPR))
|
||||
{
|
||||
name = operator_name_info[CAST_EXPR].mangled_name;
|
||||
G.need_abi_warning = 1;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
sorry ("mangling %C", code);
|
||||
@ -2734,16 +2840,21 @@ write_expression (tree expr)
|
||||
}
|
||||
break;
|
||||
|
||||
/* FIXME these should have a distinct mangling. */
|
||||
case DYNAMIC_CAST_EXPR:
|
||||
case REINTERPRET_CAST_EXPR:
|
||||
case STATIC_CAST_EXPR:
|
||||
case CONST_CAST_EXPR:
|
||||
write_type (TREE_TYPE (expr));
|
||||
write_expression (TREE_OPERAND (expr, 0));
|
||||
break;
|
||||
|
||||
case NEW_EXPR:
|
||||
sorry ("mangling new-expression");
|
||||
break;
|
||||
case PREINCREMENT_EXPR:
|
||||
case PREDECREMENT_EXPR:
|
||||
if (abi_version_at_least (6))
|
||||
write_char ('_');
|
||||
else
|
||||
G.need_abi_warning = 1;
|
||||
/* Fall through. */
|
||||
|
||||
default:
|
||||
/* In the middle-end, some expressions have more operands than
|
||||
@ -2855,12 +2966,28 @@ write_template_arg (tree node)
|
||||
G.need_abi_warning = 1;
|
||||
}
|
||||
|
||||
if (TREE_CODE (node) == BASELINK
|
||||
&& !type_unknown_p (node))
|
||||
{
|
||||
if (abi_version_at_least (6))
|
||||
node = BASELINK_FUNCTIONS (node);
|
||||
else
|
||||
/* We wrongly wrapped a class-scope function in X/E. */
|
||||
G.need_abi_warning = 1;
|
||||
}
|
||||
|
||||
if (ARGUMENT_PACK_P (node))
|
||||
{
|
||||
/* Expand the template argument pack. */
|
||||
tree args = ARGUMENT_PACK_ARGS (node);
|
||||
int i, length = TREE_VEC_LENGTH (args);
|
||||
write_char ('I');
|
||||
if (abi_version_at_least (6))
|
||||
write_char ('J');
|
||||
else
|
||||
{
|
||||
write_char ('I');
|
||||
G.need_abi_warning = 1;
|
||||
}
|
||||
for (i = 0; i < length; ++i)
|
||||
write_template_arg (TREE_VEC_ELT (args, i));
|
||||
write_char ('E');
|
||||
@ -3208,8 +3335,8 @@ mangle_decl (const tree decl)
|
||||
|
||||
SET_IDENTIFIER_GLOBAL_VALUE (id, decl);
|
||||
if (IDENTIFIER_GLOBAL_VALUE (id) != decl)
|
||||
inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=4 (or =0) "
|
||||
"avoids this error with a change in vector mangling");
|
||||
inform (DECL_SOURCE_LOCATION (decl), "-fabi-version=6 (or =0) "
|
||||
"avoids this error with a change in mangling");
|
||||
|
||||
#ifdef ASM_OUTPUT_DEF
|
||||
save_ver = flag_abi_version;
|
||||
|
@ -101,8 +101,10 @@ DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1)
|
||||
/* The cast operator. */
|
||||
DEF_SIMPLE_OPERATOR ("", TYPE_EXPR, "cv", 1)
|
||||
DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", 1)
|
||||
DEF_SIMPLE_OPERATOR ("", CONST_CAST_EXPR, "cv", 1)
|
||||
DEF_SIMPLE_OPERATOR ("", STATIC_CAST_EXPR, "cv", 1)
|
||||
DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", 1)
|
||||
DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", 1)
|
||||
DEF_SIMPLE_OPERATOR ("const_cast", CONST_CAST_EXPR, "cc", 1)
|
||||
DEF_SIMPLE_OPERATOR ("static_cast", STATIC_CAST_EXPR, "sc", 1)
|
||||
|
||||
/* Binary operators. */
|
||||
DEF_SIMPLE_OPERATOR ("+", PLUS_EXPR, "pl", 2)
|
||||
@ -125,6 +127,7 @@ DEF_SIMPLE_OPERATOR ("&&", TRUTH_ANDIF_EXPR, "aa", 2)
|
||||
DEF_SIMPLE_OPERATOR ("||", TRUTH_ORIF_EXPR, "oo", 2)
|
||||
DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR, "cm", 2)
|
||||
DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2)
|
||||
DEF_SIMPLE_OPERATOR (".*", DOTSTAR_EXPR, "ds", 2)
|
||||
DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2)
|
||||
DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2)
|
||||
DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2)
|
||||
|
@ -16885,7 +16885,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
|
||||
|
||||
default:
|
||||
/* An unresolved overload is a nondeduced context. */
|
||||
if (type_unknown_p (parm))
|
||||
if (is_overloaded_fn (parm) || type_unknown_p (parm))
|
||||
return unify_success (explain_p);
|
||||
gcc_assert (EXPR_P (parm));
|
||||
|
||||
|
@ -1457,7 +1457,7 @@ is_overloaded_fn (tree x)
|
||||
(14.6.2), return the IDENTIFIER_NODE for that name. Otherwise, return
|
||||
NULL_TREE. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
dependent_name (tree x)
|
||||
{
|
||||
if (TREE_CODE (x) == IDENTIFIER_NODE)
|
||||
|
@ -1,5 +1,21 @@
|
||||
2012-01-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/abi/mangle51.C: New.
|
||||
* g++.dg/abi/mangle52.C: New.
|
||||
* g++.dg/abi/mangle53.C: New.
|
||||
* g++.dg/abi/mangle54.C: New.
|
||||
* g++.dg/abi/mangle55.C: New.
|
||||
* g++.dg/abi/mangle56.C: New.
|
||||
* g++.dg/abi/mangle57.C: New.
|
||||
* g++.dg/abi/mangle58.C: New.
|
||||
* g++.dg/abi/mangle59.C: New.
|
||||
* g++.dg/cpp0x/trailing3.C: Update mangling.
|
||||
* g++.dg/cpp0x/variadic111.C: Update mangling.
|
||||
* g++.dg/cpp0x/variadic4.C: Update mangling.
|
||||
* g++.dg/cpp0x/variadic42.C: Pass -fabi-version=5.
|
||||
* g++.dg/template/nontype22.C: Works now.
|
||||
* g++.dg/template/pr35240.C: Works now.
|
||||
|
||||
* g++.dg/cpp0x/error7.C: New.
|
||||
|
||||
2012-01-06 Tobias Burnus <burnus@net-b.de>
|
||||
|
27
gcc/testsuite/g++.dg/abi/mangle51.C
Normal file
27
gcc/testsuite/g++.dg/abi/mangle51.C
Normal file
@ -0,0 +1,27 @@
|
||||
// { dg-options "-std=c++0x -fabi-version=0" }
|
||||
|
||||
void* operator new (__SIZE_TYPE__, void *p) { return p; }
|
||||
int i;
|
||||
|
||||
template <unsigned int> struct helper {};
|
||||
// { dg-final { scan-assembler "_Z6check1IiEvP6helperIXsznw_T_EEE" } }
|
||||
template <class T> void check1( helper<sizeof(new T)> * ) { }
|
||||
// { dg-final { scan-assembler "_Z6check2IiEvP6helperIXszgsnw_T_piEEE" } }
|
||||
template <class T> void check2( helper<sizeof(::new T())> * ) { }
|
||||
// { dg-final { scan-assembler "_Z6check3IiEvP6helperIXsznwadL_Z1iE_T_piLi1EEEE" } }
|
||||
template <class T> void check3( helper<sizeof(new (&i) T(1))> * ) { }
|
||||
// { dg-final { scan-assembler "_Z7check3aIiEvP6helperIXsznw_T_ilLi1EEEE" } }
|
||||
template <class T> void check3a( helper<sizeof(new T{1})> * ) { }
|
||||
// { dg-final { scan-assembler "_Z6check4IiEvP6helperIXszna_A1_T_EEE" } }
|
||||
template <class T> void check4( helper<sizeof(new T[1])> * ) { }
|
||||
// { dg-final { scan-assembler "_Z6check5IiEvP6helperIXszna_A1_T_piEEE" } }
|
||||
template <class T> void check5( helper<sizeof(new T[1]())> * ) { }
|
||||
int main()
|
||||
{
|
||||
check1<int>(0);
|
||||
check2<int>(0);
|
||||
check3<int>(0);
|
||||
check3a<int>(0);
|
||||
check4<int>(0);
|
||||
check5<int>(0);
|
||||
}
|
21
gcc/testsuite/g++.dg/abi/mangle52.C
Normal file
21
gcc/testsuite/g++.dg/abi/mangle52.C
Normal file
@ -0,0 +1,21 @@
|
||||
// { dg-options "-fabi-version=0" }
|
||||
|
||||
template <unsigned int> struct helper {};
|
||||
// { dg-final { scan-assembler "_Z6check1IiEvP6helperIXszscT_Li1EEE" } }
|
||||
template <class T> void check1( helper<sizeof(static_cast<T>(1))> * ) { }
|
||||
// { dg-final { scan-assembler "_Z6check2IiXadL_Z1iEEEvP6helperIXszccPT_T0_EE" } }
|
||||
template <class T, T* p> void check2( helper<sizeof(const_cast<T*>(p))> * ) { }
|
||||
// { dg-final { scan-assembler "_Z6check3IiEvP6helperIXszrcPT_Li0EEE" } }
|
||||
template <class T> void check3( helper<sizeof(reinterpret_cast<T*>(0))> * ) { }
|
||||
// { dg-final { scan-assembler "_Z6check4I1AXadL_Z1aEEEvP6helperIXszdcPT_T0_EE" } }
|
||||
template <class T, T* p> void check4( helper<sizeof(dynamic_cast<T*>(p))> * ) { }
|
||||
|
||||
struct A{} a;
|
||||
int i;
|
||||
int main()
|
||||
{
|
||||
check1<int>(0);
|
||||
check2<int,&i>(0);
|
||||
check3<int>(0);
|
||||
check4<A,&a>(0);
|
||||
}
|
13
gcc/testsuite/g++.dg/abi/mangle53.C
Normal file
13
gcc/testsuite/g++.dg/abi/mangle53.C
Normal file
@ -0,0 +1,13 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
bool b;
|
||||
// { dg-final { scan-assembler "_Z1fIiEDTquL_Z1bEfp_twLi42EET_" } }
|
||||
template <class T> auto f (T t) -> decltype(b?t:throw 42) { return 0; }
|
||||
// { dg-final { scan-assembler "_Z2f2IiEDTquL_Z1bEfp_trET_" } }
|
||||
template <class T> auto f2 (T t) -> decltype(b?t:throw) { return 0; }
|
||||
|
||||
int main()
|
||||
{
|
||||
f(0);
|
||||
f2(0);
|
||||
}
|
19
gcc/testsuite/g++.dg/abi/mangle54.C
Normal file
19
gcc/testsuite/g++.dg/abi/mangle54.C
Normal file
@ -0,0 +1,19 @@
|
||||
// { dg-options "-std=c++0x -fabi-version=0" }
|
||||
|
||||
int i;
|
||||
// { dg-final { scan-assembler "_Z2f1IiEDTppfp_ET_" } }
|
||||
template <class T> auto f1 (T t) -> decltype(t++) { return i; }
|
||||
// { dg-final { scan-assembler "_Z2f2IiEDTpp_fp_ET_" } }
|
||||
template <class T> auto f2 (T t) -> decltype(++t) { return i; }
|
||||
// { dg-final { scan-assembler "_Z2f3IiEDTmmfp_ET_" } }
|
||||
template <class T> auto f3 (T t) -> decltype(t--) { return i; }
|
||||
// { dg-final { scan-assembler "_Z2f4IiEDTmm_fp_ET_" } }
|
||||
template <class T> auto f4 (T t) -> decltype(--t) { return i; }
|
||||
|
||||
int main()
|
||||
{
|
||||
f1(0);
|
||||
f2(0);
|
||||
f3(0);
|
||||
f4(0);
|
||||
}
|
14
gcc/testsuite/g++.dg/abi/mangle55.C
Normal file
14
gcc/testsuite/g++.dg/abi/mangle55.C
Normal file
@ -0,0 +1,14 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
struct A { int i; };
|
||||
// { dg-final { scan-assembler "_Z2f1Ii1AEDTdsfp_fp0_ET0_MS2_T_" } }
|
||||
template <class T, class U> auto f1 (U u, T U::* p) -> decltype(u.*p) { return u.*p; }
|
||||
// { dg-final { scan-assembler "_Z2f2Ii1AEDTpmfp_fp0_EPT0_MS2_T_" } }
|
||||
template <class T, class U> auto f2 (U* u, T U::* p) -> decltype(u->*p) { return u->*p; }
|
||||
|
||||
int main()
|
||||
{
|
||||
A a = {};
|
||||
f1(a, &A::i);
|
||||
f2(&a, &A::i);
|
||||
}
|
13
gcc/testsuite/g++.dg/abi/mangle56.C
Normal file
13
gcc/testsuite/g++.dg/abi/mangle56.C
Normal file
@ -0,0 +1,13 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template <class T> T g(T t1, T t2) { return t2; }
|
||||
// { dg-final { scan-assembler "_Z2f1IiEDTcl1gfp_ilEEET_" } }
|
||||
template <class T> auto f1 (T t) -> decltype(g(t,{})) { return g(t,{}); }
|
||||
// { dg-final { scan-assembler "_Z2f2IiEDTcl1gfp_tlT_EEES0_" } }
|
||||
template <class T> auto f2 (T t) -> decltype(g(t,T{})) { return g(t,T{}); }
|
||||
|
||||
int main()
|
||||
{
|
||||
f1(0);
|
||||
f2(0);
|
||||
}
|
16
gcc/testsuite/g++.dg/abi/mangle57.C
Normal file
16
gcc/testsuite/g++.dg/abi/mangle57.C
Normal file
@ -0,0 +1,16 @@
|
||||
// { dg-options "-std=c++0x -fabi-version=0" }
|
||||
|
||||
template<typename T> int cmp1(T a, T b);
|
||||
int cmp2(char a, char b);
|
||||
template<typename T, int (*cmp)(T, T)> struct A { };
|
||||
// { dg-final { scan-assembler "_Z1fIcEvR1AIT_X4cmp1EE" } }
|
||||
template <typename T> void f (A<T,cmp1> &);
|
||||
// { dg-final { scan-assembler "_Z1fIcEvR1AIT_L_Z4cmp2ccEE" } }
|
||||
template <typename T> void f (A<T,cmp2> &);
|
||||
void g()
|
||||
{
|
||||
A<char,cmp1> a;
|
||||
f(a);
|
||||
A<char,cmp2> a2;
|
||||
f(a2);
|
||||
}
|
19
gcc/testsuite/g++.dg/abi/mangle58.C
Normal file
19
gcc/testsuite/g++.dg/abi/mangle58.C
Normal file
@ -0,0 +1,19 @@
|
||||
// { dg-options "-std=c++0x -fabi-version=0" }
|
||||
|
||||
template<typename T, int (*cmp)(T, T)> struct A { };
|
||||
struct B {
|
||||
template<typename T> static int cmp1(T a, T b);
|
||||
static int cmp2(char a, char b);
|
||||
// { dg-final { scan-assembler "_ZN1B1fIcEEvR1AIT_X4cmp1EE" } }
|
||||
template <typename T> static void f (A<T,cmp1> &);
|
||||
// { dg-final { scan-assembler "_ZN1B1fIcEEvR1AIT_L_ZNS_4cmp2EccEE" } }
|
||||
template <typename T> static void f (A<T,cmp2> &);
|
||||
};
|
||||
|
||||
void g()
|
||||
{
|
||||
A<char,B::cmp1> a;
|
||||
B::f(a);
|
||||
A<char,B::cmp2> a2;
|
||||
B::f(a2);
|
||||
}
|
19
gcc/testsuite/g++.dg/abi/mangle59.C
Normal file
19
gcc/testsuite/g++.dg/abi/mangle59.C
Normal file
@ -0,0 +1,19 @@
|
||||
// { dg-options "-std=c++0x -fabi-version=0" }
|
||||
|
||||
// { dg-final { scan-assembler "_Z1fIiEDTcmdlfp_psfp_EPT_" } }
|
||||
template <class T> auto f (T* p) -> decltype(delete p, +p) { return p; }
|
||||
// { dg-final { scan-assembler "_Z1gIiEDTcmgsdlfp_psfp_EPT_" } }
|
||||
template <class T> auto g (T* p) -> decltype(::delete p, +p) { return p; }
|
||||
// { dg-final { scan-assembler "_Z1hIiEDTcmdafp_psfp_EPT_" } }
|
||||
template <class T> auto h (T* p) -> decltype(delete[] p, +p) { return p; }
|
||||
// { dg-final { scan-assembler "_Z1iIiEDTcmgsdafp_psfp_EPT_" } }
|
||||
template <class T> auto i (T* p) -> decltype(::delete[] p, +p) { return p; }
|
||||
|
||||
int main()
|
||||
{
|
||||
int x;
|
||||
f(&x);
|
||||
g(&x);
|
||||
h(&x);
|
||||
i(&x);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// More auto/decltype mangling tests.
|
||||
// { dg-options "-std=c++0x" }
|
||||
// { dg-options "-std=c++0x -fabi-version=0" }
|
||||
|
||||
template <class T>
|
||||
struct B
|
||||
@ -58,6 +58,6 @@ int main()
|
||||
A<int>().h(1);
|
||||
// { dg-final { scan-assembler "_ZN1AIiE1jIiEEDTplfp_clL_Z1xvEEET_" } }
|
||||
A<int>().j(1);
|
||||
// { dg-final { scan-assembler "_Z1gIIidEEDTcl1fspplfp_Li1EEEDpT_" } }
|
||||
// { dg-final { scan-assembler "_Z1gIJidEEDTcl1fspplfp_Li1EEEDpT_" } }
|
||||
g(42, 1.0);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// PR c++/48424
|
||||
// { dg-options -std=c++0x }
|
||||
// { dg-options "-std=c++0x -fabi-version=0" }
|
||||
|
||||
template<typename... Args1>
|
||||
struct S
|
||||
@ -16,4 +16,4 @@ int main()
|
||||
s.f(1,2.0,false,'a');
|
||||
}
|
||||
|
||||
// { dg-final { scan-assembler "_ZN1SIIidEE1fIIbcEEEvidDpOT_" } }
|
||||
// { dg-final { scan-assembler "_ZN1SIJidEE1fIJbcEEEvidDpOT_" } }
|
||||
|
@ -1,4 +1,4 @@
|
||||
// { dg-options "-std=gnu++0x" }
|
||||
// { dg-options "-std=gnu++0x -fabi-version=0" }
|
||||
// { dg-do compile }
|
||||
template<typename... Args>
|
||||
class tuple {};
|
||||
@ -9,7 +9,7 @@ void f_two(tuple<int, float>) {}
|
||||
void f_nested(tuple<int, tuple<double, char>, float>) { }
|
||||
|
||||
|
||||
// { dg-final { scan-assembler "_Z6f_none5tupleIIEE" } }
|
||||
// { dg-final { scan-assembler "_Z5f_one5tupleIIiEE" } }
|
||||
// { dg-final { scan-assembler "_Z5f_two5tupleIIifEE" } }
|
||||
// { dg-final { scan-assembler "_Z8f_nested5tupleIIiS_IIdcEEfEE" } }
|
||||
// { dg-final { scan-assembler "_Z6f_none5tupleIJEE" } }
|
||||
// { dg-final { scan-assembler "_Z5f_one5tupleIJiEE" } }
|
||||
// { dg-final { scan-assembler "_Z5f_two5tupleIJifEE" } }
|
||||
// { dg-final { scan-assembler "_Z8f_nested5tupleIJiS_IJdcEEfEE" } }
|
||||
|
@ -1,4 +1,4 @@
|
||||
// { dg-options "-std=gnu++0x" }
|
||||
// { dg-options "-std=gnu++0x -fabi-version=5" }
|
||||
// { dg-do compile }
|
||||
template<typename... Args>
|
||||
void f(Args...) { }
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
template<typename T> int cmp1(T a, T b);
|
||||
template<typename T, int (*cmp)(T, T) = cmp1> struct A { };
|
||||
template <typename T> void f (A<T> &); // { dg-bogus "" "" { xfail *-*-* } }
|
||||
template <typename T> void f (A<T> &);
|
||||
void g()
|
||||
{
|
||||
A<char> a;
|
||||
|
@ -1,12 +1,11 @@
|
||||
// PR c++/35240
|
||||
// { dg-do compile }
|
||||
|
||||
|
||||
template<int> struct A {};
|
||||
|
||||
template<int N> A<sizeof(new int[N][N])> foo(); // { dg-message "unimplemented" }
|
||||
template<int N> A<sizeof(new int[N][N])> foo();
|
||||
|
||||
void bar()
|
||||
{
|
||||
foo<1>(); // { dg-message "required" }
|
||||
foo<1>();
|
||||
}
|
||||
|
@ -1,3 +1,12 @@
|
||||
2012-01-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/6057
|
||||
PR c++/48051
|
||||
PR c++/50855
|
||||
PR c++/51322
|
||||
* demangle.h (enum demangle_component_type): Add
|
||||
DEMANGLE_COMPONENT_INITIALIZER_LIST, DEMANGLE_COMPONENT_NULLARY.
|
||||
|
||||
2011-11-07 Richard Henderson <rth@redhat.com>
|
||||
|
||||
Merged from transactional-memory.
|
||||
|
@ -344,6 +344,9 @@ enum demangle_component_type
|
||||
template argument, and the right subtree is either NULL or
|
||||
another TEMPLATE_ARGLIST node. */
|
||||
DEMANGLE_COMPONENT_TEMPLATE_ARGLIST,
|
||||
/* An initializer list. The left subtree is either an explicit type or
|
||||
NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST. */
|
||||
DEMANGLE_COMPONENT_INITIALIZER_LIST,
|
||||
/* An operator. This holds information about a standard
|
||||
operator. */
|
||||
DEMANGLE_COMPONENT_OPERATOR,
|
||||
@ -353,6 +356,8 @@ enum demangle_component_type
|
||||
/* A typecast, represented as a unary operator. The one subtree is
|
||||
the type to which the argument should be cast. */
|
||||
DEMANGLE_COMPONENT_CAST,
|
||||
/* A nullary expression. The left subtree is the operator. */
|
||||
DEMANGLE_COMPONENT_NULLARY,
|
||||
/* A unary expression. The left subtree is the operator, and the
|
||||
right subtree is the single argument. */
|
||||
DEMANGLE_COMPONENT_UNARY,
|
||||
|
@ -1,5 +1,22 @@
|
||||
2012-01-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/6057
|
||||
PR c++/48051
|
||||
PR c++/50855
|
||||
PR c++/51322
|
||||
* cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_NULLARY and
|
||||
DEMANGLE_COMPONENT_INITIALIZER_LIST.
|
||||
(d_make_comp): Likewise. Allow null right arg for
|
||||
DEMANGLE_COMPONENT_TRINARY_ARG2.
|
||||
(cplus_demangle_operators): Adjust new/delete; add .*, :: and throw.
|
||||
(d_template_args, d_template_arg): Handle 'J' for argument packs.
|
||||
(d_exprlist): Add terminator parm.
|
||||
(d_expression, d_print_comp): Handle initializer lists, nullary
|
||||
expressions, prefix/suffix operators, and new.
|
||||
(d_print_subexpr): Avoid parens around DEMANGLE_COMPONENT_QUAL_NAME
|
||||
and DEMANGLE_COMPONENT_INITIALIZER_LIST.
|
||||
* testsuite/demangle-expected: Add tests.
|
||||
|
||||
* cp-demangle.c (cplus_demangle_type): decltype, pack expansion
|
||||
and vector are substitutable.
|
||||
(cplus_demangle_operators): Sort.
|
||||
|
@ -648,9 +648,15 @@ d_dump (struct demangle_component *dc, int indent)
|
||||
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
|
||||
printf ("template argument list\n");
|
||||
break;
|
||||
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
|
||||
printf ("initializer list\n");
|
||||
break;
|
||||
case DEMANGLE_COMPONENT_CAST:
|
||||
printf ("cast\n");
|
||||
break;
|
||||
case DEMANGLE_COMPONENT_NULLARY:
|
||||
printf ("nullary operator\n");
|
||||
break;
|
||||
case DEMANGLE_COMPONENT_UNARY:
|
||||
printf ("unary operator\n");
|
||||
break;
|
||||
@ -806,7 +812,6 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
|
||||
case DEMANGLE_COMPONENT_BINARY_ARGS:
|
||||
case DEMANGLE_COMPONENT_TRINARY:
|
||||
case DEMANGLE_COMPONENT_TRINARY_ARG1:
|
||||
case DEMANGLE_COMPONENT_TRINARY_ARG2:
|
||||
case DEMANGLE_COMPONENT_LITERAL:
|
||||
case DEMANGLE_COMPONENT_LITERAL_NEG:
|
||||
case DEMANGLE_COMPONENT_COMPOUND_NAME:
|
||||
@ -843,6 +848,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
|
||||
case DEMANGLE_COMPONENT_PACK_EXPANSION:
|
||||
case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
|
||||
case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
|
||||
case DEMANGLE_COMPONENT_NULLARY:
|
||||
case DEMANGLE_COMPONENT_TRINARY_ARG2:
|
||||
if (left == NULL)
|
||||
return NULL;
|
||||
break;
|
||||
@ -850,6 +857,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
|
||||
/* This needs a right parameter, but the left parameter can be
|
||||
empty. */
|
||||
case DEMANGLE_COMPONENT_ARRAY_TYPE:
|
||||
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
|
||||
if (right == NULL)
|
||||
return NULL;
|
||||
break;
|
||||
@ -1573,15 +1581,17 @@ const struct demangle_operator_info cplus_demangle_operators[] =
|
||||
{ "cm", NL (","), 2 },
|
||||
{ "co", NL ("~"), 1 },
|
||||
{ "dV", NL ("/="), 2 },
|
||||
{ "da", NL ("delete[]"), 1 },
|
||||
{ "da", NL ("delete[] "), 1 },
|
||||
{ "de", NL ("*"), 1 },
|
||||
{ "dl", NL ("delete"), 1 },
|
||||
{ "dl", NL ("delete "), 1 },
|
||||
{ "ds", NL (".*"), 2 },
|
||||
{ "dt", NL ("."), 2 },
|
||||
{ "dv", NL ("/"), 2 },
|
||||
{ "eO", NL ("^="), 2 },
|
||||
{ "eo", NL ("^"), 2 },
|
||||
{ "eq", NL ("=="), 2 },
|
||||
{ "ge", NL (">="), 2 },
|
||||
{ "gs", NL ("::"), 1 },
|
||||
{ "gt", NL (">"), 2 },
|
||||
{ "ix", NL ("[]"), 2 },
|
||||
{ "lS", NL ("<<="), 2 },
|
||||
@ -1593,11 +1603,11 @@ const struct demangle_operator_info cplus_demangle_operators[] =
|
||||
{ "mi", NL ("-"), 2 },
|
||||
{ "ml", NL ("*"), 2 },
|
||||
{ "mm", NL ("--"), 1 },
|
||||
{ "na", NL ("new[]"), 1 },
|
||||
{ "na", NL ("new[]"), 3 },
|
||||
{ "ne", NL ("!="), 2 },
|
||||
{ "ng", NL ("-"), 1 },
|
||||
{ "nt", NL ("!"), 1 },
|
||||
{ "nw", NL ("new"), 1 },
|
||||
{ "nw", NL ("new"), 3 },
|
||||
{ "oR", NL ("|="), 2 },
|
||||
{ "oo", NL ("||"), 2 },
|
||||
{ "or", NL ("|"), 2 },
|
||||
@ -1614,6 +1624,8 @@ const struct demangle_operator_info cplus_demangle_operators[] =
|
||||
{ "rs", NL (">>"), 2 },
|
||||
{ "st", NL ("sizeof "), 1 },
|
||||
{ "sz", NL ("sizeof "), 1 },
|
||||
{ "tr", NL ("throw"), 0 },
|
||||
{ "tw", NL ("throw "), 1 },
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
@ -2679,8 +2691,10 @@ d_template_args (struct d_info *di)
|
||||
constructor or destructor. */
|
||||
hold_last_name = di->last_name;
|
||||
|
||||
if (! d_check_char (di, 'I'))
|
||||
if (d_peek_char (di) != 'I'
|
||||
&& d_peek_char (di) != 'J')
|
||||
return NULL;
|
||||
d_advance (di, 1);
|
||||
|
||||
if (d_peek_char (di) == 'E')
|
||||
{
|
||||
@ -2739,6 +2753,7 @@ d_template_arg (struct d_info *di)
|
||||
return d_expr_primary (di);
|
||||
|
||||
case 'I':
|
||||
case 'J':
|
||||
/* An argument pack. */
|
||||
return d_template_args (di);
|
||||
|
||||
@ -2747,15 +2762,16 @@ d_template_arg (struct d_info *di)
|
||||
}
|
||||
}
|
||||
|
||||
/* Subroutine of <expression> ::= cl <expression>+ E */
|
||||
/* Parse a sequence of expressions until we hit the terminator
|
||||
character. */
|
||||
|
||||
static struct demangle_component *
|
||||
d_exprlist (struct d_info *di)
|
||||
d_exprlist (struct d_info *di, char terminator)
|
||||
{
|
||||
struct demangle_component *list = NULL;
|
||||
struct demangle_component **p = &list;
|
||||
|
||||
if (d_peek_char (di) == 'E')
|
||||
if (d_peek_char (di) == terminator)
|
||||
{
|
||||
d_advance (di, 1);
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL);
|
||||
@ -2772,7 +2788,7 @@ d_exprlist (struct d_info *di)
|
||||
return NULL;
|
||||
p = &d_right (*p);
|
||||
|
||||
if (d_peek_char (di) == 'E')
|
||||
if (d_peek_char (di) == terminator)
|
||||
{
|
||||
d_advance (di, 1);
|
||||
break;
|
||||
@ -2863,9 +2879,21 @@ d_expression (struct d_info *di)
|
||||
else
|
||||
return name;
|
||||
}
|
||||
else if ((peek == 'i' || peek == 't')
|
||||
&& d_peek_next_char (di) == 'l')
|
||||
{
|
||||
/* Brace-enclosed initializer list, untyped or typed. */
|
||||
struct demangle_component *type = NULL;
|
||||
if (peek == 't')
|
||||
type = cplus_demangle_type (di);
|
||||
d_advance (di, 2);
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
|
||||
type, d_exprlist (di, 'E'));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct demangle_component *op;
|
||||
const char *code = NULL;
|
||||
int args;
|
||||
|
||||
op = d_operator_name (di);
|
||||
@ -2873,12 +2901,13 @@ d_expression (struct d_info *di)
|
||||
return NULL;
|
||||
|
||||
if (op->type == DEMANGLE_COMPONENT_OPERATOR)
|
||||
di->expansion += op->u.s_operator.op->len - 2;
|
||||
|
||||
if (op->type == DEMANGLE_COMPONENT_OPERATOR
|
||||
&& strcmp (op->u.s_operator.op->code, "st") == 0)
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
|
||||
cplus_demangle_type (di));
|
||||
{
|
||||
code = op->u.s_operator.op->code;
|
||||
di->expansion += op->u.s_operator.op->len - 2;
|
||||
if (strcmp (code, "st") == 0)
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
|
||||
cplus_demangle_type (di));
|
||||
}
|
||||
|
||||
switch (op->type)
|
||||
{
|
||||
@ -2897,26 +2926,43 @@ d_expression (struct d_info *di)
|
||||
|
||||
switch (args)
|
||||
{
|
||||
case 0:
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_NULLARY, op, NULL);
|
||||
|
||||
case 1:
|
||||
{
|
||||
struct demangle_component *operand;
|
||||
int suffix = 0;
|
||||
|
||||
if (code && (code[0] == 'p' || code[0] == 'm')
|
||||
&& code[1] == code[0])
|
||||
/* pp_ and mm_ are the prefix variants. */
|
||||
suffix = !d_check_char (di, '_');
|
||||
|
||||
if (op->type == DEMANGLE_COMPONENT_CAST
|
||||
&& d_check_char (di, '_'))
|
||||
operand = d_exprlist (di);
|
||||
operand = d_exprlist (di, 'E');
|
||||
else
|
||||
operand = d_expression (di);
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
|
||||
operand);
|
||||
|
||||
if (suffix)
|
||||
/* Indicate the suffix variant for d_print_comp. */
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
|
||||
d_make_comp (di,
|
||||
DEMANGLE_COMPONENT_BINARY_ARGS,
|
||||
operand, operand));
|
||||
else
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
|
||||
operand);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
struct demangle_component *left;
|
||||
struct demangle_component *right;
|
||||
const char *code = op->u.s_operator.op->code;
|
||||
|
||||
left = d_expression (di);
|
||||
if (!strcmp (code, "cl"))
|
||||
right = d_exprlist (di);
|
||||
right = d_exprlist (di, 'E');
|
||||
else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
|
||||
{
|
||||
right = d_unqualified_name (di);
|
||||
@ -2936,17 +2982,50 @@ d_expression (struct d_info *di)
|
||||
{
|
||||
struct demangle_component *first;
|
||||
struct demangle_component *second;
|
||||
struct demangle_component *third;
|
||||
|
||||
first = d_expression (di);
|
||||
second = d_expression (di);
|
||||
if (!strcmp (code, "qu"))
|
||||
{
|
||||
/* ?: expression. */
|
||||
first = d_expression (di);
|
||||
second = d_expression (di);
|
||||
third = d_expression (di);
|
||||
}
|
||||
else if (code[0] == 'n')
|
||||
{
|
||||
/* new-expression. */
|
||||
if (code[1] != 'w' && code[1] != 'a')
|
||||
return NULL;
|
||||
first = d_exprlist (di, '_');
|
||||
second = cplus_demangle_type (di);
|
||||
if (d_peek_char (di) == 'E')
|
||||
{
|
||||
d_advance (di, 1);
|
||||
third = NULL;
|
||||
}
|
||||
else if (d_peek_char (di) == 'p'
|
||||
&& d_peek_next_char (di) == 'i')
|
||||
{
|
||||
/* Parenthesized initializer. */
|
||||
d_advance (di, 2);
|
||||
third = d_exprlist (di, 'E');
|
||||
}
|
||||
else if (d_peek_char (di) == 'i'
|
||||
&& d_peek_next_char (di) == 'l')
|
||||
/* initializer-list. */
|
||||
third = d_expression (di);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
|
||||
d_make_comp (di,
|
||||
DEMANGLE_COMPONENT_TRINARY_ARG1,
|
||||
first,
|
||||
d_make_comp (di,
|
||||
DEMANGLE_COMPONENT_TRINARY_ARG2,
|
||||
second,
|
||||
d_expression (di))));
|
||||
second, third)));
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
@ -3666,6 +3745,8 @@ d_print_subexpr (struct d_print_info *dpi, int options,
|
||||
{
|
||||
int simple = 0;
|
||||
if (dc->type == DEMANGLE_COMPONENT_NAME
|
||||
|| dc->type == DEMANGLE_COMPONENT_QUAL_NAME
|
||||
|| dc->type == DEMANGLE_COMPONENT_INITIALIZER_LIST
|
||||
|| dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
|
||||
simple = 1;
|
||||
if (!simple)
|
||||
@ -4261,6 +4342,19 @@ d_print_comp (struct d_print_info *dpi, int options,
|
||||
}
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_INITIALIZER_LIST:
|
||||
{
|
||||
struct demangle_component *type = d_left (dc);
|
||||
struct demangle_component *list = d_right (dc);
|
||||
|
||||
if (type)
|
||||
d_print_comp (dpi, options, type);
|
||||
d_append_char (dpi, '{');
|
||||
d_print_comp (dpi, options, list);
|
||||
d_append_char (dpi, '}');
|
||||
}
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_OPERATOR:
|
||||
{
|
||||
char c;
|
||||
@ -4284,55 +4378,59 @@ d_print_comp (struct d_print_info *dpi, int options,
|
||||
d_print_cast (dpi, options, dc);
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_NULLARY:
|
||||
d_print_expr_op (dpi, options, d_left (dc));
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_UNARY:
|
||||
if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
|
||||
&& d_left (dc)->u.s_operator.op->len == 1
|
||||
&& d_left (dc)->u.s_operator.op->name[0] == '&'
|
||||
&& d_right (dc)->type == DEMANGLE_COMPONENT_TYPED_NAME
|
||||
&& d_left (d_right (dc))->type == DEMANGLE_COMPONENT_QUAL_NAME
|
||||
&& d_right (d_right (dc))->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
|
||||
{
|
||||
/* Address of a function (therefore in an expression context) must
|
||||
have its argument list suppressed.
|
||||
{
|
||||
struct demangle_component *op = d_left (dc);
|
||||
struct demangle_component *operand = d_right (dc);
|
||||
const char *code = NULL;
|
||||
|
||||
unary operator ... dc
|
||||
operator & ... d_left (dc)
|
||||
typed name ... d_right (dc)
|
||||
qualified name ... d_left (d_right (dc))
|
||||
<names>
|
||||
function type ... d_right (d_right (dc))
|
||||
argument list
|
||||
<arguments> */
|
||||
if (op->type == DEMANGLE_COMPONENT_OPERATOR)
|
||||
{
|
||||
code = op->u.s_operator.op->code;
|
||||
if (!strcmp (code, "ad"))
|
||||
{
|
||||
/* Don't print the argument list for the address of a
|
||||
function. */
|
||||
if (operand->type == DEMANGLE_COMPONENT_TYPED_NAME
|
||||
&& d_left (operand)->type == DEMANGLE_COMPONENT_QUAL_NAME
|
||||
&& d_right (operand)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
|
||||
operand = d_left (operand);
|
||||
}
|
||||
if (operand->type == DEMANGLE_COMPONENT_BINARY_ARGS)
|
||||
{
|
||||
/* This indicates a suffix operator. */
|
||||
operand = d_left (operand);
|
||||
d_print_subexpr (dpi, options, operand);
|
||||
d_print_expr_op (dpi, options, op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
d_print_expr_op (dpi, options, d_left (dc));
|
||||
d_print_comp (dpi, options, d_left (d_right (dc)));
|
||||
return;
|
||||
}
|
||||
else if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
|
||||
&& d_left (dc)->u.s_operator.op->len == 1
|
||||
&& d_left (dc)->u.s_operator.op->name[0] == '&'
|
||||
&& d_right (dc)->type == DEMANGLE_COMPONENT_QUAL_NAME)
|
||||
{
|
||||
/* Keep also already processed variant without the argument list.
|
||||
|
||||
unary operator ... dc
|
||||
operator & ... d_left (dc)
|
||||
qualified name ... d_right (dc)
|
||||
<names> */
|
||||
|
||||
d_print_expr_op (dpi, options, d_left (dc));
|
||||
d_print_comp (dpi, options, d_right (dc));
|
||||
return;
|
||||
}
|
||||
else if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
|
||||
d_print_expr_op (dpi, options, d_left (dc));
|
||||
else
|
||||
{
|
||||
d_append_char (dpi, '(');
|
||||
d_print_cast (dpi, options, d_left (dc));
|
||||
d_append_char (dpi, ')');
|
||||
}
|
||||
d_print_subexpr (dpi, options, d_right (dc));
|
||||
if (op->type != DEMANGLE_COMPONENT_CAST)
|
||||
d_print_expr_op (dpi, options, op);
|
||||
else
|
||||
{
|
||||
d_append_char (dpi, '(');
|
||||
d_print_cast (dpi, options, op);
|
||||
d_append_char (dpi, ')');
|
||||
}
|
||||
if (code && !strcmp (code, "gs"))
|
||||
/* Avoid parens after '::'. */
|
||||
d_print_comp (dpi, options, operand);
|
||||
else if (code && !strcmp (code, "st"))
|
||||
/* Always print parens for sizeof (type). */
|
||||
{
|
||||
d_append_char (dpi, '(');
|
||||
d_print_comp (dpi, options, operand);
|
||||
d_append_char (dpi, ')');
|
||||
}
|
||||
else
|
||||
d_print_subexpr (dpi, options, operand);
|
||||
}
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_BINARY:
|
||||
@ -4397,11 +4495,33 @@ d_print_comp (struct d_print_info *dpi, int options,
|
||||
d_print_error (dpi);
|
||||
return;
|
||||
}
|
||||
d_print_subexpr (dpi, options, d_left (d_right (dc)));
|
||||
d_print_expr_op (dpi, options, d_left (dc));
|
||||
d_print_subexpr (dpi, options, d_left (d_right (d_right (dc))));
|
||||
d_append_string (dpi, " : ");
|
||||
d_print_subexpr (dpi, options, d_right (d_right (d_right (dc))));
|
||||
{
|
||||
struct demangle_component *op = d_left (dc);
|
||||
struct demangle_component *first = d_left (d_right (dc));
|
||||
struct demangle_component *second = d_left (d_right (d_right (dc)));
|
||||
struct demangle_component *third = d_right (d_right (d_right (dc)));
|
||||
|
||||
if (!strcmp (op->u.s_operator.op->code, "qu"))
|
||||
{
|
||||
d_print_subexpr (dpi, options, first);
|
||||
d_print_expr_op (dpi, options, op);
|
||||
d_print_subexpr (dpi, options, second);
|
||||
d_append_string (dpi, " : ");
|
||||
d_print_subexpr (dpi, options, third);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_append_string (dpi, "new ");
|
||||
if (d_left (first) != NULL)
|
||||
{
|
||||
d_print_subexpr (dpi, options, first);
|
||||
d_append_char (dpi, ' ');
|
||||
}
|
||||
d_print_comp (dpi, options, second);
|
||||
if (third)
|
||||
d_print_subexpr (dpi, options, third);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case DEMANGLE_COMPONENT_TRINARY_ARG1:
|
||||
|
@ -3935,7 +3935,7 @@ _Z1tIlEDTplcvT_Li5EclL_Z1qsELi6EEEv
|
||||
decltype (((long)(5))+(q(6))) t<long>()
|
||||
# test for expansion of function parameter pack
|
||||
--format=gnu-v3
|
||||
_Z1gIIidEEDTclL_Z1fEspplfp_Li1EEEDpT_
|
||||
_Z1gIJidEEDTclL_Z1fEspplfp_Li1EEEDpT_
|
||||
decltype (f(({parm#1}+(1))...)) g<int, double>(int, double)
|
||||
# lambda tests
|
||||
--format=gnu-v3
|
||||
@ -4030,6 +4030,45 @@ decltype ((int)()) f<int, int>(int, int)
|
||||
--format=gnu-v3
|
||||
_Z1fDv4_iS_
|
||||
f(int __vector(4), int __vector(4))
|
||||
--format=gnu-v3
|
||||
_Z2f1Ii1AEDTdsfp_fp0_ET0_MS2_T_
|
||||
decltype ({parm#1}.*{parm#2}) f1<int, A>(A, int A::*)
|
||||
--format=gnu-v3
|
||||
_Z2f2IiEDTquL_Z1bEfp_trET_
|
||||
decltype (b?{parm#1} : (throw)) f2<int>(int)
|
||||
--format=gnu-v3
|
||||
_Z6check1IiEvP6helperIXsznw_T_EEE
|
||||
void check1<int>(helper<sizeof (new int)>*)
|
||||
--format=gnu-v3
|
||||
_Z6check2IiEvP6helperIXszgsnw_T_piEEE
|
||||
void check2<int>(helper<sizeof (::new int())>*)
|
||||
--format=gnu-v3
|
||||
_Z6check3IiEvP6helperIXsznwadL_Z1iE_T_piLi1EEEE
|
||||
void check3<int>(helper<sizeof (new (&i) int(1))>*)
|
||||
--format=gnu-v3
|
||||
_Z6check4IiEvP6helperIXszna_A1_T_EEE
|
||||
void check4<int>(helper<sizeof (new int [1])>*)
|
||||
--format=gnu-v3
|
||||
_Z6check5IiEvP6helperIXszna_A1_T_piEEE
|
||||
void check5<int>(helper<sizeof (new int [1]())>*)
|
||||
--format=gnu-v3
|
||||
_Z1fIiEDTcmgsdlfp_psfp_EPT_
|
||||
decltype ((::delete {parm#1}),(+{parm#1})) f<int>(int*)
|
||||
--format=gnu-v3
|
||||
_Z1fIiEDTcmdafp_psfp_EPT_
|
||||
decltype ((delete[] {parm#1}),(+{parm#1})) f<int>(int*)
|
||||
--format=gnu-v3
|
||||
_Z2f1IiEDTppfp_ET_
|
||||
decltype ({parm#1}++) f1<int>(int)
|
||||
--format=gnu-v3
|
||||
_Z2f1IiEDTpp_fp_ET_
|
||||
decltype (++{parm#1}) f1<int>(int)
|
||||
--format=gnu-v3
|
||||
_Z2f1IiEDTcl1gfp_ilEEET_
|
||||
decltype (g({parm#1}, {})) f1<int>(int)
|
||||
--format=gnu-v3
|
||||
_Z2f1IiEDTnw_T_ilEES0_
|
||||
decltype (new int{}) f1<int>(int)
|
||||
#
|
||||
# Ada (GNAT) tests.
|
||||
#
|
||||
|
@ -1,3 +1,8 @@
|
||||
2012-01-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* testsuite/abi/demangle/regression/cw-16.cc (main): Adjust
|
||||
expected demangling.
|
||||
|
||||
2012-01-06 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||
|
||||
PR libstdc++/51504
|
||||
|
@ -39,7 +39,7 @@ verify_demangle("_Z1fPFYPFiiEiE",
|
||||
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)");
|
||||
"void f<5, A>(C<sizeof (T::t), sizeof T::t>::q)");
|
||||
// 2003/12/03, libstdc++/13045
|
||||
verify_demangle("_Z1fILi1ELc120EEv1AIXplT_cviLd4028ae147ae147aeEEE",
|
||||
"void f<1, (char)120>(A<(1)+((int)((double)[4028ae147ae147ae]))>)");
|
||||
|
Loading…
x
Reference in New Issue
Block a user