PR c++/53528 C++11 attribute support

This patch implements the c++-11 generalized attributes, described in
the N2761 paper[1].

The idea is to modify the front-end to accept the new attribute syntax
(including alignas expressions) and to build an internal
representation similar to the one we already have for GNU attributes.

This lets us re-use our existing GNU attribute mechanisms to support
the generalized c++11 attributes.

The patch does change the existing internal representation to support
scoped attribute (aka attributes with namespaces), which is a concept
that doesn't exist in GNU attributes.  I have thus put all existing
GNU extension attributes into the "gnu" namespace.  For instance, in
C++-11, the "unused" attribute would be represented as
"[[gnu::unused]]".  Because there is no syntax for scoped attributes
in C, writting "__attribute__((unused))" unconditionnally refers to
the "unused" attribute in the "gnu" namespace.

Note that this patch follows a conservative understanding of the
specification by disallowing attributes appertaining to types, unless
they apply to a type definition.

Tested on x86_64-unknown-linux-gnu and powerpc64-unknown-linux-gnu.

[1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf

gcc/
	* plugin.h (register_scoped_attributes): Declare new function.
	* tree.h (enu attribute_flags::ATTR_FLAG_CXX_11): New flag.
	(lookup_scoped_attribute_spec, cxx_11_attribute_p)
	(get_attribute_name, get_attribute_namespace): Declare new functions.
	(struct attribute_spec): Remove const qualifier from the members.
	* tree.c (comp_type_attributes, private_lookup_attribute)
	(lookup_ident_attribute, remove_attribute, merge_attribute)
	(attribute_hash_list, attribute_list_contained): Use
	get_attribute_name.
	* attribs.c (decl_attributes): Don't crash on error_mark_node.
	Forbid c++11 attributes appertaining to type-specifiers.
	(attribute_hash): Remove global variable.
	(attributes_table): New global variable.
	(find_attribute_namespace, register_scoped_attribute): New static
	functions.
	(register_scoped_attributes, lookup_scoped_attribute_spec)
	(cxx11_attribute_p, get_attribute_name, get_attribute_namespace):
	New public functions.
	(init_attributes): Register all the GNU attributes into the "gnu"
	namespace.
	(register_attribute): Use register_scoped_attribute to register
	the attribute into the "gnu" namespace.
	(lookup_attribute_spec): Use lookup_scoped_attribute_spec to
	lookup the attribute in the "gnu" namespace.
	(decl_attributes): Use new get_attribute_namespace and
	lookup_scoped_attribute_spec to consider attribute namespaces when
	looking up attributes.  When operating in c++-11 mode, pass flag
	ATTR_FLAG_CXX11 to the spec handler.

gcc/c-family/

	* c-common.h (bitfield_p, cxx_fundamental_alignment_p): Declare
	new functions.
	* c-common.c (check_cxx_fundamental_alignment_constraints): New
	static function.
	(handle_aligned_attribute): In choose strictest alignment
	among many.  Use new check_cxx_fundamental_alignment_constraints.
	(handle_transparent_union_attribute): In c++11 attribute syntax,
	don't look through typedefs.

gcc/cp/

	* cp-tree.h (enum cpp0x_warn_str::CPP0X_ATTRIBUTES): New member.
	(enum cp_decl_spec::ds_std_attribute): New enumerator.
	(struct cp_decl_specifier_seq::std_attributes): New field.
	(cxx_alignas_expr, warn_misplaced_attr_for_class_type): Declare
	new functions.
	(check_tag_decl): Take an extra parameter for explicit
	instantiations.
	* decl.c (warn_misplaced_attr_for_class_type): Extract from ...
	(check_tag_decl): ... here.  Add check for c++11 attributes being
	applied to an explicit instantiation.  Take an extra parameter for
	explicit instantiations.
	(grokdeclarator): Make sure a c++11 attribute after an array
	declarator appertains to the array, an attribute after a function
	declarator appertains to the function type, an attribute after a
	declarator-id appertains to the entity being declared, and an
	attribute after a pointer declarator appertains to the pointer.
	* decl2.c (is_late_template_attribute): Use get_attribute_name.
	* error.c (maybe_warn_cpp0x): Support
	CPP0X_GENERALIZED_ATTRIBUTES.
	* parser.c (cp_next_tokens_can_be_attribute_p)
	(cp_next_tokens_can_be_gnu_attribute_p)
	(cp_next_tokens_can_be_std_attribute_p)
	(cp_nth_tokens_can_be_attribute_p)
	(cp_nth_tokens_can_be_gnu_attribute_p)
	(cp_nth_tokens_can_be_std_attribute_p)
	(cp_parser_gnu_attribute_list, cp_parser_std_attribute)
	(cp_parser_std_attribute_spec, cp_parser_std_attribute_spec_seq)
	(cp_parser_attributes_opt, cp_parser_std_attribute_list): New
	static functions.
	(cp_parser_gnu_attributes_opt): Replace cp_parser_attributes_opt.
	(cp_parser_gnu_attribute_list): Replace cp_parser_attribute_list.
	(cp_parser_postfix_expression): Disallow "[[" tokens here.
	(cp_parser_label_for_labeled_statement): Use take an extra
	parameter for attributes.
	(cp_parser_block_declaration): Use
	cp_nth_tokens_can_be_std_attribute_p here.
	(cp_parser_decl_specifier_seq): Likewise.  Store C++11 attributes
	that appears in in decl specifiers in cp_decl_specifier_seq::std_attributes.
	declaration.  Emit proper warning about misplaced c++11 attributes
	for class type.
	(cp_parser_explicit_instantiation): Adjust call to check_tag_decl.
	(cp_parser_init_declarator):  Parsing attributes here is no more a
	GNU extension in c++-11.
	(cp_parser_type_specifier_seq): Use
	cp_next_tokens_can_be_attribute_p.
	(cp_parser_direct_declarator): Likewise.  Hang c++11 attributes
	following the declarator to its syntactic construct.  It'll later
	be applied to the proper appertaining entity by grokdeclarator.
	(cp_parser_ptr_operator): Likewise.
	(make_declarator): Initialize cp_declarator::std_attribute.
	(make_pointer_declarator, make_reference_declarator)
	(make_ptrmem_declarator, cp_parser_make_indirect_declarator): Take
	attributes that appertain to the pointer/reference in argument.
	(cp_parser_ptr_operator): Take an out parameter for c++11
	attributes.  Update comments.
	(cp_parser_new_declarator_opt)
	(cp_parser_conversion_declarator_opt): Adjust.
	(cp_parser_declarator): Likewise.  Handle C++11 attributes.
	Rename attributes to gnu_attribute for better legibility.
	(cp_parser_simple_declaration): Update comment.
	(cp_parser_class_specifier_1): Parse GNU attributes specifically
	(cp_parser_enum_specifier): Accept only gnu attributes after the
	specifier.
	(cp_parser_member_declaration): Don't clear attributes -- intended
	for the entity being declared -- too early because check_tag_decl
	needs them.
	(cp_parser_statement): Update comment.  Parse optional c++11
	attributes at the beginning of the relevant kind of statements and
	ignore them, for now, unless when calling
	cp_parser_label_for_labeled_statement.
	(cp_parser_label_for_labeled_statement): Take c++11 attributes
	in parameter.
	* semantics.c (potential_constant_expression_1): Likewise.
	* typeck.c (fundamental_alignment_p, cxx_alignas_expr): New public
	functions.

gcc/testsuite/

	* g++.dg/cpp0x/gen-attrs-1.C: New test.
	* g++.dg/cpp0x/gen-attrs-2.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-2-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-3.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-4.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-5.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-6.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-7.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-8.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-9.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-10.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-11.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-12.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-13.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-14.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-15.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-16.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-17.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-18.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-19.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-20.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-21.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-22.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-23.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-24.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-25.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-26.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-27.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-28.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-29.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-30.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-31.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-32.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-33.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-34.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-35.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-36.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-36-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-37.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-38.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-39.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-39-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-40.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-41.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-42.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-43.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-44.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-45.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-46.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-47.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-47-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-48.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-49.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-50.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-51.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-52.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-53.C: Likewise.

From-SVN: r192199
This commit is contained in:
Dodji Seketeli 2012-10-08 09:29:05 +00:00 committed by Dodji Seketeli
parent f70308d411
commit e28d52cffb
74 changed files with 2089 additions and 142 deletions

View File

@ -1,3 +1,35 @@
2012-10-08 Dodji Seketeli <dodji@redhat.com>
PR c++/53528 C++11 attribute support
* plugin.h (register_scoped_attributes): Declare new function.
* tree.h (enu attribute_flags::ATTR_FLAG_CXX_11): New flag.
(lookup_scoped_attribute_spec, cxx_11_attribute_p)
(get_attribute_name, get_attribute_namespace): Declare new functions.
(struct attribute_spec): Remove const qualifier from the members.
* tree.c (comp_type_attributes, private_lookup_attribute)
(lookup_ident_attribute, remove_attribute, merge_attribute)
(attribute_hash_list, attribute_list_contained): Use
get_attribute_name.
* attribs.c (decl_attributes): Don't crash on error_mark_node.
Forbid c++11 attributes appertaining to type-specifiers.
(attribute_hash): Remove global variable.
(attributes_table): New global variable.
(find_attribute_namespace, register_scoped_attribute): New static
functions.
(register_scoped_attributes, lookup_scoped_attribute_spec)
(cxx11_attribute_p, get_attribute_name, get_attribute_namespace):
New public functions.
(init_attributes): Register all the GNU attributes into the "gnu"
namespace.
(register_attribute): Use register_scoped_attribute to register
the attribute into the "gnu" namespace.
(lookup_attribute_spec): Use lookup_scoped_attribute_spec to
lookup the attribute in the "gnu" namespace.
(decl_attributes): Use new get_attribute_namespace and
lookup_scoped_attribute_spec to consider attribute namespaces when
looking up attributes. When operating in c++-11 mode, pass flag
ATTR_FLAG_CXX11 to the spec handler.
2012-10-08 Georg-Johann Lay <avr@gjlay.de>
PR target/54815

View File

@ -38,9 +38,6 @@ along with GCC; see the file COPYING3. If not see
searched. */
static const struct attribute_spec *attribute_tables[4];
/* Hashtable mapping names (represented as substrings) to attribute specs. */
static htab_t attribute_hash;
/* Substring representation. */
struct substring
@ -49,6 +46,28 @@ struct substring
int length;
};
DEF_VEC_O (attribute_spec);
DEF_VEC_ALLOC_O (attribute_spec, heap);
/* Scoped attribute name representation. */
struct scoped_attributes
{
const char *ns;
VEC (attribute_spec, heap) *attributes;
htab_t attribute_hash;
};
DEF_VEC_O (scoped_attributes);
DEF_VEC_ALLOC_O (scoped_attributes, heap);
/* The table of scope attributes. */
static VEC(scoped_attributes, heap) *attributes_table;
static scoped_attributes* find_attribute_namespace (const char*);
static void register_scoped_attribute (const struct attribute_spec *,
scoped_attributes *);
static bool attributes_initialized = false;
/* Default empty table of attributes. */
@ -102,6 +121,64 @@ eq_attr (const void *p, const void *q)
return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]);
}
/* Insert an array of attributes ATTRIBUTES into a namespace. This
array must be NULL terminated. NS is the name of attribute
namespace. The function returns the namespace into which the
attributes have been registered. */
scoped_attributes*
register_scoped_attributes (const struct attribute_spec * attributes,
const char* ns)
{
scoped_attributes *result = NULL;
/* See if we already have attributes in the namespace NS. */
result = find_attribute_namespace (ns);
if (result == NULL)
{
/* We don't have any namespace NS yet. Create one. */
scoped_attributes sa;
if (attributes_table == NULL)
attributes_table = VEC_alloc (scoped_attributes, heap, 64);
memset (&sa, 0, sizeof (sa));
sa.ns = ns;
sa.attributes = VEC_alloc (attribute_spec, heap, 64);
result = VEC_safe_push (scoped_attributes, heap, attributes_table, sa);
}
/* Really add the attributes to their namespace now. */
for (unsigned i = 0; attributes[i].name != NULL; ++i)
{
VEC_safe_push (attribute_spec, heap,
result->attributes, attributes[i]);
register_scoped_attribute (&attributes[i], result);
}
gcc_assert (result != NULL);
return result;
}
/* Return the namespace which name is NS, NULL if none exist. */
static scoped_attributes*
find_attribute_namespace (const char* ns)
{
unsigned ix;
scoped_attributes *iter;
FOR_EACH_VEC_ELT (scoped_attributes, attributes_table, ix, iter)
if (ns == iter->ns
|| (iter->ns != NULL
&& ns != NULL
&& !strcmp (iter->ns, ns)))
return iter;
return NULL;
}
/* Initialize attribute tables, and make some sanity checks
if --enable-checking. */
@ -109,7 +186,6 @@ void
init_attributes (void)
{
size_t i;
int k;
if (attributes_initialized)
return;
@ -181,12 +257,10 @@ init_attributes (void)
}
#endif
attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
for (k = 0; attribute_tables[i][k].name != NULL; k++)
{
register_attribute (&attribute_tables[i][k]);
}
for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
/* Put all the GNU attributes into the "gnu" namespace. */
register_scoped_attributes (attribute_tables[i], "gnu");
invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
attributes_initialized = true;
}
@ -195,10 +269,24 @@ init_attributes (void)
void
register_attribute (const struct attribute_spec *attr)
{
register_scoped_attribute (attr, find_attribute_namespace ("gnu"));
}
/* Insert a single attribute ATTR into a namespace of attributes. */
static void
register_scoped_attribute (const struct attribute_spec *attr,
scoped_attributes *name_space)
{
struct substring str;
void **slot;
gcc_assert (attr != NULL && name_space != NULL);
if (name_space->attribute_hash == NULL)
name_space->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
str.str = attr->name;
str.length = strlen (str.str);
@ -206,27 +294,45 @@ register_attribute (const struct attribute_spec *attr)
in the form '__text__'. */
gcc_assert (str.length > 0 && str.str[0] != '_');
slot = htab_find_slot_with_hash (attribute_hash, &str,
slot = htab_find_slot_with_hash (name_space->attribute_hash, &str,
substring_hash (str.str, str.length),
INSERT);
gcc_assert (!*slot || attr->name[0] == '*');
*slot = (void *) CONST_CAST (struct attribute_spec *, attr);
}
/* Return the spec for the scoped attribute with namespace NS and
name NAME. */
const struct attribute_spec *
lookup_scoped_attribute_spec (const_tree ns, const_tree name)
{
struct substring attr;
scoped_attributes *attrs;
const char *ns_str = (ns != NULL_TREE) ? IDENTIFIER_POINTER (ns): NULL;
attrs = find_attribute_namespace (ns_str);
if (attrs == NULL)
return NULL;
attr.str = IDENTIFIER_POINTER (name);
attr.length = IDENTIFIER_LENGTH (name);
extract_attribute_substring (&attr);
return (const struct attribute_spec *)
htab_find_with_hash (attrs->attribute_hash, &attr,
substring_hash (attr.str, attr.length));
}
/* Return the spec for the attribute named NAME. */
const struct attribute_spec *
lookup_attribute_spec (const_tree name)
{
struct substring attr;
attr.str = IDENTIFIER_POINTER (name);
attr.length = IDENTIFIER_LENGTH (name);
extract_attribute_substring (&attr);
return (const struct attribute_spec *)
htab_find_with_hash (attribute_hash, &attr,
substring_hash (attr.str, attr.length));
return lookup_scoped_attribute_spec (get_identifier ("gnu"), name);
}
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
@ -243,7 +349,7 @@ decl_attributes (tree *node, tree attributes, int flags)
tree a;
tree returned_attrs = NULL_TREE;
if (TREE_TYPE (*node) == error_mark_node)
if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
return NULL_TREE;
if (!attributes_initialized)
@ -302,10 +408,12 @@ decl_attributes (tree *node, tree attributes, int flags)
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
tree ns = get_attribute_namespace (a);
tree name = get_attribute_name (a);
tree args = TREE_VALUE (a);
tree *anode = node;
const struct attribute_spec *spec = lookup_attribute_spec (name);
const struct attribute_spec *spec =
lookup_scoped_attribute_spec (ns, name);
bool no_add_attrs = 0;
int fn_ptr_quals = 0;
tree fn_ptr_tmp = NULL_TREE;
@ -313,8 +421,15 @@ decl_attributes (tree *node, tree attributes, int flags)
if (spec == NULL)
{
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
warning (OPT_Wattributes, "%qE attribute directive ignored",
name);
{
if (ns == NULL_TREE || !cxx11_attribute_p (a))
warning (OPT_Wattributes, "%qE attribute directive ignored",
name);
else
warning (OPT_Wattributes,
"%<%E::%E%> scoped attribute directive ignored",
ns, name);
}
continue;
}
else if (list_length (args) < spec->min_length
@ -327,6 +442,20 @@ decl_attributes (tree *node, tree attributes, int flags)
}
gcc_assert (is_attribute_p (spec->name, name));
if (TYPE_P (*node)
&& cxx11_attribute_p (a)
&& !(flags & ATTR_FLAG_TYPE_IN_PLACE))
{
/* This is a c++11 attribute that appertains to a
type-specifier, outside of the definition of, a class
type. Ignore it. */
warning (OPT_Wattributes, "attribute ignored");
inform (input_location,
"an attribute that appertains to a type-specifier "
"is ignored");
continue;
}
if (spec->decl_required && !DECL_P (*anode))
{
if (flags & ((int) ATTR_FLAG_DECL_NEXT
@ -406,9 +535,15 @@ decl_attributes (tree *node, tree attributes, int flags)
}
if (spec->handler != NULL)
returned_attrs = chainon ((*spec->handler) (anode, name, args,
flags, &no_add_attrs),
returned_attrs);
{
int cxx11_flag =
cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
returned_attrs = chainon ((*spec->handler) (anode, name, args,
flags|cxx11_flag,
&no_add_attrs),
returned_attrs);
}
/* Layout the decl in case anything changed. */
if (spec->type_required && DECL_P (*node)
@ -488,6 +623,56 @@ decl_attributes (tree *node, tree attributes, int flags)
return returned_attrs;
}
/* Return TRUE iff ATTR has been parsed by the front-end as a C++-11
attribute.
When G++ parses a C++11 attribute, it is represented as
a TREE_LIST which TREE_PURPOSE is itself a TREE_LIST. TREE_PURPOSE
(TREE_PURPOSE (ATTR)) is the namespace of the attribute, and the
TREE_VALUE (TREE_PURPOSE (ATTR)) is its non-qualified name. Please
use get_attribute_namespace and get_attribute_name to retrieve the
namespace and name of the attribute, as these accessors work with
GNU attributes as well. */
bool
cxx11_attribute_p (const_tree attr)
{
if (attr == NULL_TREE
|| TREE_CODE (attr) != TREE_LIST)
return false;
return (TREE_CODE (TREE_PURPOSE (attr)) == TREE_LIST);
}
/* Return the name of the attribute ATTR. This accessor works on GNU
and C++11 (scoped) attributes.
Please read the comments of cxx11_attribute_p to understand the
format of attributes. */
tree
get_attribute_name (const_tree attr)
{
if (cxx11_attribute_p (attr))
return TREE_VALUE (TREE_PURPOSE (attr));
return TREE_PURPOSE (attr);
}
/* Return the namespace of the attribute ATTR. This accessor works on
GNU and C++11 (scoped) attributes. On GNU attributes,
it returns an identifier tree for the string "gnu".
Please read the comments of cxx11_attribute_p to understand the
format of attributes. */
tree
get_attribute_namespace (const_tree attr)
{
if (cxx11_attribute_p (attr))
return TREE_PURPOSE (TREE_PURPOSE (attr));
return get_identifier ("gnu");
}
/* Subroutine of set_method_tm_attributes. Apply TM attribute ATTR
to the method FNDECL. */

View File

@ -1,3 +1,15 @@
2012-10-08 Dodji Seketeli <dodji@redhat.com>
PR c++/53528 C++11 attribute support
* c-common.h (bitfield_p, cxx_fundamental_alignment_p): Declare
new functions.
* c-common.c (check_cxx_fundamental_alignment_constraints): New
static function.
(handle_aligned_attribute): In choose strictest alignment
among many. Use new check_cxx_fundamental_alignment_constraints.
(handle_transparent_union_attribute): In c++11 attribute syntax,
don't look through typedefs.
2012-10-04 Arnaud Charlet <charlet@adacore.com>
* c-ada-spec.c (print_ada_declaration): Remove handling of TDF_RAW.

View File

@ -484,6 +484,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
{ "__volatile", RID_VOLATILE, 0 },
{ "__volatile__", RID_VOLATILE, 0 },
{ "alignas", RID_ALIGNAS, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "asm", RID_ASM, D_ASM },
{ "auto", RID_AUTO, 0 },
@ -6665,7 +6666,9 @@ handle_transparent_union_attribute (tree *node, tree name,
*no_add_attrs = true;
if (TREE_CODE (*node) == TYPE_DECL)
if (TREE_CODE (*node) == TYPE_DECL
&& ! (flags & ATTR_FLAG_CXX11))
node = &TREE_TYPE (*node);
type = *node;
@ -7137,6 +7140,89 @@ check_user_alignment (const_tree align, bool allow_zero)
return i;
}
/*
If in c++-11, check if the c++-11 alignment constraint with respect
to fundamental alignment (in [dcl.align]) are satisfied. If not in
c++-11 mode, does nothing.
[dcl.align]2/ says:
[* if the constant expression evaluates to a fundamental alignment,
the alignment requirement of the declared entity shall be the
specified fundamental alignment.
* if the constant expression evaluates to an extended alignment
and the implementation supports that alignment in the context
of the declaration, the alignment of the declared entity shall
be that alignment
* if the constant expression evaluates to an extended alignment
and the implementation does not support that alignment in the
context of the declaration, the program is ill-formed]. */
static bool
check_cxx_fundamental_alignment_constraints (tree node,
unsigned align_log,
int flags)
{
bool alignment_too_large_p = false;
unsigned requested_alignment = 1U << align_log;
unsigned max_align = 0;
if ((!(flags & ATTR_FLAG_CXX11) && !warn_cxx_compat)
|| (node == NULL_TREE || node == error_mark_node))
return true;
if (cxx_fundamental_alignment_p (requested_alignment))
return true;
if (DECL_P (node))
{
if (TREE_STATIC (node))
{
/* For file scope variables and static members, the target
supports alignments that are at most
MAX_OFILE_ALIGNMENT. */
if (requested_alignment > (max_align = MAX_OFILE_ALIGNMENT))
alignment_too_large_p = true;
}
else
{
#ifdef BIGGEST_FIELD_ALIGNMENT
#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_FIELD_ALIGNMENT
#else
#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_ALIGNMENT
#endif
/* For non-static members, the target supports either
alignments that at most either BIGGEST_FIELD_ALIGNMENT
if it is defined or BIGGEST_ALIGNMENT. */
max_align = MAX_TARGET_FIELD_ALIGNMENT;
if (TREE_CODE (node) == FIELD_DECL
&& requested_alignment > (max_align = MAX_TARGET_FIELD_ALIGNMENT))
alignment_too_large_p = true;
#undef MAX_TARGET_FIELD_ALIGNMENT
/* For stack variables, the target supports at most
MAX_STACK_ALIGNMENT. */
else if (decl_function_context (node) != NULL
&& requested_alignment > (max_align = MAX_STACK_ALIGNMENT))
alignment_too_large_p = true;
}
}
else if (TYPE_P (node))
{
/* Let's be liberal for types. */
if (requested_alignment > (max_align = BIGGEST_ALIGNMENT))
alignment_too_large_p = true;
}
if (alignment_too_large_p)
pedwarn (input_location, OPT_Wattributes,
"requested alignment %d is larger than %d",
requested_alignment, max_align);
return !alignment_too_large_p;
}
/* Handle a "aligned" attribute; arguments as in
struct attribute_spec.handler. */
@ -7160,7 +7246,8 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
else if (TYPE_P (*node))
type = node, is_type = 1;
if ((i = check_user_alignment (align_expr, false)) == -1)
if ((i = check_user_alignment (align_expr, false)) == -1
|| !check_cxx_fundamental_alignment_constraints (*node, i, flags))
*no_add_attrs = true;
else if (is_type)
{
@ -7190,6 +7277,17 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
error ("alignment may not be specified for %q+D", decl);
*no_add_attrs = true;
}
else if (DECL_USER_ALIGN (decl)
&& DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
/* C++-11 [dcl.align/4]:
When multiple alignment-specifiers are specified for an
entity, the alignment requirement shall be set to the
strictest specified alignment.
This formally comes from the c++11 specification but we are
doing it for the GNU attribute syntax as well. */
*no_add_attrs = true;
else if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
{
@ -11154,4 +11252,22 @@ convert_vector_to_pointer_for_subscript (location_t loc,
}
}
/* Return true iff ALIGN is an integral constant that is a fundamental
alignment, as defined by [basic.align] in the c++-11
specifications.
That is:
[A fundamental alignment is represented by an alignment less than or
equal to the greatest alignment supported by the implementation
in all contexts, which is equal to
alignof(max_align_t)]. */
bool
cxx_fundamental_alignment_p (unsigned align)
{
return (align <= MAX (TYPE_ALIGN (long_long_integer_type_node),
TYPE_ALIGN (long_double_type_node)));
}
#include "gt-c-family-c-common.h"

View File

@ -789,6 +789,7 @@ extern bool keyword_begins_type_specifier (enum rid);
extern bool keyword_is_storage_class_specifier (enum rid);
extern bool keyword_is_type_qualifier (enum rid);
extern bool keyword_is_decl_specifier (enum rid);
extern bool cxx_fundamental_alignment_p (unsigned);
#define c_sizeof(LOC, T) c_sizeof_or_alignof_type (LOC, T, true, 1)
#define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, 1)

View File

@ -1,3 +1,82 @@
2012-10-08 Dodji Seketeli <dodji@redhat.com>
PR c++/53528 C++11 attribute support
* cp-tree.h (enum cpp0x_warn_str::CPP0X_ATTRIBUTES): New member.
(enum cp_decl_spec::ds_std_attribute): New enumerator.
(struct cp_decl_specifier_seq::std_attributes): New field.
(cxx_alignas_expr, warn_misplaced_attr_for_class_type): Declare
new functions.
(check_tag_decl): Take an extra parameter for explicit
instantiations.
* decl.c (warn_misplaced_attr_for_class_type): Extract from ...
(check_tag_decl): ... here. Add check for c++11 attributes being
applied to an explicit instantiation. Take an extra parameter for
explicit instantiations.
(grokdeclarator): Make sure a c++11 attribute after an array
declarator appertains to the array, an attribute after a function
declarator appertains to the function type, an attribute after a
declarator-id appertains to the entity being declared, and an
attribute after a pointer declarator appertain to the pointer.
* decl2.c (is_late_template_attribute): Use get_attribute_name.
* error.c (maybe_warn_cpp0x): Support
CPP0X_GENERALIZED_ATTRIBUTES.
* parser.c (cp_next_tokens_can_be_attribute_p)
(cp_next_tokens_can_be_gnu_attribute_p)
(cp_next_tokens_can_be_std_attribute_p)
(cp_nth_tokens_can_be_attribute_p)
(cp_nth_tokens_can_be_gnu_attribute_p)
(cp_nth_tokens_can_be_std_attribute_p)
(cp_parser_gnu_attribute_list, cp_parser_std_attribute)
(cp_parser_std_attribute_spec, cp_parser_std_attribute_spec_seq)
(cp_parser_attributes_opt, cp_parser_std_attribute_list): New
static functions.
(cp_parser_gnu_attributes_opt): Replace cp_parser_attributes_opt.
(cp_parser_gnu_attribute_list): Replace cp_parser_attribute_list.
(cp_parser_postfix_expression): Disallow "[[" tokens here.
(cp_parser_label_for_labeled_statement): Use take an extra
parameter for attributes.
(cp_parser_block_declaration): Use
cp_nth_tokens_can_be_std_attribute_p here.
(cp_parser_decl_specifier_seq): Likewise. Store C++11 attributes
that appears in in decl specifiers in cp_decl_specifier_seq::std_attributes.
declaration. Emit proper warning about misplaced c++11 attributes
for class type.
(cp_parser_explicit_instantiation): Adjust call to check_tag_decl.
(cp_parser_init_declarator): Parsing attributes here is no more a
GNU extension in c++-11.
(cp_parser_type_specifier_seq): Use
cp_next_tokens_can_be_attribute_p.
(cp_parser_direct_declarator): Likewise. Hang c++11 attributes
following the declarator to its syntactic construct. It'll later
be applied to the proper appertaining entity by grokdeclarator.
(cp_parser_ptr_operator): Likewise.
(make_declarator): Initialize cp_declarator::std_attribute.
(make_pointer_declarator, make_reference_declarator)
(make_ptrmem_declarator, cp_parser_make_indirect_declarator): Take
attributes that appertain to the pointer/reference in argument.
(cp_parser_ptr_operator): Take an out parameter for c++11
attributes. Update comments.
(cp_parser_new_declarator_opt)
(cp_parser_conversion_declarator_opt): Adjust.
(cp_parser_declarator): Likewise. Handle C++11 attributes.
Rename attributes to gnu_attribute for better legibility.
(cp_parser_simple_declaration): Update comment.
(cp_parser_class_specifier_1): Parse GNU attributes specifically
(cp_parser_enum_specifier): Accept only gnu attributes after the
specifier.
(cp_parser_member_declaration): Don't clear attributes -- intended
for the entity being declared -- too early because check_tag_decl
needs them.
(cp_parser_statement): Update comment. Parse optional c++11
attributes at the beginning of the relevant kind of statements and
ignore them, for now, unless when calling
cp_parser_label_for_labeled_statement.
(cp_parser_label_for_labeled_statement): Take c++11 attributes
in parameter.
* semantics.c (potential_constant_expression_1): Likewise.
* typeck.c (fundamental_alignment_p, cxx_alignas_expr): New public
functions.
2012-10-07 Paolo Carlini <paolo.carlini@oracle.com>
* pt.c (fold_non_dependent_expr_sfinae): Remove static specifier.

View File

@ -418,7 +418,9 @@ typedef enum cpp0x_warn_str
/* user defined literals */
CPP0X_USER_DEFINED_LITERALS,
/* delegating constructors */
CPP0X_DELEGATING_CTORS
CPP0X_DELEGATING_CTORS,
/* C++11 attributes */
CPP0X_ATTRIBUTES
} cpp0x_warn_str;
/* The various kinds of operation used by composite_pointer_type. */
@ -4684,6 +4686,7 @@ typedef enum cp_decl_spec {
ds_type_spec,
ds_redefined_builtin_type_spec,
ds_attribute,
ds_std_attribute,
ds_storage_class,
ds_long_long,
ds_last /* This enumerator must always be the last one. */
@ -4702,6 +4705,8 @@ typedef struct cp_decl_specifier_seq {
tree type;
/* The attributes, if any, provided with the specifier sequence. */
tree attributes;
/* The c++11 attributes that follows the type specifier. */
tree std_attributes;
/* If non-NULL, a built-in type that the user attempted to redefine
to some other type. */
tree redefined_builtin_type;
@ -4770,8 +4775,14 @@ struct cp_declarator {
to indicate this is a parameter pack. */
BOOL_BITFIELD parameter_pack_p : 1;
location_t id_loc; /* Currently only set for cdk_id and cdk_function. */
/* Attributes that apply to this declarator. */
/* GNU Attributes that apply to this declarator. If the declarator
is a pointer or a reference, these attribute apply to the type
pointed to. */
tree attributes;
/* Standard C++11 attributes that apply to this declarator. If the
declarator is a pointer or a reference, these attributes apply
to the pointer, rather than to the type pointed to. */
tree std_attributes;
/* For all but cdk_id and cdk_error, the contained declarator. For
cdk_id and cdk_error, guaranteed to be NULL. */
cp_declarator *declarator;
@ -5068,7 +5079,9 @@ extern tree build_cp_library_fn_ptr (const char *, tree);
extern tree push_library_fn (tree, tree, tree);
extern tree push_void_library_fn (tree, tree);
extern tree push_throw_library_fn (tree, tree);
extern tree check_tag_decl (cp_decl_specifier_seq *);
extern void warn_misplaced_attr_for_class_type (source_location location,
tree class_type);
extern tree check_tag_decl (cp_decl_specifier_seq *, bool);
extern tree shadow_tag (cp_decl_specifier_seq *);
extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *, bool);
extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
@ -5829,6 +5842,7 @@ extern int comp_cv_qualification (const_tree, const_tree);
extern int comp_cv_qual_signature (tree, tree);
extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code, bool);
extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool);
extern tree cxx_alignas_expr (tree);
extern tree cxx_sizeof_nowarn (tree);
extern tree is_bitfield_expr_with_lowered_type (const_tree);
extern tree unlowered_expr_type (const_tree);

View File

@ -4132,13 +4132,32 @@ fixup_anonymous_aggr (tree t)
}
}
/* Warn for an attribute located at LOCATION that appertains to the
class type CLASS_TYPE that has not been properly placed after its
class-key, in it class-specifier. */
void
warn_misplaced_attr_for_class_type (source_location location,
tree class_type)
{
gcc_assert (TAGGED_TYPE_P (class_type));
warning_at (location, OPT_Wattributes,
"attribute ignored in declaration "
"of %q#T", class_type);
inform (location,
"attribute for %q#T must follow the %qs keyword",
class_type, class_key_or_enum_as_string (class_type));
}
/* Make sure that a declaration with no declarator is well-formed, i.e.
just declares a tagged type or anonymous union.
Returns the type declared; or NULL_TREE if none. */
tree
check_tag_decl (cp_decl_specifier_seq *declspecs)
check_tag_decl (cp_decl_specifier_seq *declspecs,
bool explicit_type_instantiation_p)
{
int saw_friend = decl_spec_seq_has_spec_p (declspecs, ds_friend);
int saw_typedef = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
@ -4247,10 +4266,22 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
/* For a template class (an explicit instantiation), use the
current location. */
loc = input_location;
warning_at (loc, OPT_Wattributes, "attribute ignored in declaration "
"of %q#T", declared_type);
inform (loc, "attribute for %q#T must follow the %qs keyword",
declared_type, class_key_or_enum_as_string (declared_type));
if (explicit_type_instantiation_p)
/* [dcl.attr.grammar]/4:
No attribute-specifier-seq shall appertain to an explicit
instantiation. */
{
warning_at (loc, OPT_Wattributes,
"attribute ignored in explicit instantiation %q#T",
declared_type);
inform (loc,
"no attribute can be applied to "
"an explicit instantiation");
}
else
warn_misplaced_attr_for_class_type (loc, declared_type);
}
return declared_type;
@ -4272,7 +4303,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
tree
shadow_tag (cp_decl_specifier_seq *declspecs)
{
tree t = check_tag_decl (declspecs);
tree t = check_tag_decl (declspecs,
/*explicit_type_instantiation_p=*/false);
if (!t)
return NULL_TREE;
@ -9178,6 +9210,15 @@ grokdeclarator (const cp_declarator *declarator,
}
}
if (declspecs->std_attributes)
{
/* Apply the c++11 attributes to the type preceding them. */
source_location saved_loc = input_location;
input_location = declspecs->locations[ds_std_attribute];
decl_attributes (&type, declspecs->std_attributes, 0);
input_location = saved_loc;
}
/* Determine the type of the entity declared by recurring on the
declarator. */
for (; declarator; declarator = declarator->declarator)
@ -9215,6 +9256,13 @@ grokdeclarator (const cp_declarator *declarator,
case cdk_array:
type = create_array_type_for_decl (dname, type,
declarator->u.array.bounds);
if (declarator->std_attributes)
/* [dcl.array]/1:
The optional attribute-specifier-seq appertains to the
array. */
returned_attrs = chainon (returned_attrs,
declarator->std_attributes);
break;
case cdk_function:
@ -9411,6 +9459,13 @@ grokdeclarator (const cp_declarator *declarator,
}
type = build_function_type (type, arg_types);
if (declarator->std_attributes)
/* [dcl.fct]/2:
The optional attribute-specifier-seq appertains to
the function type. */
decl_attributes (&type, declarator->std_attributes,
0);
}
break;
@ -9573,6 +9628,17 @@ grokdeclarator (const cp_declarator *declarator,
declarator->u.pointer.qualifiers);
type_quals = cp_type_quals (type);
}
/* Apply C++11 attributes to the pointer, and not to the
type pointed to. This is unlike what is done for GNU
attributes above. It is to comply with [dcl.ptr]/1:
[the optional attribute-specifier-seq (7.6.1) appertains
to the pointer and not to the object pointed to]. */
if (declarator->std_attributes)
decl_attributes (&type, declarator->std_attributes,
0);
ctype = NULL_TREE;
break;
@ -9698,6 +9764,13 @@ grokdeclarator (const cp_declarator *declarator,
attrlist = &returned_attrs;
}
if (declarator
&& declarator->kind == cdk_id
&& declarator->std_attributes)
/* [dcl.meaning]/1: The optional attribute-specifier-seq following
a declarator-id appertains to the entity that is declared. */
*attrlist = chainon (*attrlist, declarator->std_attributes);
/* Handle parameter packs. */
if (parameter_pack_p)
{

View File

@ -1091,7 +1091,7 @@ grokbitfield (const cp_declarator *declarator,
static bool
is_late_template_attribute (tree attr, tree decl)
{
tree name = TREE_PURPOSE (attr);
tree name = get_attribute_name (attr);
tree args = TREE_VALUE (attr);
const struct attribute_spec *spec = lookup_attribute_spec (name);
tree arg;

View File

@ -3374,6 +3374,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
"delegating constructors "
"only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_ATTRIBUTES:
pedwarn (input_location, 0,
"c++11 attributes "
"only available with -std=c++11 or -std=gnu++11");
break;
default:
gcc_unreachable ();
}

File diff suppressed because it is too large Load Diff

View File

@ -1701,6 +1701,56 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain)
else
return cxx_alignof_expr (e, complain? tf_warning_or_error : tf_none);
}
/* Build a representation of an expression 'alignas(E).' Return the
folded integer value of E if it is an integral constant expression
that resolves to a valid alignment. If E depends on a template
parameter, return a syntactic representation tree of kind
ALIGNOF_EXPR. Otherwise, return an error_mark_node if the
expression is ill formed, or NULL_TREE if E is NULL_TREE. */
tree
cxx_alignas_expr (tree e)
{
if (e == NULL_TREE || e == error_mark_node
|| (!TYPE_P (e) && !require_potential_rvalue_constant_expression (e)))
return e;
if (TYPE_P (e))
/* [dcl.align]/3:
When the alignment-specifier is of the form
alignas(type-id ), it shall have the same effect as
alignas( alignof(type-id )). */
return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, false);
/* If we reach this point, it means the alignas expression if of
the form "alignas(assignment-expression)", so we should follow
what is stated by [dcl.align]/2. */
e = mark_rvalue_use (e);
/* [dcl.align]/2 says:
the assignment-expression shall be an integral constant
expression. */
e = fold_non_dependent_expr (e);
if (value_dependent_expression_p (e))
/* Leave value-dependent expression alone for now. */;
else
e = cxx_constant_value (e);
if (e == NULL_TREE
|| e == error_mark_node
|| TREE_CODE (e) != INTEGER_CST)
return error_mark_node;
return e;
}
/* EXPR is being used in a context that is not a function call.
Enforce:

View File

@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "gcc-plugin.h"
struct attribute_spec;
struct scoped_attributes;
extern void add_new_plugin (const char *);
extern void parse_plugin_arg_opt (const char *);
@ -64,5 +65,7 @@ invoke_plugin_callbacks (int event ATTRIBUTE_UNUSED,
/* In attribs.c. */
extern void register_attribute (const struct attribute_spec *attr);
extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
const char *);
#endif /* PLUGIN_H */

View File

@ -1,3 +1,64 @@
2012-10-08 Dodji Seketeli <dodji@redhat.com>
PR c++/53528 C++11 attribute support
* g++.dg/cpp0x/gen-attrs-1.C: New test.
* g++.dg/cpp0x/gen-attrs-2.C: Likewise.
* g++.dg/cpp0x/gen-attrs-2-1.C: Likewise.
* g++.dg/cpp0x/gen-attrs-3.C: Likewise.
* g++.dg/cpp0x/gen-attrs-4.C: Likewise.
* g++.dg/cpp0x/gen-attrs-5.C: Likewise.
* g++.dg/cpp0x/gen-attrs-6.C: Likewise.
* g++.dg/cpp0x/gen-attrs-7.C: Likewise.
* g++.dg/cpp0x/gen-attrs-8.C: Likewise.
* g++.dg/cpp0x/gen-attrs-9.C: Likewise.
* g++.dg/cpp0x/gen-attrs-10.C: Likewise.
* g++.dg/cpp0x/gen-attrs-11.C: Likewise.
* g++.dg/cpp0x/gen-attrs-12.C: Likewise.
* g++.dg/cpp0x/gen-attrs-13.C: Likewise.
* g++.dg/cpp0x/gen-attrs-14.C: Likewise.
* g++.dg/cpp0x/gen-attrs-15.C: Likewise.
* g++.dg/cpp0x/gen-attrs-16.C: Likewise.
* g++.dg/cpp0x/gen-attrs-17.C: Likewise.
* g++.dg/cpp0x/gen-attrs-18.C: Likewise.
* g++.dg/cpp0x/gen-attrs-19.C: Likewise.
* g++.dg/cpp0x/gen-attrs-20.C: Likewise.
* g++.dg/cpp0x/gen-attrs-21.C: Likewise.
* g++.dg/cpp0x/gen-attrs-22.C: Likewise.
* g++.dg/cpp0x/gen-attrs-23.C: Likewise.
* g++.dg/cpp0x/gen-attrs-24.C: Likewise.
* g++.dg/cpp0x/gen-attrs-25.C: Likewise.
* g++.dg/cpp0x/gen-attrs-26.C: Likewise.
* g++.dg/cpp0x/gen-attrs-27.C: Likewise.
* g++.dg/cpp0x/gen-attrs-28.C: Likewise.
* g++.dg/cpp0x/gen-attrs-29.C: Likewise.
* g++.dg/cpp0x/gen-attrs-30.C: Likewise.
* g++.dg/cpp0x/gen-attrs-31.C: Likewise.
* g++.dg/cpp0x/gen-attrs-32.C: Likewise.
* g++.dg/cpp0x/gen-attrs-33.C: Likewise.
* g++.dg/cpp0x/gen-attrs-34.C: Likewise.
* g++.dg/cpp0x/gen-attrs-35.C: Likewise.
* g++.dg/cpp0x/gen-attrs-36.C: Likewise.
* g++.dg/cpp0x/gen-attrs-36-1.C: Likewise.
* g++.dg/cpp0x/gen-attrs-37.C: Likewise.
* g++.dg/cpp0x/gen-attrs-38.C: Likewise.
* g++.dg/cpp0x/gen-attrs-39.C: Likewise.
* g++.dg/cpp0x/gen-attrs-39-1.C: Likewise.
* g++.dg/cpp0x/gen-attrs-40.C: Likewise.
* g++.dg/cpp0x/gen-attrs-41.C: Likewise.
* g++.dg/cpp0x/gen-attrs-42.C: Likewise.
* g++.dg/cpp0x/gen-attrs-43.C: Likewise.
* g++.dg/cpp0x/gen-attrs-44.C: Likewise.
* g++.dg/cpp0x/gen-attrs-45.C: Likewise.
* g++.dg/cpp0x/gen-attrs-46.C: Likewise.
* g++.dg/cpp0x/gen-attrs-47.C: Likewise.
* g++.dg/cpp0x/gen-attrs-47-1.C: Likewise.
* g++.dg/cpp0x/gen-attrs-48.C: Likewise.
* g++.dg/cpp0x/gen-attrs-49.C: Likewise.
* g++.dg/cpp0x/gen-attrs-50.C: Likewise.
* g++.dg/cpp0x/gen-attrs-51.C: Likewise.
* g++.dg/cpp0x/gen-attrs-52.C: Likewise.
* g++.dg/cpp0x/gen-attrs-53.C: Likewise.
2012-10-08 Eric Botcazou <ebotcazou@adacore.com>
* gcc.dg/tree-ssa/slsr-30.c: Use correct cleanup directive.

View File

@ -0,0 +1,3 @@
// { dg-do compile { target c++11 } }
int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "ignored" }

View File

@ -0,0 +1,9 @@
// PR c++/12795
// { dg-do compile { target c++11 } }
// { dg-require-alias "" }
void foo()
{
extern void bar [[gnu::__alias__ ("BAR")]] (); // { dg-warning "ignored" }
bar ();
}

View File

@ -0,0 +1,17 @@
// { dg-do compile { target c++11 } }
// PR c++/13791
template <typename T> struct O {
struct [[gnu::packed]] I {
int i;
char c;
};
I* foo();
};
template <typename T>
typename O<T>::I*
O<T>::foo() { return 0; }
template class O<int>;

View File

@ -0,0 +1,17 @@
// { dg-do compile { target c++11 } }
// PR c++/13791
template <typename T> struct O {
struct [[gnu::packed]] I {
int i;
char c;
};
I* foo();
};
template <typename T>
typename O<T>::I*
O<T>::foo() { return 0; }
template class O<int>;

View File

@ -0,0 +1,5 @@
// { dg-do compile { target c++11 } }
// PR c++/13854
extern char *rindex [[gnu::__pure__]] (__const char *__s, int __c) throw ();
extern char *rindex [[gnu::__pure__]] (__const char *__s, int __c) throw ();

View File

@ -0,0 +1,14 @@
// { dg-do compile { target c++11 } }
// PR c++/13170
// The bogus attribute is ignored, but was in TYPE_ATTRIBUTES during
// parsing of the class, causing some variants to have it and some not.
struct [[gnu::bogus]] A // { dg-warning "ignored" "" }
{
virtual ~A();
void foo(const A&);
void bar(const A&);
};
void A::foo(const A&) {}
void A::bar(const A& a) { foo(a); }

View File

@ -0,0 +1,9 @@
// { dg-do compile { target c++11 } }
// PR c++/15317
struct A
{
A(char);
};
A::A([[gnu::unused]] char i2)
{}

View File

@ -0,0 +1,8 @@
// { dg-do compile { target c++11 } }
// Origin: <rguenth at tat dot physik dot uni-tuebingen dot de>
// PR c++/10479: use of non dependent expressions in attributes in templates
template <int i>
struct foo2 {
float bar [[gnu::aligned(alignof(double))]];
};

View File

@ -0,0 +1,19 @@
// { dg-do compile { target c++11 } }
// Origin: Benjamin Kosnik <bkoz at gcc dot gnu dot org>
// PR c++/17743: Attributes applied to typedefs.
struct A {
typedef char layout_type[sizeof(double)]
[[gnu::aligned(alignof(double)]]); // { dg-error "expected" }
layout_type data;
};
struct B {
typedef char layout_type[sizeof(double)];
layout_type data [[gnu::aligned(alignof(double))]];
};
template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};
StaticAssert<alignof(A) == alignof(B)> a1;// { dg-error "incomplete type and cannot be defined" }

View File

@ -0,0 +1,19 @@
// { dg-do compile { target c++11 } }
// Origin: Benjamin Kosnik <bkoz at gcc dot gnu dot org>
// PR c++/17743: Attributes applied to typedefs.
struct A {
typedef char layout_type[sizeof(double)]
[[gnu::aligned(alignof(double))]];
layout_type data;
};
struct B {
typedef char layout_type[sizeof(double)];
layout_type data [[gnu::aligned(alignof(double))]];
};
template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};
StaticAssert<alignof(A) == alignof(B)> a1;

View File

@ -0,0 +1,10 @@
// PR c++/17542
// Test that we warn when an attribute preceding the class-key is ignored.
// { dg-do compile { target c++11 } }
[[gnu::packed]] struct A // { dg-warning "attribute" }
{
char c;
int x;
void f();
};

View File

@ -0,0 +1,11 @@
// PR c++/19739
// { dg-do compile { target c++11 } }
void Dummy() [[ , ]];
void Dummy() {}
int main (int argc, char **argv)
{
Dummy();
return 0;
}

View File

@ -0,0 +1,3 @@
// { dg-do compile { target c++11 } }
struct [[gnu::unused]] A {};

View File

@ -0,0 +1,11 @@
// { dg-do compile { target c++11 } }
struct [[gnu::packed]] A
{
void f () const;
};
void
A::f () const
{
}

View File

@ -0,0 +1,22 @@
// { dg-do compile { target c++11 } }
// { dg-options "-g" }
// Origin: <jan at etpmod dot phys dot tue dot nl>
// PR c++/19508: avoid attributes for template parameters
template <typename T>
struct BVector
{
typedef T T2;
typedef T value_type [[gnu::aligned(8)]]; // { dg-bogus "attribute" "attribute" }
typedef T2 value_type2 [[gnu::aligned(8)]]; // { dg-bogus "attribute" "attribute" }
value_type v;
};
BVector<int> m;
template <template <class> class T>
struct BV2
{
typedef T<float> value_type [[gnu::aligned(8)]]; // { dg-bogus "attribute" "attribute" }
value_type v;
};
BV2<BVector> m2;

View File

@ -0,0 +1,21 @@
// PR c++/20763
// { dg-do compile { target c++11 } }
typedef void *voidp;
struct S
{
char a;
voidp b [[gnu::aligned (16)]];
};
struct T
{
char a;
void * b [[gnu::aligned (16)]];
};
static_assert (sizeof (S) == sizeof (T),
"struct S and T should have the same size");
static_assert (sizeof (S) == 32, "sizeof (S) == 8 + 16 + 8");

View File

@ -0,0 +1,7 @@
// PR c++/27648
// { dg-do compile { target c++11 } }
void f()
{
static_cast<float *[[gnu::unused]]>(0); // { dg-warning "ignored" }
}

View File

@ -0,0 +1,11 @@
// PR c++/28112
// { dg-do compile { target c++11 } }
int i [[gnu::init_priority(;)]]; // { dg-error "before" }
int j [[gnu::vector_size(;)]]; // { dg-error "before" }
int k [[gnu::visibility(;)]]; // { dg-error "before" }
struct A {} [[gnu::aligned(;)]]; // { dg-error "before" }
struct B {} [[gnu::mode(;)]]; // { dg-error "before" }
void foo() [[gnu::alias(;)]]; // { dg-error "before" }
void bar() [[gnu::nonnull(;)]]; // { dg-error "before" }
void baz() [[gnu::section(;)]]; // { dg-error "before" }

View File

@ -0,0 +1,4 @@
// PR c++/28387
// { dg-do compile { target c++11 } }
enum [[gnu::unused]] E; // { dg-error "without previous declaration" }

View File

@ -0,0 +1,12 @@
// PR c++/28559
// { dg-do compile { target c++11 } }
template<typename T> struct A
{
struct B;
};
struct C
{
template<typename T> friend struct [[gnu::packed]] A<T>::B; // { dg-warning "uninstantiated" }
};

View File

@ -0,0 +1,15 @@
// PR c++/28659
// The attribute was causing us to get confused in merge_types when
// combining the template type with an uninstantiated version.
// { dg-do compile { target c++11 } }
template<class T>
struct [[gnu::aligned(1)]] A
{
A& operator=(const A &t);
};
template<class T>
A<T>& A<T>::operator=(const A<T> &t)
{
}

View File

@ -0,0 +1,6 @@
//PR c++/29980
// { dg-do compile { target c++11 } }
struct A { typedef int X; }; // { dg-message "previous declaration" }
struct [[gnu::unused]] A::X; // { dg-error "typedef-name" }

View File

@ -0,0 +1,13 @@
// PR c++/28558
// { dg-options "" }
// { dg-do compile { target c++11 } }
struct A
{
A(int) { }
};
int main()
{
A a = (A [[gnu::unused]])0; // { dg-warning "attribute" }
}

View File

@ -0,0 +1,10 @@
// PR c++/33506
// { dg-do compile { target c++11 } }
extern int f1 [[gnu::warn_unused_result]] (char *) ;
extern int f2 [[gnu::warn_unused_result]] (char *) throw () ;
extern int f2 (char *) throw ();
extern int f3 [[gnu::nonnull (1)]] (char *) ;
extern int f4 [[gnu::nonnull (1)]] (char *) throw ();
extern int f4 (char *) throw ();

View File

@ -0,0 +1,22 @@
// Test that attributes work in a variety of situations.
// { dg-options "-O -ftrack-macro-expansion=0" }
// { dg-do run { target c++11 } }
#define attrib [[gnu::mode (QI)]]
#define gnu_attrib __attribute((mode (QI)))
attrib signed int a;
static unsigned int b attrib;
int foo(attrib int o)
{
return (sizeof (a) != 1
|| sizeof (b) != 1
|| sizeof (o) != 1
|| sizeof ((gnu_attrib signed int) b) != 1);
}
int main ()
{
return foo (42);
}

View File

@ -0,0 +1,9 @@
// { dg-do compile { target c++11 } }
// PR c++/35074
template<typename T> struct A
{
void foo() const;
} [[gnu::aligned(4)]]; // { dg-warning "ignored" }
template<typename T> void A<T>::foo() const {}

View File

@ -0,0 +1,16 @@
// PR c++/35097
// { dg-do compile { target c++11 } }
template<int> struct A;
template<> struct A<0>
{
typedef int X [[gnu::aligned(4)]];
};
template<typename T> void foo(const A<0>::X&, T);
void bar()
{
foo(A<0>::X(), 0);
}

View File

@ -0,0 +1,37 @@
// PR c++/35315
// { dg-do compile { target c++11 } }
typedef union { int i; } U [[gnu::transparent_union]]; // { dg-warning "ignored" }
static void foo(U) {}
static void foo(int) {}
void bar()
{
foo(0);
}
typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" }
static void foo2(U1) {} // { dg-error "previously defined" }
static void foo2(U2) {} // { dg-error "redefinition" }
void bar2(U1 u1, U2 u2)
{
foo2(u1);
foo2(u2);
}
// PR c++/36410
struct A
{
typedef union [[gnu::transparent_union]]
{
int i;
} B;
};
void foo(A::B b)
{
b.i;
}

View File

@ -0,0 +1,19 @@
// PR c++/35546
// { dg-do compile { target c++11 } }
// { dg-options "-g" }
template <int N>
struct T
{
void foo [[gnu::format (printf,2,3)]] (char const * ...);
};
template struct T<3>;
template <typename T>
struct U
{
typedef T V [[gnu::mode (SI)]];
};
U<int>::V v;

View File

@ -0,0 +1,19 @@
// PR c/37171
// { dg-do compile { target c++11 } }
// { dg-options "-O2 -fdump-tree-optimized" }
unsigned int f1 [[gnu::const]] ();
unsigned int f2 [[gnu::__const]] () ;
unsigned int f3 [[gnu::__const__]] () ;
unsigned int f4 ()
{
return f1 () + f1 () + f1 () + f1 ()
+ f2 () + f2 () + f2 () + f2 ()
+ f3 () + f3 () + f3 () + f3 ();
}
// { dg-final { scan-tree-dump-times "= f1 \\(\\)" 1 "optimized" } }
// { dg-final { scan-tree-dump-times "= f2 \\(\\)" 1 "optimized" } }
// { dg-final { scan-tree-dump-times "= f3 \\(\\)" 1 "optimized" } }
// { dg-final { cleanup-tree-dump "optimized" } }

View File

@ -0,0 +1,20 @@
// { dg-do compile { target i?86-*-* x86_64-*-* } }
// { dg-options "-O3 -msse2 -std=c++11" }
// { dg-require-effective-target sse2 }
// You can make NON-template typedefs with a large alignment.
typedef double AlignedDoubleType [[gnu::aligned(16)]];
template <typename RealType>
RealType f(const RealType* p)
{
// But if you use a template parameter it complains.
typedef RealType AlignedRealType [[gnu::aligned(16)]];
return p[0];
}
double f2(const double* p)
{
return f<double>(p);
}

View File

@ -0,0 +1,11 @@
// { dg-do compile { target c++11 } }
struct S;
typedef int (*F [[gnu::warn_unused_result]]) (int);
typedef int (*F2 [[gnu::warn_unused_result]]) (int);
typedef int (S::*F3 [[gnu::warn_unused_result]]) (int); // { dg-warning "only applies to function types" }
typedef int [[gnu::warn_unused_result]] (*F5) (int); // { dg-warning "ignored" }

View File

@ -0,0 +1,23 @@
// PR c++/43031
// { dg-options "-std=c++11 -pedantic" }
// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } }
class T;
class L { };
class P : public L
{
typedef void (T::* [[gnu::__stdcall__]] F2) (L*); // { dg-warning "only applies to function types" }
typedef void (T::*F) (L*) [[gnu::__stdcall__]];
void f(bool aAdd);
};
class T
{
public:
virtual void A(L *listener) [[gnu::__stdcall__]] = 0;
virtual void R(L *listener) [[gnu::__stdcall__]] = 0;
};
void P::f(bool aAdd)
{
F addRemoveEventListener = (aAdd ? &T::A : &T::R);
}

View File

@ -0,0 +1,15 @@
// PR c++/43093
// { dg-options "-std=c++11 -pedantic" }
// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } }
struct S {
int x;
S(const S &s) {}
};
S getS() [[gnu::__stdcall__]];
void test()
{
S s = getS();
}

View File

@ -0,0 +1,12 @@
// { dg-do compile { target c++11 } }
// PR c++/36625
template <int N>
struct A {
struct S { short f[3]; } [[gnu::aligned (N)]]; // { dg-warning "ignored" }
};
int main ()
{
A<4>::S s;
}

View File

@ -0,0 +1,10 @@
// { dg-do compile { target c++11 } }
int fragile_block(void) {
typedef
[[gnu::aligned (16)]] // { dg-warning "ignored" }
struct {
int i;
} XmmUint16;
return 0;
}

View File

@ -0,0 +1,10 @@
// PR debug/43370
// { dg-do compile { target c++11 } }
// { dg-options "-g" }
int fragile_block(void) {
typedef struct [[gnu::aligned (16)]] {
int i;
} XmmUint16;
return 0;
}

View File

@ -0,0 +1,30 @@
// { dg-options "-std=c++11 -Wunused -pedantic-errors" }
// { dg-do compile }
// Test for syntax support of various attribute permutations.
int
[[gnu::noreturn]] // { dg-warning "ignored" }
one
[[gnu::unused]]
(void);
int one_third [[gnu::noreturn]] [[gnu::unused]] (void);
int [[gnu::unused]] one_half(); // { dg-warning "ignored" }
static
[[gnu::noreturn]] // { dg-warning "ignored" }
void two [[gnu::unused]] (void) {}
[[gnu::unused]]
int
five(void)
[[gnu::noreturn]] // { dg-warning "ignored" }
{}
[[gnu::noreturn]]
void
six (void)
;

View File

@ -0,0 +1,5 @@
// PR c++/46803
// { dg-do compile { target c++11 } }
int strftime(char *, int, const char *, const struct tm *)
[[gnu::__bounded__(__string__,1,2)]]; // { dg-warning "ignored" }

View File

@ -0,0 +1,20 @@
// PR c++/45267
// { dg-do compile { target c++11 } }
// { dg-options "-O" }
template<typename T> struct Vector {
Vector(long long x);
inline Vector<T> operator<< [[gnu::always_inline]] (int x) const;
};
long long bar (long long);
template<> inline Vector<int> Vector<int>::operator<<(int x) const {
return bar(x);
}
bool b;
int main() {
Vector<int> a(1);
if ((a << 2), b) {
a << 2;
throw 1;
}
}

View File

@ -0,0 +1,13 @@
// { dg-options "-std=c++11 -pedantic" }
// { dg-do compile { target { i?86-*-* && ilp32 } } }
struct A {
[[gnu::fastcall]]
void f();
};
int main()
{
typedef void (A::*FP)();
FP fp[] = {&A::f}; // { dg-error "cannot convert" }
}

View File

@ -0,0 +1,4 @@
// { dg-do compile { target c++11 } }
template <class T> struct A { };
template [[gnu::packed]] struct A<int>; // { dg-warning "ignored in explicit instantiation" }

View File

@ -0,0 +1,3 @@
// PR c++/52671
// { dg-do compile { target c++11 } }
[[gnu::deprecated]] enum E { E0 }; // { dg-warning "ignored in declaration" }

View File

@ -0,0 +1,4 @@
// PR c++/52906
// { dg-do compile { target c++11 } }
[[gnu::deprecated]]; // { dg-error "does not declare anything" }

View File

@ -0,0 +1,5 @@
// PR c++/40821
// { dg-do compile { target c++11 } }
struct [[gnu::aligned(8)] S1 { int i; }; // { dg-error "" }
struct [aligned(8) S2 { int i; }; // { dg-error "" }

View File

@ -0,0 +1,8 @@
// { dg-do compile { target c++11 } }
int
foo ()
{
int i [[and, bitor, xor_eq, compl, bitand]]; // { dg-warning "ignored" }
i = 0;
return i;
}

View File

@ -0,0 +1,13 @@
// { dg-do compile { target c++11 } }
// Example taken from dcl.attr.grammar:
int p[10];
void f()
{
int x = 42, y[5];
/* Here, the '[[' should have introduced an attribute, on a
lambda invocation an array subscripting expression. */
int(p[[x] { return x; }()]); // { dg-error "expected|consecutive" }
/* Likewise, the '[[gnu::' is invalid here. */
y[[] { return 2; }()] = 2; // { dg-error "expected|consecutive" }
}

View File

@ -0,0 +1,17 @@
// { dg-do compile { target c++11 } }
typedef char layout_type;
struct A {
layout_type member alignas (double);
};
static_assert (alignof (A) == alignof (double),
"alignment of struct A must be alignof (double)");
struct alignas (alignof (long double)) B {
layout_type member;
};
static_assert (alignof (B) == alignof (long double),
"alignment of struct A must be alignof (double double)");

View File

@ -0,0 +1,17 @@
// { dg-do compile { target c++11 } }
typedef char layout_type;
template<class> struct A {
layout_type member alignas (double);
};
static_assert (alignof (A<int>) == alignof (double),
"alignment of struct A must be alignof (double)");
template<class> struct alignas (alignof (long double)) B {
layout_type member;
};
static_assert (alignof (B<int>) == alignof (long double),
"alignment of struct A must be alignof (double double)");

View File

@ -0,0 +1,23 @@
// { dg-do compile { target c++11 } }
//
// There were two related problems here, depending on the vintage. At
// one time:
//
// typedef struct A { ... } A [[gnu::aligned (16)]];
//
// would cause original_types to go into an infinite loop. At other
// times, the attributes applied to an explicit typedef would be lost
// (check_b3 would have a negative size).
// First check that the declaration is accepted and has an effect.
typedef struct A { int i; } A [[gnu::aligned (16)]];
int check_A[alignof (A) >= 16 ? 1 : -1];
// Check that the alignment is only applied to the typedef.
struct B { int i; };
struct B b1;
typedef struct B B [[gnu::aligned (16)]];
struct B b2;
B b3;
int check_b1[__alignof__ (b1) == __alignof__ (b2) ? 1 : -1];
int check_b3[__alignof__ (b3) >= 16 ? 1 : -1];

View File

@ -0,0 +1,22 @@
// { dg-do compile { target c++11 } }
typedef char layout_type;
template<class> struct A {
layout_type member alignas (double) alignas (int);
};
// Here, the spec says that A<int> should have the stricter alignment,
// so that would be the alignment of 'double', not 'int'.
static_assert (alignof (A<int>) == alignof (double),
"alignment of struct A must be alignof (double)");
template<class> struct alignas (1) alignas (alignof (long double)) B {
layout_type member;
};
// Similarly, the B<int> should have the stricter alignment, so that would
// so that would be the alignment of 'long double', not '1'.
static_assert (alignof (B<int>) == alignof (long double),
"alignment of struct A must be alignof (double double)");

View File

@ -0,0 +1,9 @@
// { dg-do compile { target c++11 } }
typedef char layout_type;
struct A
{
layout_type member [[gnu::aligned (16)]];
};
static_assert (sizeof (A) == 16, "Alignment should be 16");

View File

@ -0,0 +1,21 @@
// { dg-do compile { target c++11 } }
struct A {int i;} a [[gnu::aligned(16)]];
struct B {int i;} __attribute__((aligned(16))) b;
int
main ()
{
A aa;
B bb;
static_assert (sizeof (a) == 4, "sizeof (a) should be 4");
static_assert (sizeof (b) == 16, "sizeof (b) should be 16");
static_assert (sizeof (aa) == 4, "sizeof (aa) should be 4");
static_assert (sizeof (bb) == 16, "sizeof (bb) should be 16");
static_assert (__alignof__ (a) == 16, "alignof (a) should be 16");
static_assert (__alignof__ (b) == 16, "alignof (b) should be 16");
static_assert (__alignof__ (aa) == 4, "alignof (aa) should be 4");
static_assert (__alignof__ (bb) == 16, "alignof (bb) should be 16");
}

View File

@ -0,0 +1,39 @@
// { dg-do compile { target c++11 } }
int
toto ()
{
[[gnu::unused]] good:
return 0;
}
int
foo ()
{
[[gnu::unused]] good:
int i = 0;
// A C++11 attribute at the beginning of the return statement is
// syntactically correct, appertains to the return statement (not to
// the label) but is currently ignored by this implementation.
good_ignored : [[gnu::unused]] // { dg-warning "attributes at the beginning of statement are ignored" }
return i;
}
int
bar ()
{
// A GNU attribute after the label appertains to the label.
good: __attribute__((unused));
return 0;
}
int
baz ()
{
// The c++ attribute after the label appertains to the (empty)
// statement.
bad: [[gnu::unused]]; // { dg-warning "attributes at the beginning of statement are ignored" }
return 0;
}

View File

@ -0,0 +1,20 @@
// Copyright (C) 2002 Free Software Foundation.
//
// Test that the nothrow attribute is working correctly.
//
// Written by Richard Henderson, 26 May 2002.
// { dg-do link { target c++11} }
extern void foo [[gnu::nothrow]] ();
extern void link_error();
int main()
{
try {
foo();
} catch (...) {
link_error();
}
}
void foo() { }

View File

@ -0,0 +1,4 @@
// { dg-do compile { target c++11 } }
// { dg-options "-Wunused-parameter" }
void f (int i [[gnu::__unused__]]) {}

View File

@ -0,0 +1,6 @@
// { dg-options "-std=c++11 -pedantic" }
// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } }
extern int * ([[gnu::stdcall]] *fooPtr)( void); // { dg-error "expected" }
int * [[gnu::stdcall]] myFn01( void) { return 0; }// { dg-warning "attribute only applies to function types" }

View File

@ -0,0 +1,12 @@
// { dg-do compile { target c++11 } }
class C;
struct S;
union U;
enum e {};
enum [[gnu::unused]] e; // { dg-warning "already defined" }
struct [[gnu::unused]] B *p; // { dg-warning "attributes" }
template <class T> struct A { };
struct [[gnu::unused]] A<int>; // { dg-warning "attributes" }

View File

@ -4350,7 +4350,7 @@ comp_type_attributes (const_tree type1, const_tree type2)
const struct attribute_spec *as;
const_tree attr;
as = lookup_attribute_spec (TREE_PURPOSE (a));
as = lookup_attribute_spec (get_attribute_name (a));
if (!as || as->affects_type_identity == false)
continue;
@ -4364,7 +4364,7 @@ comp_type_attributes (const_tree type1, const_tree type2)
{
const struct attribute_spec *as;
as = lookup_attribute_spec (TREE_PURPOSE (a));
as = lookup_attribute_spec (get_attribute_name (a));
if (!as || as->affects_type_identity == false)
continue;
@ -5287,11 +5287,12 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
{
while (list)
{
size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list));
size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
if (ident_len == attr_len)
{
if (strcmp (attr_name, IDENTIFIER_POINTER (TREE_PURPOSE (list))) == 0)
if (!strcmp (attr_name,
IDENTIFIER_POINTER (get_attribute_name (list))))
break;
}
/* TODO: If we made sure that attributes were stored in the
@ -5299,7 +5300,7 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
to '__text__') then we could avoid the following case. */
else if (ident_len == attr_len + 4)
{
const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
if (p[0] == '_' && p[1] == '_'
&& p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
&& strncmp (attr_name, p + 2, attr_len) == 0)
@ -5329,10 +5330,11 @@ lookup_ident_attribute (tree attr_identifier, tree list)
while (list)
{
gcc_checking_assert (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE);
gcc_checking_assert (TREE_CODE (get_attribute_name (list))
== IDENTIFIER_NODE);
/* Identifiers can be compared directly for equality. */
if (attr_identifier == TREE_PURPOSE (list))
if (attr_identifier == get_attribute_name (list))
break;
/* If they are not equal, they may still be one in the form
@ -5342,11 +5344,11 @@ lookup_ident_attribute (tree attr_identifier, tree list)
the fact that we're comparing identifiers. :-) */
{
size_t attr_len = IDENTIFIER_LENGTH (attr_identifier);
size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list));
size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
if (ident_len == attr_len + 4)
{
const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
const char *q = IDENTIFIER_POINTER (attr_identifier);
if (p[0] == '_' && p[1] == '_'
&& p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
@ -5355,7 +5357,7 @@ lookup_ident_attribute (tree attr_identifier, tree list)
}
else if (ident_len + 4 == attr_len)
{
const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
const char *q = IDENTIFIER_POINTER (attr_identifier);
if (q[0] == '_' && q[1] == '_'
&& q[attr_len - 2] == '_' && q[attr_len - 1] == '_'
@ -5385,7 +5387,7 @@ remove_attribute (const char *attr_name, tree list)
tree l = *p;
/* TODO: If we were storing attributes in normalized form, here
we could use a simple strcmp(). */
if (private_is_attribute_p (attr_name, attr_len, TREE_PURPOSE (l)))
if (private_is_attribute_p (attr_name, attr_len, get_attribute_name (l)))
*p = TREE_CHAIN (l);
else
p = &TREE_CHAIN (l);
@ -5422,9 +5424,11 @@ merge_attributes (tree a1, tree a2)
for (; a2 != 0; a2 = TREE_CHAIN (a2))
{
tree a;
for (a = lookup_ident_attribute (TREE_PURPOSE (a2), attributes);
for (a = lookup_ident_attribute (get_attribute_name (a2),
attributes);
a != NULL_TREE && !attribute_value_equal (a, a2);
a = lookup_ident_attribute (TREE_PURPOSE (a2), TREE_CHAIN (a)))
a = lookup_ident_attribute (get_attribute_name (a2),
TREE_CHAIN (a)))
;
if (a == NULL_TREE)
{
@ -6346,7 +6350,7 @@ attribute_hash_list (const_tree list, hashval_t hashcode)
for (tail = list; tail; tail = TREE_CHAIN (tail))
/* ??? Do we want to add in TREE_VALUE too? */
hashcode = iterative_hash_object
(IDENTIFIER_HASH_VALUE (TREE_PURPOSE (tail)), hashcode);
(IDENTIFIER_HASH_VALUE (get_attribute_name (tail)), hashcode);
return hashcode;
}
@ -6383,7 +6387,7 @@ attribute_list_contained (const_tree l1, const_tree l2)
/* Maybe the lists are similar. */
for (t1 = l1, t2 = l2;
t1 != 0 && t2 != 0
&& TREE_PURPOSE (t1) == TREE_PURPOSE (t2)
&& get_attribute_name (t1) == get_attribute_name (t2)
&& TREE_VALUE (t1) == TREE_VALUE (t2);
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
;
@ -6398,9 +6402,9 @@ attribute_list_contained (const_tree l1, const_tree l2)
/* This CONST_CAST is okay because lookup_attribute does not
modify its argument and the return value is assigned to a
const_tree. */
for (attr = lookup_ident_attribute (TREE_PURPOSE (t2), CONST_CAST_TREE(l1));
for (attr = lookup_ident_attribute (get_attribute_name (t2), CONST_CAST_TREE(l1));
attr != NULL_TREE && !attribute_value_equal (t2, attr);
attr = lookup_ident_attribute (TREE_PURPOSE (t2), TREE_CHAIN (attr)))
attr = lookup_ident_attribute (get_attribute_name (t2), TREE_CHAIN (attr)))
;
if (attr == NULL_TREE)

View File

@ -4903,12 +4903,12 @@ struct attribute_spec
{
/* The name of the attribute (without any leading or trailing __),
or NULL to mark the end of a table of attributes. */
const char *const name;
const char *name;
/* The minimum length of the list of arguments of the attribute. */
const int min_length;
int min_length;
/* The maximum length of the list of arguments of the attribute
(-1 for no maximum). */
const int max_length;
int max_length;
/* Whether this attribute requires a DECL. If it does, it will be passed
from types of DECLs, function return types and array element types to
the DECLs, function types and array types respectively; but when
@ -4916,15 +4916,15 @@ struct attribute_spec
a warning. (If greater control is desired for a given attribute,
this should be false, and the flags argument to the handler may be
used to gain greater control in that case.) */
const bool decl_required;
bool decl_required;
/* Whether this attribute requires a type. If it does, it will be passed
from a DECL to the type of that DECL. */
const bool type_required;
bool type_required;
/* Whether this attribute requires a function (or method) type. If it does,
it will be passed from a function pointer type to the target type,
and from a function return type (which is not itself a function
pointer type) to the function type. */
const bool function_type_required;
bool function_type_required;
/* Function to handle this attribute. NODE points to the node to which
the attribute is to be applied. If a DECL, it should be modified in
place; if a TYPE, a copy should be created. NAME is the name of the
@ -4939,10 +4939,10 @@ struct attribute_spec
otherwise the return value should be NULL_TREE. This pointer may be
NULL if no special handling is required beyond the checks implied
by the rest of this structure. */
tree (*const handler) (tree *node, tree name, tree args,
int flags, bool *no_add_attrs);
tree (*handler) (tree *node, tree name, tree args,
int flags, bool *no_add_attrs);
/* Specifies if attribute affects type's identity. */
const bool affects_type_identity;
bool affects_type_identity;
};
/* Flags that may be passed in the third argument of decl_attributes, and
@ -4967,7 +4967,9 @@ enum attribute_flags
/* The attributes are being applied by default to a library function whose
name indicates known behavior, and should be silently ignored if they
are not in fact compatible with the function type. */
ATTR_FLAG_BUILT_IN = 16
ATTR_FLAG_BUILT_IN = 16,
/* A given attribute has been parsed as a C++-11 attribute. */
ATTR_FLAG_CXX11 = 32
};
/* Default versions of target-overridable functions. */
@ -6054,6 +6056,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree);
/* In attribs.c. */
extern const struct attribute_spec *lookup_attribute_spec (const_tree);
extern const struct attribute_spec *lookup_scoped_attribute_spec (const_tree,
const_tree);
extern void init_attributes (void);
@ -6067,6 +6071,12 @@ extern void init_attributes (void);
a decl attribute to the declaration rather than to its type). */
extern tree decl_attributes (tree *, tree, int);
extern bool cxx11_attribute_p (const_tree);
extern tree get_attribute_name (const_tree);
extern tree get_attribute_namespace (const_tree);
extern void apply_tm_attr (tree, tree);
/* In stor-layout.c */