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:
parent
f70308d411
commit
e28d52cffb
74 changed files with 2089 additions and 142 deletions
|
@ -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
|
||||
|
|
239
gcc/attribs.c
239
gcc/attribs.c
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
660
gcc/cp/parser.c
660
gcc/cp/parser.c
File diff suppressed because it is too large
Load diff
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
3
gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
Normal file
3
gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
Normal file
|
@ -0,0 +1,3 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "ignored" }
|
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C
Normal 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 ();
|
||||
}
|
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C
Normal file
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C
Normal 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>;
|
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C
Normal file
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C
Normal 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>;
|
5
gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C
Normal file
5
gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C
Normal 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 ();
|
14
gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C
Normal 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); }
|
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// PR c++/15317
|
||||
|
||||
struct A
|
||||
{
|
||||
A(char);
|
||||
};
|
||||
A::A([[gnu::unused]] char i2)
|
||||
{}
|
8
gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C
Normal file
8
gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C
Normal 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))]];
|
||||
};
|
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C
Normal file
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C
Normal 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" }
|
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C
Normal file
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C
Normal 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;
|
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C
Normal file
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C
Normal 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();
|
||||
};
|
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C
Normal file
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C
Normal 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;
|
||||
}
|
3
gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
Normal file
3
gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
Normal file
|
@ -0,0 +1,3 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct [[gnu::unused]] A {};
|
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C
Normal file
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct [[gnu::packed]] A
|
||||
{
|
||||
void f () const;
|
||||
};
|
||||
|
||||
void
|
||||
A::f () const
|
||||
{
|
||||
}
|
22
gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C
Normal file
22
gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C
Normal 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;
|
21
gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C
Normal file
21
gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C
Normal 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");
|
7
gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
Normal file
7
gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
Normal 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" }
|
||||
}
|
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C
Normal file
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C
Normal 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" }
|
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C
Normal file
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C
Normal file
|
@ -0,0 +1,4 @@
|
|||
// PR c++/28387
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
enum [[gnu::unused]] E; // { dg-error "without previous declaration" }
|
12
gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C
Normal 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" }
|
||||
};
|
15
gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C
Normal file
15
gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C
Normal 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)
|
||||
{
|
||||
}
|
6
gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C
Normal file
6
gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C
Normal 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" }
|
13
gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C
Normal file
13
gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C
Normal 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" }
|
||||
}
|
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C
Normal file
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C
Normal 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 ();
|
22
gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C
Normal file
22
gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C
Normal 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);
|
||||
}
|
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C
Normal 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 {}
|
16
gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C
Normal file
16
gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C
Normal 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);
|
||||
}
|
37
gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C
Normal file
37
gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C
Normal 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;
|
||||
}
|
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C
Normal file
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C
Normal 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;
|
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C
Normal file
19
gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C
Normal 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" } }
|
20
gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C
Normal file
20
gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C
Normal 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);
|
||||
}
|
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
Normal file
11
gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
Normal 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" }
|
23
gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C
Normal file
23
gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C
Normal 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);
|
||||
}
|
15
gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C
Normal file
15
gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C
Normal 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();
|
||||
}
|
12
gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C
Normal 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;
|
||||
}
|
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
Normal file
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
Normal 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;
|
||||
}
|
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C
Normal file
10
gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C
Normal 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;
|
||||
}
|
30
gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
Normal file
30
gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
Normal 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)
|
||||
;
|
5
gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C
Normal file
5
gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C
Normal 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" }
|
20
gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C
Normal file
20
gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C
Normal 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;
|
||||
}
|
||||
}
|
13
gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C
Normal file
13
gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C
Normal 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" }
|
||||
}
|
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
Normal file
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
Normal 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" }
|
3
gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C
Normal file
3
gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C
Normal file
|
@ -0,0 +1,3 @@
|
|||
// PR c++/52671
|
||||
// { dg-do compile { target c++11 } }
|
||||
[[gnu::deprecated]] enum E { E0 }; // { dg-warning "ignored in declaration" }
|
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C
Normal file
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C
Normal file
|
@ -0,0 +1,4 @@
|
|||
// PR c++/52906
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
[[gnu::deprecated]]; // { dg-error "does not declare anything" }
|
5
gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C
Normal file
5
gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C
Normal 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 "" }
|
8
gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
Normal file
8
gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
Normal 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;
|
||||
}
|
13
gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C
Normal file
13
gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C
Normal 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" }
|
||||
}
|
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C
Normal file
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C
Normal 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)");
|
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C
Normal file
17
gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C
Normal 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)");
|
23
gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C
Normal file
23
gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C
Normal 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];
|
22
gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C
Normal file
22
gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C
Normal 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)");
|
||||
|
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C
Normal 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");
|
21
gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
Normal file
21
gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
Normal 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");
|
||||
}
|
39
gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
Normal file
39
gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
Normal 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;
|
||||
}
|
||||
|
20
gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C
Normal file
20
gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C
Normal 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() { }
|
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C
Normal file
4
gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C
Normal file
|
@ -0,0 +1,4 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-Wunused-parameter" }
|
||||
|
||||
void f (int i [[gnu::__unused__]]) {}
|
6
gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C
Normal file
6
gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C
Normal 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" }
|
||||
|
12
gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
Normal file
12
gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
Normal 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" }
|
38
gcc/tree.c
38
gcc/tree.c
|
@ -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)
|
||||
|
|
30
gcc/tree.h
30
gcc/tree.h
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue