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. From-SVN: r193367
This commit is contained in:
parent
52dccf7ac9
commit
7dbb85a793
@ -1,3 +1,7 @@
|
|||||||
|
2012-11-09 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* attribs.c (lookup_attribute_spec): Handle getting a TREE_LIST.
|
||||||
|
|
||||||
2012-11-09 Vladimir Makarov <vmakarov@redhat.com>
|
2012-11-09 Vladimir Makarov <vmakarov@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/55154
|
PR tree-optimization/55154
|
||||||
|
@ -325,12 +325,21 @@ lookup_scoped_attribute_spec (const_tree ns, const_tree name)
|
|||||||
substring_hash (attr.str, attr.length));
|
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 *
|
const struct attribute_spec *
|
||||||
lookup_attribute_spec (const_tree name)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2012-11-09 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* c.opt (Wabi-tag): New.
|
||||||
|
|
||||||
2012-11-09 Andi Kleen <ak@linux.intel.com>
|
2012-11-09 Andi Kleen <ak@linux.intel.com>
|
||||||
|
|
||||||
PR 55139
|
PR 55139
|
||||||
|
@ -257,6 +257,10 @@ Wabi
|
|||||||
C ObjC C++ ObjC++ LTO Var(warn_abi) Warning
|
C ObjC C++ ObjC++ LTO Var(warn_abi) Warning
|
||||||
Warn about things that will change when compiling with an ABI-compliant compiler
|
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
|
Wpsabi
|
||||||
C ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Undocumented
|
C ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Undocumented
|
||||||
|
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
|
2012-11-09 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* 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 <paolo.carlini@oracle.com>
|
2012-11-07 Paolo Carlini <paolo.carlini@oracle.com>
|
||||||
|
|
||||||
PR c++/55226
|
PR c++/55226
|
||||||
|
@ -1302,6 +1302,89 @@ handle_using_decl (tree using_decl, tree t)
|
|||||||
alter_access (t, decl, access);
|
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<struct abi_tag_data*>(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,
|
/* 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
|
and NO_CONST_ASN_REF_P. Also set flag bits in T based on
|
||||||
properties of the bases. */
|
properties of the bases. */
|
||||||
@ -1431,6 +1514,8 @@ check_bases (tree t,
|
|||||||
if (tm_attr)
|
if (tm_attr)
|
||||||
seen_tm_mask |= tm_attr_to_mask (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
|
/* 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))
|
&& !TYPE_HAS_CONST_COPY_ASSIGN (type))
|
||||||
*no_const_asn_ref = 1;
|
*no_const_asn_ref = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_abi_tags (t, field);
|
||||||
|
|
||||||
if (DECL_INITIAL (field) != NULL_TREE)
|
if (DECL_INITIAL (field) != NULL_TREE)
|
||||||
{
|
{
|
||||||
/* `build_class_init_list' does not recognize
|
/* `build_class_init_list' does not recognize
|
||||||
|
@ -5749,6 +5749,7 @@ extern bool type_has_nontrivial_default_init (const_tree);
|
|||||||
extern bool type_has_nontrivial_copy_init (const_tree);
|
extern bool type_has_nontrivial_copy_init (const_tree);
|
||||||
extern bool class_tmpl_impl_spec_p (const_tree);
|
extern bool class_tmpl_impl_spec_p (const_tree);
|
||||||
extern int zero_init_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 (tree);
|
||||||
extern tree strip_typedefs_expr (tree);
|
extern tree strip_typedefs_expr (tree);
|
||||||
extern tree copy_binfo (tree, tree, tree,
|
extern tree copy_binfo (tree, tree, tree,
|
||||||
|
@ -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;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
|
||||||
|
@ -173,6 +173,7 @@ static void mangle_call_offset (const tree, const tree);
|
|||||||
static void write_mangled_name (const tree, bool);
|
static void write_mangled_name (const tree, bool);
|
||||||
static void write_encoding (const tree);
|
static void write_encoding (const tree);
|
||||||
static void write_name (tree, const int);
|
static void write_name (tree, const int);
|
||||||
|
static void write_abi_tags (tree);
|
||||||
static void write_unscoped_name (const tree);
|
static void write_unscoped_name (const tree);
|
||||||
static void write_unscoped_template_name (const tree);
|
static void write_unscoped_template_name (const tree);
|
||||||
static void write_nested_name (const tree);
|
static void write_nested_name (const tree);
|
||||||
@ -1192,15 +1193,17 @@ write_unqualified_name (const tree decl)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
if (DECL_NAME (decl) == NULL_TREE)
|
if (DECL_NAME (decl) == NULL_TREE)
|
||||||
{
|
{
|
||||||
|
found = true;
|
||||||
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
|
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
|
||||||
write_source_name (DECL_ASSEMBLER_NAME (decl));
|
write_source_name (DECL_ASSEMBLER_NAME (decl));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (DECL_DECLARES_FUNCTION_P (decl))
|
else if (DECL_DECLARES_FUNCTION_P (decl))
|
||||||
{
|
{
|
||||||
bool found = true;
|
found = true;
|
||||||
if (DECL_CONSTRUCTOR_P (decl))
|
if (DECL_CONSTRUCTOR_P (decl))
|
||||||
write_special_name_constructor (decl);
|
write_special_name_constructor (decl);
|
||||||
else if (DECL_DESTRUCTOR_P (decl))
|
else if (DECL_DESTRUCTOR_P (decl))
|
||||||
@ -1234,14 +1237,13 @@ write_unqualified_name (const tree decl)
|
|||||||
write_literal_operator_name (DECL_NAME (decl));
|
write_literal_operator_name (DECL_NAME (decl));
|
||||||
else
|
else
|
||||||
found = false;
|
found = false;
|
||||||
|
|
||||||
if (found)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VAR_OR_FUNCTION_DECL_P (decl) && ! TREE_PUBLIC (decl)
|
if (found)
|
||||||
&& DECL_NAMESPACE_SCOPE_P (decl)
|
/* OK */;
|
||||||
&& decl_linkage (decl) == lk_internal)
|
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);
|
MANGLE_TRACE_TREE ("local-source-name", decl);
|
||||||
write_char ('L');
|
write_char ('L');
|
||||||
@ -1262,6 +1264,11 @@ write_unqualified_name (const tree decl)
|
|||||||
else
|
else
|
||||||
write_source_name (DECL_NAME (decl));
|
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. */
|
/* Write the unqualified-name for a conversion operator to TYPE. */
|
||||||
@ -1291,6 +1298,51 @@ write_source_name (tree identifier)
|
|||||||
write_identifier (IDENTIFIER_POINTER (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.
|
/* Write a user-defined literal operator.
|
||||||
::= li <source-name> # "" <source-name>
|
::= li <source-name> # "" <source-name>
|
||||||
IDENTIFIER is an LITERAL_IDENTIFIER_NODE. */
|
IDENTIFIER is an LITERAL_IDENTIFIER_NODE. */
|
||||||
|
@ -49,6 +49,7 @@ static tree build_local_temp (tree);
|
|||||||
static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
|
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_com_interface_attribute (tree *, tree, tree, int, bool *);
|
||||||
static tree handle_init_priority_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.
|
/* If REF is an lvalue, returns the kind of lvalue that REF is.
|
||||||
Otherwise, returns clk_none. */
|
Otherwise, returns clk_none. */
|
||||||
@ -3000,6 +3001,8 @@ const struct attribute_spec cxx_attribute_table[] =
|
|||||||
handle_com_interface_attribute, false },
|
handle_com_interface_attribute, false },
|
||||||
{ "init_priority", 1, 1, true, false, false,
|
{ "init_priority", 1, 1, true, false, false,
|
||||||
handle_init_priority_attribute, 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 }
|
{ 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
|
/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
|
||||||
thing pointed to by the constant. */
|
thing pointed to by the constant. */
|
||||||
|
|
||||||
|
@ -15598,6 +15598,27 @@ You must specify @option{-Wno-pmf-conversions} to use this extension.
|
|||||||
Some attributes only make sense for C++ programs.
|
Some attributes only make sense for C++ programs.
|
||||||
|
|
||||||
@table @code
|
@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})
|
@item init_priority (@var{priority})
|
||||||
@cindex @code{init_priority} attribute
|
@cindex @code{init_priority} attribute
|
||||||
|
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2012-11-09 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* g++.dg/abi/abi-tag1.C: New.
|
||||||
|
* g++.dg/abi/abi-tag2.C: New.
|
||||||
|
|
||||||
2012-11-09 Vladimir Makarov <vmakarov@redhat.com>
|
2012-11-09 Vladimir Makarov <vmakarov@redhat.com>
|
||||||
|
|
||||||
PR rtl-optimization/55154
|
PR rtl-optimization/55154
|
||||||
|
19
gcc/testsuite/g++.dg/abi/abi-tag1.C
Normal file
19
gcc/testsuite/g++.dg/abi/abi-tag1.C
Normal file
@ -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());
|
||||||
|
}
|
5
gcc/testsuite/g++.dg/abi/abi-tag2.C
Normal file
5
gcc/testsuite/g++.dg/abi/abi-tag2.C
Normal file
@ -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" }
|
@ -1,3 +1,8 @@
|
|||||||
|
2012-11-09 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* demangle.h (enum demangle_component_type): Add
|
||||||
|
DEMANGLE_COMPONENT_TAGGED_NAME.
|
||||||
|
|
||||||
2012-10-29 Sterling Augustine <saugustine@google.com>
|
2012-10-29 Sterling Augustine <saugustine@google.com>
|
||||||
Cary Coutant <ccoutant@google.com>
|
Cary Coutant <ccoutant@google.com>
|
||||||
|
|
||||||
|
@ -420,6 +420,8 @@ enum demangle_component_type
|
|||||||
DEMANGLE_COMPONENT_NONTRANSACTION_CLONE,
|
DEMANGLE_COMPONENT_NONTRANSACTION_CLONE,
|
||||||
/* A pack expansion. */
|
/* A pack expansion. */
|
||||||
DEMANGLE_COMPONENT_PACK_EXPANSION,
|
DEMANGLE_COMPONENT_PACK_EXPANSION,
|
||||||
|
/* A name with an ABI tag. */
|
||||||
|
DEMANGLE_COMPONENT_TAGGED_NAME,
|
||||||
/* A cloned function. */
|
/* A cloned function. */
|
||||||
DEMANGLE_COMPONENT_CLONE
|
DEMANGLE_COMPONENT_CLONE
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
2012-11-09 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* 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 <jason@redhat.com>
|
2012-10-08 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
* cp-demangle.c (d_special_name, d_dump): Handle TH and TW.
|
* cp-demangle.c (d_special_name, d_dump): Handle TH and TW.
|
||||||
|
@ -508,6 +508,11 @@ d_dump (struct demangle_component *dc, int indent)
|
|||||||
case DEMANGLE_COMPONENT_NAME:
|
case DEMANGLE_COMPONENT_NAME:
|
||||||
printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
|
printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
|
||||||
return;
|
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:
|
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
|
||||||
printf ("template parameter %ld\n", dc->u.s_number.number);
|
printf ("template parameter %ld\n", dc->u.s_number.number);
|
||||||
return;
|
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_QUAL_NAME:
|
||||||
case DEMANGLE_COMPONENT_LOCAL_NAME:
|
case DEMANGLE_COMPONENT_LOCAL_NAME:
|
||||||
case DEMANGLE_COMPONENT_TYPED_NAME:
|
case DEMANGLE_COMPONENT_TYPED_NAME:
|
||||||
|
case DEMANGLE_COMPONENT_TAGGED_NAME:
|
||||||
case DEMANGLE_COMPONENT_TEMPLATE:
|
case DEMANGLE_COMPONENT_TEMPLATE:
|
||||||
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
|
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
|
||||||
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
|
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
|
||||||
@ -1202,6 +1208,23 @@ d_encoding (struct d_info *di, int top_level)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* <tagged-name> ::= <name> B <source-name> */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* <name> ::= <nested-name>
|
/* <name> ::= <nested-name>
|
||||||
::= <unscoped-name>
|
::= <unscoped-name>
|
||||||
::= <unscoped-template-name> <template-args>
|
::= <unscoped-template-name> <template-args>
|
||||||
@ -1223,14 +1246,17 @@ d_name (struct d_info *di)
|
|||||||
switch (peek)
|
switch (peek)
|
||||||
{
|
{
|
||||||
case 'N':
|
case 'N':
|
||||||
return d_nested_name (di);
|
dc = d_nested_name (di);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'Z':
|
case 'Z':
|
||||||
return d_local_name (di);
|
dc = d_local_name (di);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
case 'U':
|
case 'U':
|
||||||
return d_unqualified_name (di);
|
dc = d_unqualified_name (di);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
{
|
{
|
||||||
@ -1272,7 +1298,7 @@ d_name (struct d_info *di)
|
|||||||
d_template_args (di));
|
d_template_args (di));
|
||||||
}
|
}
|
||||||
|
|
||||||
return dc;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1287,8 +1313,12 @@ d_name (struct d_info *di)
|
|||||||
dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
|
dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
|
||||||
d_template_args (di));
|
d_template_args (di));
|
||||||
}
|
}
|
||||||
return dc;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d_peek_char (di) == 'B')
|
||||||
|
dc = d_abi_tags (di, dc);
|
||||||
|
return dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
|
/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
|
||||||
@ -3745,6 +3775,7 @@ d_find_pack (struct d_print_info *dpi,
|
|||||||
|
|
||||||
case DEMANGLE_COMPONENT_LAMBDA:
|
case DEMANGLE_COMPONENT_LAMBDA:
|
||||||
case DEMANGLE_COMPONENT_NAME:
|
case DEMANGLE_COMPONENT_NAME:
|
||||||
|
case DEMANGLE_COMPONENT_TAGGED_NAME:
|
||||||
case DEMANGLE_COMPONENT_OPERATOR:
|
case DEMANGLE_COMPONENT_OPERATOR:
|
||||||
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
|
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
|
||||||
case DEMANGLE_COMPONENT_SUB_STD:
|
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);
|
d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
|
||||||
return;
|
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_QUAL_NAME:
|
||||||
case DEMANGLE_COMPONENT_LOCAL_NAME:
|
case DEMANGLE_COMPONENT_LOCAL_NAME:
|
||||||
d_print_comp (dpi, options, d_left (dc));
|
d_print_comp (dpi, options, d_left (dc));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user