From d4701f6c1a7673d43ac1687b1c6c856cfbf057cd Mon Sep 17 00:00:00 2001 From: jason Date: Fri, 9 Nov 2012 16:14:37 +0000 Subject: Add C++ attribute abi_tag and -Wabi-tag option. gcc/ * attribs.c (lookup_attribute_spec): Handle getting a TREE_LIST. gcc/c-family/ * c.opt (Wabi-tag): New. gcc/cp/ * tree.c (cxx_attribute_table): Add abi_tag attribute. (check_abi_tag_redeclaration, handle_abi_tag_attribute): New. * class.c (find_abi_tags_r, check_abi_tags): New. (check_bases, check_field_decl): Call check_abi_tags. * decl.c (redeclaration_error_message): Call check_abi_tag_redeclaration. * mangle.c (tree_string_cmp, write_abi_tags): New. (write_unqualified_name): Call write_abi_tags. include/ * demangle.h (enum demangle_component_type): Add DEMANGLE_COMPONENT_TAGGED_NAME. libiberty/ * cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_TAGGED_NAME. (d_make_comp, d_find_pack, d_print_comp): Likewise. (d_abi_tags): New. (d_name): Call it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193367 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 4 ++ gcc/attribs.c | 13 +++++- gcc/c-family/ChangeLog | 4 ++ gcc/c-family/c.opt | 4 ++ gcc/cp/ChangeLog | 11 +++++ gcc/cp/class.c | 88 +++++++++++++++++++++++++++++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 4 ++ gcc/cp/mangle.c | 68 +++++++++++++++++++++++---- gcc/cp/tree.c | 93 +++++++++++++++++++++++++++++++++++++ gcc/doc/extend.texi | 21 +++++++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/abi/abi-tag1.C | 19 ++++++++ gcc/testsuite/g++.dg/abi/abi-tag2.C | 5 ++ include/ChangeLog | 5 ++ include/demangle.h | 2 + libiberty/ChangeLog | 7 +++ libiberty/cp-demangle.c | 48 +++++++++++++++++-- 18 files changed, 387 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag1.C create mode 100644 gcc/testsuite/g++.dg/abi/abi-tag2.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cd980895d80..37049f910a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2012-11-09 Jason Merrill + + * attribs.c (lookup_attribute_spec): Handle getting a TREE_LIST. + 2012-11-09 Vladimir Makarov PR tree-optimization/55154 diff --git a/gcc/attribs.c b/gcc/attribs.c index d167c1f6e13..0425de9f5b1 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -325,12 +325,21 @@ lookup_scoped_attribute_spec (const_tree ns, const_tree name) substring_hash (attr.str, attr.length)); } -/* Return the spec for the attribute named NAME. */ +/* Return the spec for the attribute named NAME. If NAME is a TREE_LIST, + it also specifies the attribute namespace. */ const struct attribute_spec * lookup_attribute_spec (const_tree name) { - return lookup_scoped_attribute_spec (get_identifier ("gnu"), name); + tree ns; + if (TREE_CODE (name) == TREE_LIST) + { + ns = TREE_PURPOSE (name); + name = TREE_VALUE (name); + } + else + ns = get_identifier ("gnu"); + return lookup_scoped_attribute_spec (ns, name); } diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 20ef315ea74..b3234d34dd5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,7 @@ +2012-11-09 Jason Merrill + + * c.opt (Wabi-tag): New. + 2012-11-09 Andi Kleen PR 55139 diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index e11aef7a365..fe1fc4d5ac0 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -257,6 +257,10 @@ Wabi C ObjC C++ ObjC++ LTO Var(warn_abi) Warning Warn about things that will change when compiling with an ABI-compliant compiler +Wabi-tag +C++ ObjC++ Var(warn_abi_tag) Warning +Warn if a subobject has an abi_tag attribute that the complete object type does not have + Wpsabi C ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Undocumented diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 339a8359da4..4d6d954db1f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2012-11-09 Jason Merrill + + * tree.c (cxx_attribute_table): Add abi_tag attribute. + (check_abi_tag_redeclaration, handle_abi_tag_attribute): New. + * class.c (find_abi_tags_r, check_abi_tags): New. + (check_bases, check_field_decl): Call check_abi_tags. + * decl.c (redeclaration_error_message): Call + check_abi_tag_redeclaration. + * mangle.c (tree_string_cmp, write_abi_tags): New. + (write_unqualified_name): Call write_abi_tags. + 2012-11-07 Paolo Carlini PR c++/55226 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a91e63a6301..d3d9aed7ff7 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1302,6 +1302,89 @@ handle_using_decl (tree using_decl, tree t) alter_access (t, decl, access); } +/* walk_tree callback for check_abi_tags: if the type at *TP involves any + types with abi tags, add the corresponding identifiers to the VEC in + *DATA and set IDENTIFIER_MARKED. */ + +struct abi_tag_data +{ + tree t; + tree subob; +}; + +static tree +find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data) +{ + if (!TAGGED_TYPE_P (*tp)) + return NULL_TREE; + + if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp))) + { + struct abi_tag_data *p = static_cast(data); + for (tree list = TREE_VALUE (attributes); list; + list = TREE_CHAIN (list)) + { + tree tag = TREE_VALUE (list); + tree id = get_identifier (TREE_STRING_POINTER (tag)); + if (!IDENTIFIER_MARKED (id)) + { + if (TYPE_P (p->subob)) + { + warning (OPT_Wabi_tag, "%qT does not have the %E abi tag " + "that base %qT has", p->t, tag, p->subob); + inform (location_of (p->subob), "%qT declared here", + p->subob); + } + else + { + warning (OPT_Wabi_tag, "%qT does not have the %E abi tag " + "that %qT (used in the type of %qD) has", + p->t, tag, *tp, p->subob); + inform (location_of (p->subob), "%qD declared here", + p->subob); + inform (location_of (*tp), "%qT declared here", *tp); + } + } + } + } + return NULL_TREE; +} + +/* Check that class T has all the abi tags that subobject SUBOB has, or + warn if not. */ + +static void +check_abi_tags (tree t, tree subob) +{ + tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t)); + if (attributes) + { + for (tree list = TREE_VALUE (attributes); list; + list = TREE_CHAIN (list)) + { + tree tag = TREE_VALUE (list); + tree id = get_identifier (TREE_STRING_POINTER (tag)); + IDENTIFIER_MARKED (id) = true; + } + } + + tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob); + struct abi_tag_data data = { t, subob }; + + cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data); + + if (attributes) + { + for (tree list = TREE_VALUE (attributes); list; + list = TREE_CHAIN (list)) + { + tree tag = TREE_VALUE (list); + tree id = get_identifier (TREE_STRING_POINTER (tag)); + IDENTIFIER_MARKED (id) = false; + } + } +} + /* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P, and NO_CONST_ASN_REF_P. Also set flag bits in T based on properties of the bases. */ @@ -1431,6 +1514,8 @@ check_bases (tree t, if (tm_attr) seen_tm_mask |= tm_attr_to_mask (tm_attr); } + + check_abi_tags (t, basetype); } /* If one of the base classes had TM attributes, and the current class @@ -3147,6 +3232,9 @@ check_field_decl (tree field, && !TYPE_HAS_CONST_COPY_ASSIGN (type)) *no_const_asn_ref = 1; } + + check_abi_tags (t, field); + if (DECL_INITIAL (field) != NULL_TREE) { /* `build_class_init_list' does not recognize diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 308ea11a5f8..be7bc0b0269 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5749,6 +5749,7 @@ extern bool type_has_nontrivial_default_init (const_tree); extern bool type_has_nontrivial_copy_init (const_tree); extern bool class_tmpl_impl_spec_p (const_tree); extern int zero_init_p (const_tree); +extern bool check_abi_tag_redeclaration (const_tree, const_tree, const_tree); extern tree strip_typedefs (tree); extern tree strip_typedefs_expr (tree); extern tree copy_binfo (tree, tree, tree, diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f8f9d4f2391..f85901fc6c7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2480,6 +2480,10 @@ redeclaration_error_message (tree newdecl, tree olddecl) } } + check_abi_tag_redeclaration + (olddecl, lookup_attribute ("abi_tag", DECL_ATTRIBUTES (olddecl)), + lookup_attribute ("abi_tag", DECL_ATTRIBUTES (newdecl))); + return NULL; } else if (TREE_CODE (newdecl) == TEMPLATE_DECL) diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index f448932e6ea..54a4c9c4bca 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -173,6 +173,7 @@ static void mangle_call_offset (const tree, const tree); static void write_mangled_name (const tree, bool); static void write_encoding (const tree); static void write_name (tree, const int); +static void write_abi_tags (tree); static void write_unscoped_name (const tree); static void write_unscoped_template_name (const tree); static void write_nested_name (const tree); @@ -1192,15 +1193,17 @@ write_unqualified_name (const tree decl) return; } + bool found = false; + if (DECL_NAME (decl) == NULL_TREE) { + found = true; gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); write_source_name (DECL_ASSEMBLER_NAME (decl)); - return; } else if (DECL_DECLARES_FUNCTION_P (decl)) { - bool found = true; + found = true; if (DECL_CONSTRUCTOR_P (decl)) write_special_name_constructor (decl); else if (DECL_DESTRUCTOR_P (decl)) @@ -1234,14 +1237,13 @@ write_unqualified_name (const tree decl) write_literal_operator_name (DECL_NAME (decl)); else found = false; - - if (found) - return; } - if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl) - && DECL_NAMESPACE_SCOPE_P (decl) - && decl_linkage (decl) == lk_internal) + if (found) + /* OK */; + else if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl) + && DECL_NAMESPACE_SCOPE_P (decl) + && decl_linkage (decl) == lk_internal) { MANGLE_TRACE_TREE ("local-source-name", decl); write_char ('L'); @@ -1262,6 +1264,11 @@ write_unqualified_name (const tree decl) else write_source_name (DECL_NAME (decl)); } + + tree attrs = (TREE_CODE (decl) == TYPE_DECL + ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) + : DECL_ATTRIBUTES (decl)); + write_abi_tags (lookup_attribute ("abi_tag", attrs)); } /* Write the unqualified-name for a conversion operator to TYPE. */ @@ -1291,6 +1298,51 @@ write_source_name (tree identifier) write_identifier (IDENTIFIER_POINTER (identifier)); } +/* Compare two TREE_STRINGs like strcmp. */ + +int +tree_string_cmp (const void *p1, const void *p2) +{ + if (p1 == p2) + return 0; + tree s1 = *(const tree*)p1; + tree s2 = *(const tree*)p2; + return strcmp (TREE_STRING_POINTER (s1), + TREE_STRING_POINTER (s2)); +} + +/* ID is the name of a function or type with abi_tags attribute TAGS. + Write out the name, suitably decorated. */ + +static void +write_abi_tags (tree tags) +{ + if (tags == NULL_TREE) + return; + + tags = TREE_VALUE (tags); + + VEC(tree,gc)* vec = make_tree_vector(); + + for (tree t = tags; t; t = TREE_CHAIN (t)) + { + tree str = TREE_VALUE (t); + VEC_safe_push (tree, gc, vec, str); + } + + VEC_qsort (tree, vec, tree_string_cmp); + + unsigned i; tree str; + FOR_EACH_VEC_ELT (tree, vec, i, str) + { + write_string ("B"); + write_unsigned_number (TREE_STRING_LENGTH (str) - 1); + write_identifier (TREE_STRING_POINTER (str)); + } + + release_tree_vector (vec); +} + /* Write a user-defined literal operator. ::= li # "" IDENTIFIER is an LITERAL_IDENTIFIER_NODE. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index bcc2779f544..5df7b6c8a76 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -49,6 +49,7 @@ static tree build_local_temp (tree); static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *); static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *); static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *); +static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *); /* If REF is an lvalue, returns the kind of lvalue that REF is. Otherwise, returns clk_none. */ @@ -3000,6 +3001,8 @@ const struct attribute_spec cxx_attribute_table[] = handle_com_interface_attribute, false }, { "init_priority", 1, 1, true, false, false, handle_init_priority_attribute, false }, + { "abi_tag", 1, -1, false, false, false, + handle_abi_tag_attribute, true }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -3131,6 +3134,96 @@ handle_init_priority_attribute (tree* node, } } +/* DECL is being redeclared; the old declaration had the abi tags in OLD, + and the new one has the tags in NEW_. Give an error if there are tags + in NEW_ that weren't in OLD. */ + +bool +check_abi_tag_redeclaration (const_tree decl, const_tree old, const_tree new_) +{ + if (old && TREE_CODE (TREE_VALUE (old)) == TREE_LIST) + old = TREE_VALUE (old); + if (new_ && TREE_CODE (TREE_VALUE (new_)) == TREE_LIST) + new_ = TREE_VALUE (new_); + bool err = false; + for (const_tree t = new_; t; t = TREE_CHAIN (t)) + { + tree str = TREE_VALUE (t); + for (const_tree in = old; in; in = TREE_CHAIN (in)) + { + tree ostr = TREE_VALUE (in); + if (cp_tree_equal (str, ostr)) + goto found; + } + error ("redeclaration of %qD adds abi tag %E", decl, str); + err = true; + found:; + } + if (err) + { + inform (DECL_SOURCE_LOCATION (decl), "previous declaration here"); + return false; + } + return true; +} + +/* Handle an "abi_tag" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_abi_tag_attribute (tree* node, tree name, tree args, + int flags, bool* no_add_attrs) +{ + if (TYPE_P (*node)) + { + if (!TAGGED_TYPE_P (*node)) + { + error ("%qE attribute applied to non-class, non-enum type %qT", + name, *node); + goto fail; + } + else if (!(flags & (int)ATTR_FLAG_TYPE_IN_PLACE)) + { + error ("%qE attribute applied to %qT after its definition", + name, *node); + goto fail; + } + + tree attributes = TYPE_ATTRIBUTES (*node); + tree decl = TYPE_NAME (*node); + + /* Make sure all declarations have the same abi tags. */ + if (DECL_SOURCE_LOCATION (decl) != input_location) + { + if (!check_abi_tag_redeclaration (decl, + lookup_attribute ("abi_tag", + attributes), + args)) + goto fail; + } + } + else + { + if (TREE_CODE (*node) != FUNCTION_DECL) + { + error ("%qE attribute applied to non-function %qD", name, *node); + goto fail; + } + else if (DECL_LANGUAGE (*node) == lang_c) + { + error ("%qE attribute applied to extern \"C\" function %qD", + name, *node); + goto fail; + } + } + + return NULL_TREE; + + fail: + *no_add_attrs = true; + return NULL_TREE; +} + /* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the thing pointed to by the constant. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 54fd54826e7..fe09b85ef0b 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -15598,6 +15598,27 @@ You must specify @option{-Wno-pmf-conversions} to use this extension. Some attributes only make sense for C++ programs. @table @code +@item abi_tag ("@var{tag}", ...) +@cindex @code{abi_tag} attribute +The @code{abi_tag} attribute can be applied to a function or class +declaration. It modifies the mangled name of the function or class to +incorporate the tag name, in order to distinguish the function or +class from an earlier version with a different ABI; perhaps the class +has changed size, or the function has a different return type that is +not encoded in the mangled name. + +The argument can be a list of strings of arbitrary length. The +strings are sorted on output, so the order of the list is +unimportant. + +A redeclaration of a function or class must not add new ABI tags, +since doing so would change the mangled name. + +The @option{-Wabi-tag} flag enables a warning about a class which does +not have all the ABI tags used by its subobjects; for users with code +that needs to coexist with an earlier ABI, using this option can help +to find all affected types that need to be tagged. + @item init_priority (@var{priority}) @cindex @code{init_priority} attribute diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 73ad2528523..608e017943c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-11-09 Jason Merrill + + * g++.dg/abi/abi-tag1.C: New. + * g++.dg/abi/abi-tag2.C: New. + 2012-11-09 Vladimir Makarov PR rtl-optimization/55154 diff --git a/gcc/testsuite/g++.dg/abi/abi-tag1.C b/gcc/testsuite/g++.dg/abi/abi-tag1.C new file mode 100644 index 00000000000..942929cdd35 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/abi-tag1.C @@ -0,0 +1,19 @@ +// { dg-options "-Wabi-tag" } + +// { dg-final { scan-assembler "_Z1fB3barB3fooi" } } +void f(int) __attribute ((abi_tag ("foo","bar"))); + +struct __attribute ((abi_tag ("bar"))) A { }; + +struct B: A { }; // { dg-warning "bar. abi tag" } +struct D { A* ap; }; // { dg-warning "bar. abi tag" } + +// { dg-final { scan-assembler "_Z1gB3baz1AB3bar" } } +void g(A) __attribute ((abi_tag ("baz"))); +void g(A) __attribute ((abi_tag ("baz"))); + +int main() +{ + f(42); + g(A()); +} diff --git a/gcc/testsuite/g++.dg/abi/abi-tag2.C b/gcc/testsuite/g++.dg/abi/abi-tag2.C new file mode 100644 index 00000000000..0e92dcc1dcc --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/abi-tag2.C @@ -0,0 +1,5 @@ +void f(int); +void f(int) __attribute ((abi_tag ("foo"))); // { dg-error "adds abi tag" } + +struct C; +struct __attribute ((abi_tag ("foo"))) C; // { dg-error "adds abi tag" } diff --git a/include/ChangeLog b/include/ChangeLog index afac33a7aef..ac2b28ed8ff 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2012-11-09 Jason Merrill + + * demangle.h (enum demangle_component_type): Add + DEMANGLE_COMPONENT_TAGGED_NAME. + 2012-10-29 Sterling Augustine Cary Coutant diff --git a/include/demangle.h b/include/demangle.h index 5da79d85221..ed019500393 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -420,6 +420,8 @@ enum demangle_component_type DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, /* A pack expansion. */ DEMANGLE_COMPONENT_PACK_EXPANSION, + /* A name with an ABI tag. */ + DEMANGLE_COMPONENT_TAGGED_NAME, /* A cloned function. */ DEMANGLE_COMPONENT_CLONE }; diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 303dda23cae..af12cd86470 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,10 @@ +2012-11-09 Jason Merrill + + * cp-demangle.c (d_dump): Handle DEMANGLE_COMPONENT_TAGGED_NAME. + (d_make_comp, d_find_pack, d_print_comp): Likewise. + (d_abi_tags): New. + (d_name): Call it. + 2012-10-08 Jason Merrill * cp-demangle.c (d_special_name, d_dump): Handle TH and TW. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 32df38c6024..86c77471200 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -508,6 +508,11 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_NAME: printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s); return; + case DEMANGLE_COMPONENT_TAGGED_NAME: + printf ("tagged name\n"); + d_dump (dc->u.s_binary.left, indent + 2); + d_dump (dc->u.s_binary.right, indent + 2); + return; case DEMANGLE_COMPONENT_TEMPLATE_PARAM: printf ("template parameter %ld\n", dc->u.s_number.number); return; @@ -809,6 +814,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: case DEMANGLE_COMPONENT_TYPED_NAME: + case DEMANGLE_COMPONENT_TAGGED_NAME: case DEMANGLE_COMPONENT_TEMPLATE: case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: @@ -1202,6 +1208,23 @@ d_encoding (struct d_info *di, int top_level) } } +/* ::= B */ + +static struct demangle_component * +d_abi_tags (struct d_info *di, struct demangle_component *dc) +{ + char peek; + while (peek = d_peek_char (di), + peek == 'B') + { + struct demangle_component *tag; + d_advance (di, 1); + tag = d_source_name (di); + dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag); + } + return dc; +} + /* ::= ::= ::= @@ -1223,14 +1246,17 @@ d_name (struct d_info *di) switch (peek) { case 'N': - return d_nested_name (di); + dc = d_nested_name (di); + break; case 'Z': - return d_local_name (di); + dc = d_local_name (di); + break; case 'L': case 'U': - return d_unqualified_name (di); + dc = d_unqualified_name (di); + break; case 'S': { @@ -1272,7 +1298,7 @@ d_name (struct d_info *di) d_template_args (di)); } - return dc; + break; } default: @@ -1287,8 +1313,12 @@ d_name (struct d_info *di) dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, d_template_args (di)); } - return dc; + break; } + + if (d_peek_char (di) == 'B') + dc = d_abi_tags (di, dc); + return dc; } /* ::= N [] E @@ -3745,6 +3775,7 @@ d_find_pack (struct d_print_info *dpi, case DEMANGLE_COMPONENT_LAMBDA: case DEMANGLE_COMPONENT_NAME: + case DEMANGLE_COMPONENT_TAGGED_NAME: case DEMANGLE_COMPONENT_OPERATOR: case DEMANGLE_COMPONENT_BUILTIN_TYPE: case DEMANGLE_COMPONENT_SUB_STD: @@ -3830,6 +3861,13 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len); return; + case DEMANGLE_COMPONENT_TAGGED_NAME: + d_print_comp (dpi, options, d_left (dc)); + d_append_string (dpi, "[abi:"); + d_print_comp (dpi, options, d_right (dc)); + d_append_char (dpi, ']'); + return; + case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: d_print_comp (dpi, options, d_left (dc)); -- cgit v1.2.3