diff options
author | Dodji Seketeli <dodji@redhat.com> | 2012-10-08 09:29:05 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2012-10-08 11:29:05 +0200 |
commit | e28d52cffbb2abc7a5764ed4c97a25c376913fee (patch) | |
tree | 1a1442f932577112e42d0c3a2bb905d3ce01d5de /gcc/c-family | |
parent | f70308d411efebfce8f15b54fedd21c17d44740c (diff) | |
download | gcc-e28d52cffbb2abc7a5764ed4c97a25c376913fee.zip gcc-e28d52cffbb2abc7a5764ed4c97a25c376913fee.tar.gz gcc-e28d52cffbb2abc7a5764ed4c97a25c376913fee.tar.bz2 |
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
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 120 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 |
3 files changed, 131 insertions, 2 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 0d112cf..b49388d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -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. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 6de2f1c..e242789 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -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" diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index cefe92d..5b23bd3 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/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) |