Patchwork PR 53528 c++/ C++11 Generalized Attribute support

login
register
mail settings
Submitter Dodji Seketeli
Date Aug. 15, 2012, 7:43 a.m.
Message ID <m3boiclhx2.fsf@redhat.com>
Download mbox | patch
Permalink /patch/177558/
State New
Headers show

Comments

Dodji Seketeli - Aug. 15, 2012, 7:43 a.m.
> > Then I figured maybe I could:
> >
> >   - do what you suggest for non-tagged types.
> >   - for tagged types apply the attribute to the decl.  The aligned
> >     attribute in particular can be applied to the decl; that's a
> >     practical workaround way to comply with the requirement to apply
> >     the attribute to the type only for that declaration.
> 
> Or we could just require people to put the attribute in the right
> place (or one of the right places) if they want it to apply to the
> decl.  That is, either at the beginning of the declaration statement
> or after the declarator-id.

Just to make sure I understand, you mean, for tagged types?  Because
e.g for scalars, I feel like having is within the spirit of [dcl.spec]/1

    const int [[some-attr]] foo = 10;

(with [[some-attr]] applying to the integer type)

right?


> >>> +typedef union { int i; } U [[gnu::transparent_union]];

[...]

> It should be rejected because it's applying a type attribute to a
> declaration.

As the specification of the transparent_union attribute doesn't
enforce it to apply to types, I did the job in
handle_transparent_union_attribute.


> > For unused though, I am not sure how to do that in an appropriate
> > manner.  An idea?
> 
> What does it mean to say that int is unused?  It seems meaningless to me.

OK, in handle_unused_attribute, I prevent 'unused' from applying to
types, when used in the c+11 attribute syntax.

Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.


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.
	(attribute_spec_t): New typedef qualifier.
	* 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.
	(attribute_hash): Remove global variable.
	(attributes_table): New global variable.
	(find_attribute_namespace, register_scoped_attribute)
	(attributes_array_length): 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 c++11, choose strictest alignment
	among many.  Use new check_cxx_fundamental_alignment_constraints.
	(handle_unused_attribute): In c++11 attribute syntax, make this
	apply to decls only.
	(handle_transparent_union_attribute): In c++11 attribute syntax,
	make this apply to union types only.

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.
	(fold_non_dependent_expr_sfinae): This is now public.
	(cxx_alignas_expr): Declare new functions.
	* decl.c (check_tag_decl): Add check for c++11 attributes being
	applied to a missing declarator.
	(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
	cp_next_tokens_can_be_std_attribute_p here.
	(cp_parser_block_declaration): Use
	cp_nth_tokens_can_be_std_attribute_p here.
	(cp_parser_decl_specifier_seq): Likewise.  C++11 attributes
	appertain to the type that precedes them and only for the current
	declaration.  Get out when C++11 attributes follow the class
	specifier.
	(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
	off of 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.
	(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; set
	them to cp_declarator::std_attribute.  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.
	(cp_parser_label_for_labeled_statement): Parse optional c++11 attributes
	before the label and apply them to it.
	* semantics.c (potential_constant_expression_1): Likewise.
	* typeck.c (fundamental_alignment_p, cxx_alignas_expr): New public
	functions.
	* pt.c (fold_non_dependent_expr_sfinae): Make this public.

gcc/testsuite/

	* g++.dg/cpp0x/gen-attrs-1.C: New test.
	* g++.dg/cpp0x/gen-attrs-2.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-6-1.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-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.
---
 gcc/attribs.c                               |  269 +++++++++++-
 gcc/c-family/c-common.c                     |  128 ++++++-
 gcc/c-family/c-common.h                     |    1 +
 gcc/cp/cp-tree.h                            |   17 +-
 gcc/cp/decl.c                               |   56 +++-
 gcc/cp/decl2.c                              |    2 +-
 gcc/cp/error.c                              |    5 +
 gcc/cp/parser.c                             |  635 ++++++++++++++++++++++++---
 gcc/cp/pt.c                                 |    2 +-
 gcc/cp/typeck.c                             |   59 +++
 gcc/plugin.h                                |    3 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C    |    3 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C   |    9 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C   |   17 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C   |   17 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-13-1.C |    4 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C   |    5 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C   |   14 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C   |    9 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C   |    8 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C |   19 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C   |   19 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C   |   10 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C   |   11 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C    |   11 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C   |   22 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C   |   21 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C   |    7 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C   |   11 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C   |    4 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C   |   12 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C   |   15 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C   |    6 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C   |   13 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C   |   10 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C    |   21 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C   |    9 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C   |   16 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C   |   37 ++
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C   |   19 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C   |   19 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C   |   20 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C |   13 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C   |   23 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C   |   15 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C   |   12 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C |   10 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C   |   10 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C    |   39 ++
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C   |    5 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C   |   20 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C   |   13 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C   |    6 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C   |    3 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C   |    4 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C   |    5 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C   |   13 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C   |   17 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C   |   17 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C    |   23 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C   |   22 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C   |    9 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C   |   21 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C   |   32 ++
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-6-1.C  |   16 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C    |   20 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C    |    4 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C    |    6 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C    |   12 +
 gcc/tree.c                                  |   38 +-
 gcc/tree.h                                  |   34 +-
 71 files changed, 1946 insertions(+), 111 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-13-1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-6-1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
Jason Merrill - Aug. 23, 2012, 3:29 a.m.
On 08/15/2012 03:43 AM, Dodji Seketeli wrote:
>> Or we could just require people to put the attribute in the right
>> place (or one of the right places) if they want it to apply to the
>> decl.  That is, either at the beginning of the declaration statement
>> or after the declarator-id.
>
> Just to make sure I understand, you mean, for tagged types?  Because
> e.g for scalars, I feel like having is within the spirit of [dcl.spec]/1
>
>      const int [[some-attr]] foo = 10;
>
> (with [[some-attr]] applying to the integer type)
>
> right?

Yes, in this declaration [[some-attr]] applies to the type.  Whether or 
not that makes sense depends on the attribute and the type. 
Specifically, it doesn't ever make sense for classes, and I'm resistant 
to doing it for any types until we clarify how attributes participate in 
the type system.  C++11 doesn't clarify that because it doesn't have any 
attributes that can be used in this context.

I think we should start out with a fairly strict interpretation of the 
rules, and possibly relax them later, rather than try to relax them now.

>>> For unused though, I am not sure how to do that in an appropriate
>>> manner.  An idea?
>>
>> What does it mean to say that int is unused?  It seems meaningless to me.
>
> OK, in handle_unused_attribute, I prevent 'unused' from applying to
> types, when used in the c+11 attribute syntax.

Well, it does make sense to specify 'unused' in a class definition (i.e. 
when ATTR_FLAG_TYPE_IN_PLACE is set), it just doesn't make sense to 
apply it to a type-specifier.

> +  if (TREE_CODE (*node) != UNION_TYPE)
> +    {
> +      if (flags & ATTR_FLAG_CXX11)
> +       {
> +         /* transparent_union is being used as a c++11 attribute.  In
> +            this mode we force it to apply to a union types only.  */
> +         warning (OPT_Wattributes,
> +                  "attribute %qE applies to union types only", name);
> +         return NULL_TREE;
> +       }
> +    }

I think it would be better to disable looking through the TYPE_DECL in 
this case and then share the warning with the normal case.

> +check_cxx_fundamental_alignment_constraints (tree node,

In this function it would be nice to print out the requested and maximum 
alignments in the error.  And I wonder if we want to offer this as an 
optional warning for GNU attribute syntax.

> +  else if (flags & ATTR_FLAG_CXX11
> +          && 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].  */
> +    *no_add_attrs = true;

This seems like a good change in general; I'd be inclined to drop the 
check for C++11 syntax.  If there are multiple conflicting alignments 
specified for a declaration, the only things that make sense are to 
choose the largest alignment or give an error; the current behavior of 
choosing the most recently-specified alignment is just broken.

> +      if (cxx11_attribute_p (declspecs->attributes))
> +       warning_at (declspecs->locations[ds_attribute],
> +                   OPT_Wattributes,
> +                   "ignoring attribute applying to missing declarator");

Does this distinguish between attributes before the class-specifier 
(which appertain to any declarations) and attributes after the 
class-specifier (which appertain to the type as used in any declarations)?

I think it would be helpful to clarify that the attributes apply to 
declarators because they're at the beginning of the declaration, and 
keep the inform call for this case as well.

> +         if (std_attrs != NULL_TREE)
> +           {
> +             /*  Attributes should be parsed as part of the the
> +                 declaration, so let's un-parse them.  */
> +             cp_lexer_rollback_tokens (parser->lexer);
> +             std_attrs = NULL_TREE;
> +           }

Huh?  Attributes before a label appertain to the label, not the labeled 
statement.  And wouldn't this cause us to parse the label in an infinite 
loop?

> +            However, in G++ we cannot apply attributes to an already
> +            built *tagged* type, as that breaks some invariants.  So,
> +            for tagged types, to comply with [dcl.spec]/1 which says:
> +
> +                [The attribute-specifier-seq affects the type only for
> +                 the declaration it appears in, not other declarations
> +                 involving the same type]
> +
> +           we are going to apply the attributes to the declaration
> +           that is carrying this type, just like what is done for GNU
> +           attributes.  decl_attributes then knows how to apply the
> +           attributes to the type of that declaration only.  For
> +           non-tagged types, we are going to just apply the
> +           attribute.  */

As discussed above, we don't want to do this.  The attributes appertain 
to the type; for tagged types, that doesn't work, but that just means 
the user's (new) code is wrong, not that we should do something different.

This is especially wrong if the declarator isn't a simple declarator-id.

> +        around as prefix attributes that apply them to the entity

"that apply to"

> +cp_parser_attributes_opt (cp_parser *parser)
> +{
> +

Extra newline.

> +  if (token->type == CPP_NAME)
> +    attr_id = token->u.value;
> +  else if (token->type == CPP_KEYWORD)
> +    attr_id = ridpointers[(int) token->keyword];
> +  else
> +    return NULL_TREE;

Does this handle alternative tokens like "and"?

> +  /* Now parse the optional argument close of the attribute.  */

"clause"

> +      bool complain = !cp_parser_uncommitted_to_tentative_parse_p (parser);

Errors in cxx_alignas_expr don't cause tentative parsing to fail; 
therefore they should not be conditional on tentative parsing.  I don't 
think it's possible for a tentatively parsed alignas to actually be an 
identifier, is it?

>   if (processing_template_decl)
>     {
>       /* If E is a constant, fold it and return it right away.
>          Otherwise, build an ALIGNOF_EXPR that will be substituted
>          into, later at template instantiation time.  */
>       tree cst = TYPE_P (e) ? NULL_TREE : fold_non_dependent_expr_sfinae (e, tf_none);

Shouldn't tf_none be complain here?

>       if (cst != NULL && cst != error_mark_node)
>         return cst;
>       return cxx_alignof_expr (e, complain);
>     }

We shouldn't call cxx_alignof_expr here; the argument to alignas is the 
numerical alignment, whereas cxx_alignof_expr gives us the alignment of 
a value.  And we don't want to call it on types.  I think we can 
actually get away without a template special case here, as long as we 
change the cxx_constant_value lower down to fold_non_dependent_expr_sfinae.

 > +  if (TYPE_P (e))
 > +    {
 > +      e = mark_type_use (e);

mark_type_use is to be used on expressions, not types.

> +  float bar [[gnu::aligned(__alignof__(double))]];

Let's use alignof rather than __alignof__.

> +extern char *f (__const char, int) throw () [[gnu::__pure__]]; // { dg-warning "does not apply to types" }
> +extern int f1 (char *) [[gnu::warn_unused_result]];
> +extern int f3 (char *) [[gnu::nonnull (1)]];
> +  void foo [[gnu::format (printf,2,3)]] (char const * ...);
> +unsigned int f1 [[gnu::const]] ();
> +typedef int (*F) (int) [[gnu::warn_unused_result]];
> +  typedef void (T::*F) (L*) [[gnu::__stdcall__]];
> +int
> +three (void)
> +[[gnu::noreturn]]; // { dg-warning "does not apply to types" }
> +  inline Vector<T> operator<< [[gnu::always_inline]] (int x) const;
> +  [[gnu::fastcall]] void f();
> +extern void foo  () [[gnu::nothrow]]; // { dg-warning "attribute does not apply to types" }

Because of quirks of the internal representation, some of these 
attributes are treated as applying to the decl, and some to the type, 
but we shouldn't be enforcing these arbitrary differences.  I guess we 
can fix this later, but we shouldn't test for the current behavior.

Jason

Patch

diff --git a/gcc/attribs.c b/gcc/attribs.c
index d3af414..5347eb4 100644
--- a/gcc/attribs.c
+++ b/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_t);
+DEF_VEC_ALLOC_O (attribute_spec_t, heap);
+
+/* Scoped attribute name representation.  */
+
+typedef struct scoped_attributes
+{
+  const char *ns;
+  VEC (attribute_spec_t, heap) *attributes;
+  htab_t attribute_hash;
+} scoped_attributes_t;
+
+DEF_VEC_O (scoped_attributes_t);
+DEF_VEC_ALLOC_O (scoped_attributes_t, heap);
+
+/* The table of scope attributes.  */
+static VEC(scoped_attributes_t, heap) *attributes_table;
+
+static scoped_attributes_t* find_attribute_namespace (const char*);
+static void register_scoped_attribute (const struct attribute_spec *,
+				       scoped_attributes_t *);
+
 static bool attributes_initialized = false;
 
 /* Default empty table of attributes.  */
@@ -102,6 +121,116 @@  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.
+   ATTRIBUTES_LENGTH is the length of the ATTRIBUTES array.  NS is the
+   name of attribute namespace.  The function returns the namespace
+   into which the attributes have been registered.  */
+
+scoped_attributes_t*
+register_scoped_attributes (const struct attribute_spec * attributes,
+			    unsigned attributes_length,
+			    const char* ns)
+{
+  unsigned index;
+  scoped_attributes_t *result = NULL, *attrs;
+  bool found_attrs = false;
+
+   /* See if we already have attributes in the namespace NS.  */
+  FOR_EACH_VEC_ELT (scoped_attributes_t,
+		    attributes_table,
+		    index, attrs)
+    {
+      if (strcmp (attrs->ns, ns) == 0)
+	{
+	  found_attrs = true;
+	  break;
+	}
+    }
+
+  if (found_attrs)
+    {
+      /* We already have attributes in the namespace NS.  Add
+	 ATTRIBUTES to that namespace.  */
+
+      unsigned i;
+
+      gcc_assert (strcmp (attrs->ns, ns) == 0);
+
+      result = VEC_index (scoped_attributes_t, attributes_table, index);
+
+      for (i = 0; i < attributes_length; ++i)
+	VEC_safe_push (attribute_spec_t, heap,
+		       result->attributes, &attributes[i]);
+    }
+  else
+    {
+      /* We don't have any namespace NS yet.  Create one and add
+	 ATTRIBUTES into it.  */
+
+      scoped_attributes_t sa;
+      unsigned i;
+
+      if (attributes_table == NULL)
+	attributes_table = VEC_alloc (scoped_attributes_t, heap, 64);
+
+      memset (&sa, 0, sizeof (sa));
+      sa.ns = ns;
+      sa.attributes = VEC_alloc (attribute_spec_t, heap, 64);
+      for (i = 0; i < attributes_length; ++i)
+	VEC_safe_push (attribute_spec_t, heap, sa.attributes, &attributes[i]);
+      VEC_safe_push (scoped_attributes_t, heap, attributes_table, &sa);
+      result = VEC_last (scoped_attributes_t, attributes_table);
+    }
+
+  if (result != NULL)
+    {
+      unsigned i;
+      for (i = 0; i < attributes_length; ++i)
+	register_scoped_attribute (&attributes[i], result);
+    }
+  return result;
+}
+
+/* Return the namespace which name is NS, NULL if none exist.  */
+
+static scoped_attributes_t*
+find_attribute_namespace (const char* ns)
+{
+  unsigned ix;
+  scoped_attributes_t *iter;
+
+  FOR_EACH_VEC_ELT (scoped_attributes_t, attributes_table, ix, iter)
+    if (ns == iter->ns
+	|| (iter->ns != NULL
+	    && ns != NULL
+	    && !strcmp (iter->ns, ns)))
+      {
+	if (iter->attribute_hash == 0)
+	  iter->attribute_hash =
+	    htab_create (200, hash_attr, eq_attr, NULL);
+	return VEC_index (scoped_attributes_t, attributes_table, ix);
+      }
+
+  return NULL;
+}
+
+/* Return the length of the NULL terminated array of struct
+   attribute_spec.  */
+
+static unsigned
+attributes_array_length (const struct attribute_spec *attributes_array)
+{
+  unsigned i;
+
+  if (attributes_array == NULL || attributes_array[0].name == NULL)
+    return 0;
+
+  for (i = 0; attributes_array[i].name != NULL; ++i)
+    ;
+
+  return i;
+}
+
 /* Initialize attribute tables, and make some sanity checks
    if --enable-checking.  */
 
@@ -109,7 +238,6 @@  void
 init_attributes (void)
 {
   size_t i;
-  int k;
 
   if (attributes_initialized)
     return;
@@ -181,12 +309,12 @@  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],
+				attributes_array_length (attribute_tables[i]),
+				"gnu");
+
   invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
   attributes_initialized = true;
 }
@@ -196,9 +324,23 @@  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_t *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 +348,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 attribute named NAME.  */
+/* Return the spec for the scoped attribute with namespace NS and
+   name NAME.   */
 
 const struct attribute_spec *
-lookup_attribute_spec (const_tree name)
+lookup_scoped_attribute_spec (const_tree ns, const_tree name)
 {
   struct substring attr;
+  scoped_attributes_t *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 (attribute_hash, &attr,
+    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)
+{
+  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 +403,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 +462,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 +475,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
@@ -406,9 +575,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 +663,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.  */
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index a002541..c46404e 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 },
@@ -6445,6 +6446,14 @@  handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     }
   else
     {
+      if (flags & ATTR_FLAG_CXX11)
+	{
+	  /* unused is being used as a c++11 attribute.  In this mode
+	     we prevent it from applying to types.  */
+	  warning (OPT_Wattributes,
+		   "attribute %qE cannot be applied to a type", name);
+	  return NULL_TREE;
+	}
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
 	*node = build_variant_type_copy (*node);
       TREE_USED (*node) = 1;
@@ -6522,6 +6531,18 @@  handle_transparent_union_attribute (tree *node, tree name,
 
   *no_add_attrs = true;
 
+  if (TREE_CODE (*node) != UNION_TYPE)
+    {
+      if (flags & ATTR_FLAG_CXX11)
+	{
+	  /* transparent_union is being used as a c++11 attribute.  In
+	     this mode we force it to apply to a union types only.  */
+	  warning (OPT_Wattributes,
+		   "attribute %qE applies to union types only", name);
+	  return NULL_TREE;
+	}
+    }
+
   if (TREE_CODE (*node) == TYPE_DECL)
     node = &TREE_TYPE (*node);
   type = *node;
@@ -6993,6 +7014,84 @@  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;
+
+  if (!(flags & ATTR_FLAG_CXX11)
+      || (node == NULL_TREE || node == error_mark_node))
+    return true;
+
+  if (cxx_fundamental_alignment_p ((1U << align_log)))
+    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 ((1U << align_log) > 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.  */
+	  if (TREE_CODE (node) == FIELD_DECL
+	      && decl_function_context (node)
+	      && (1U << align_log) > 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
+		   && (1U << align_log) > MAX_STACK_ALIGNMENT)
+	    alignment_too_large_p = true;
+	}
+    }
+  else if (TYPE_P (node))
+    {
+      /* Let's be liberal for types.  */
+      if ((1U << align_log) > BIGGEST_ALIGNMENT)
+	alignment_too_large_p = true;
+    }
+
+  if (alignment_too_large_p)
+    error ("requested alignment is too large");
+
+  return !alignment_too_large_p;
+}
 
 /* Handle a "aligned" attribute; arguments as in
    struct attribute_spec.handler.  */
@@ -7017,7 +7116,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)
     {
@@ -7047,6 +7147,13 @@  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 (flags & ATTR_FLAG_CXX11
+	   && 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].  */
+    *no_add_attrs = true;
   else if (TREE_CODE (decl) == FUNCTION_DECL
 	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
     {
@@ -11011,4 +11118,23 @@  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(std::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 050112e..691593f 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -787,6 +787,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)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 44f3ac1..9437197 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -411,7 +411,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. */
@@ -4680,6 +4682,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.  */
@@ -4698,6 +4701,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;
@@ -4766,8 +4771,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;
@@ -5399,6 +5410,7 @@  extern tree build_non_dependent_expr		(tree);
 extern void make_args_non_dependent		(VEC(tree,gc) *);
 extern bool reregister_specialization		(tree, tree, tree);
 extern tree fold_non_dependent_expr		(tree);
+extern tree fold_non_dependent_expr_sfinae      (tree, tsubst_flags_t);
 extern bool alias_type_or_template_p            (tree);
 extern bool alias_template_specialization_p     (tree);
 extern bool explicit_class_specialization_p     (tree);
@@ -5817,6 +5829,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, tsubst_flags_t);
 extern tree cxx_sizeof_nowarn                   (tree);
 extern tree is_bitfield_expr_with_lowered_type  (const_tree);
 extern tree unlowered_expr_type                 (const_tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b637643..038628a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4238,10 +4238,17 @@  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 (cxx11_attribute_p (declspecs->attributes))
+	warning_at (declspecs->locations[ds_attribute],
+		    OPT_Wattributes,
+		    "ignoring attribute applying to missing declarator");
+      else
+	{
+	  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));
+	}
     }
 
   return declared_type;
@@ -9111,6 +9118,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)
@@ -9148,6 +9164,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:
@@ -9344,6 +9367,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;
 
@@ -9506,6 +9536,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 like 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;
 
@@ -9658,6 +9699,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)
     {
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 281f6ff..50d466c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 58f0aff..fe20e836 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3368,6 +3368,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 ();
       }
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d8c3305..56c13a9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1232,6 +1232,7 @@  make_declarator (cp_declarator_kind kind)
   declarator = (cp_declarator *) alloc_declarator (sizeof (cp_declarator));
   declarator->kind = kind;
   declarator->attributes = NULL_TREE;
+  declarator->std_attributes = NULL_TREE;
   declarator->declarator = NULL;
   declarator->parameter_pack_p = false;
   declarator->id_loc = UNKNOWN_LOCATION;
@@ -1961,7 +1962,7 @@  static cp_declarator *cp_parser_declarator
 static cp_declarator *cp_parser_direct_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool);
 static enum tree_code cp_parser_ptr_operator
-  (cp_parser *, tree *, cp_cv_quals *);
+  (cp_parser *, tree *, cp_cv_quals *, tree *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
 static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
@@ -2103,9 +2104,29 @@  static tree cp_parser_asm_clobber_list
   (cp_parser *);
 static tree cp_parser_asm_label_list
   (cp_parser *);
+static bool cp_next_tokens_can_be_attribute_p
+  (cp_parser *);
+static bool cp_next_tokens_can_be_gnu_attribute_p
+  (cp_parser *);
+static bool cp_next_tokens_can_be_std_attribute_p
+  (cp_parser *);
+static bool cp_nth_tokens_can_be_std_attribute_p
+  (cp_parser *, size_t);
+static bool cp_nth_tokens_can_be_gnu_attribute_p
+  (cp_parser *, size_t);
+static bool cp_nth_tokens_can_be_attribute_p
+  (cp_parser *, size_t);
 static tree cp_parser_attributes_opt
   (cp_parser *);
-static tree cp_parser_attribute_list
+static tree cp_parser_gnu_attributes_opt
+  (cp_parser *);
+static tree cp_parser_gnu_attribute_list
+  (cp_parser *);
+static tree cp_parser_std_attribute
+  (cp_parser *);
+static tree cp_parser_std_attribute_spec
+  (cp_parser *);
+static tree cp_parser_std_attribute_spec_seq
   (cp_parser *);
 static bool cp_parser_extension_opt
   (cp_parser *, int *);
@@ -5609,6 +5630,13 @@  cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
       switch (token->type)
 	{
 	case CPP_OPEN_SQUARE:
+	  if (cp_next_tokens_can_be_std_attribute_p (parser))
+	    {
+	      cp_parser_error (parser,
+			       "two consecutive %<[%> shall "
+			       "only introduce an attribute");
+	      return error_mark_node;
+	    }
 	  postfix_expression
 	    = cp_parser_postfix_open_square_expression (parser,
 							postfix_expression,
@@ -6853,13 +6881,13 @@  static cp_declarator *
 cp_parser_new_declarator_opt (cp_parser* parser)
 {
   enum tree_code code;
-  tree type;
-  cp_cv_quals cv_quals;
+  tree type, std_attributes = NULL_TREE;
+  cp_cv_quals cv_quals;  
 
   /* We don't know if there's a ptr-operator next, or not.  */
   cp_parser_parse_tentatively (parser);
   /* Look for a ptr-operator.  */
-  code = cp_parser_ptr_operator (parser, &type, &cv_quals);
+  code = cp_parser_ptr_operator (parser, &type, &cv_quals, &std_attributes);
   /* If that worked, look for more new-declarators.  */
   if (cp_parser_parse_definitely (parser))
     {
@@ -6868,8 +6896,11 @@  cp_parser_new_declarator_opt (cp_parser* parser)
       /* Parse another optional declarator.  */
       declarator = cp_parser_new_declarator_opt (parser);
 
-      return cp_parser_make_indirect_declarator
+      declarator = cp_parser_make_indirect_declarator
 	(code, type, cv_quals, declarator);
+      if (declarator != NULL && declarator != cp_error_declarator)
+	declarator->attributes = std_attributes;
+      return declarator;
     }
 
   /* If the next token is a `[', there is a direct-new-declarator.  */
@@ -8608,6 +8639,18 @@  cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
      declaration-statement
      try-block
 
+  C++11:
+
+  statement:
+    labeled-statement
+    attribute-specifier-seq (opt) expression-statement
+    attribute-specifier-seq (opt) compound-statement
+    attribute-specifier-seq (opt) selection-statement
+    attribute-specifier-seq (opt) iteration-statement
+    attribute-specifier-seq (opt) jump-statement
+    declaration-statement
+    attribute-specifier-seq (opt) try-block
+
   TM Extension:
 
    statement:
@@ -8624,15 +8667,20 @@  static void
 cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 		     bool in_compound, bool *if_p)
 {
-  tree statement;
+  tree statement, std_attrs = NULL_TREE;
   cp_token *token;
-  location_t statement_location;
+  location_t statement_location, attrs_location;
 
  restart:
   if (if_p != NULL)
     *if_p = false;
   /* There is no statement yet.  */
   statement = NULL_TREE;
+
+  cp_lexer_save_tokens (parser->lexer);
+  attrs_location = cp_lexer_peek_token (parser->lexer)->location;
+  std_attrs = cp_parser_std_attribute_spec_seq (parser);
+
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* Remember the location of the first token in the statement.  */
@@ -8650,6 +8698,13 @@  cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 	  /* Looks like a labeled-statement with a case label.
 	     Parse the label, and then use tail recursion to parse
 	     the statement.  */
+	  if (std_attrs != NULL_TREE)
+	    {
+	      /*  Attributes should be parsed as part of the the
+		  declaration, so let's un-parse them.  */
+	      cp_lexer_rollback_tokens (parser->lexer);
+	      std_attrs = NULL_TREE;
+	    }
 	  cp_parser_label_for_labeled_statement (parser);
 	  goto restart;
 
@@ -8713,6 +8768,15 @@  cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 	  /* Looks like a labeled-statement with an ordinary label.
 	     Parse the label, and then use tail recursion to parse
 	     the statement.  */
+
+	  if (std_attrs != NULL_TREE)
+	    {
+	      /*  Attributes should be parsed as part of the the
+		  declaration, so let's un-parse them.  */
+	      cp_lexer_rollback_tokens (parser->lexer);
+	      std_attrs = NULL_TREE;
+	    }
+
 	  cp_parser_label_for_labeled_statement (parser);
 	  goto restart;
 	}
@@ -8749,6 +8813,14 @@  cp_parser_statement (cp_parser* parser, tree in_statement_expr,
     {
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
 	{
+	  if (std_attrs != NULL_TREE)
+	    {
+	      /*  Attributes should be parsed as part of the the
+		  declaration, so let's un-parse them.  */
+	      cp_lexer_rollback_tokens (parser->lexer);
+	      std_attrs = NULL_TREE;
+	    }
+
 	  cp_parser_parse_tentatively (parser);
 	  /* Try to parse the declaration-statement.  */
 	  cp_parser_declaration_statement (parser);
@@ -8763,6 +8835,13 @@  cp_parser_statement (cp_parser* parser, tree in_statement_expr,
   /* Set the line number for the statement.  */
   if (statement && STATEMENT_CODE_P (TREE_CODE (statement)))
     SET_EXPR_LOCATION (statement, statement_location);
+
+  /* Note that for now, we don't do anything with c++11 statements
+     parsed at this level.  */
+  if (std_attrs != NULL_TREE)
+    warning_at (attrs_location,
+		OPT_Wattributes,
+		"attributes at the beginning of statement are ignored");
 }
 
 /* Parse the label for a labeled-statement, i.e.
@@ -8783,6 +8862,7 @@  cp_parser_label_for_labeled_statement (cp_parser* parser)
 {
   cp_token *token;
   tree label = NULL_TREE;
+  tree attributes = cp_parser_std_attribute_spec_seq (parser);
   bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
 
   /* The next token should be an identifier.  */
@@ -8859,21 +8939,23 @@  cp_parser_label_for_labeled_statement (cp_parser* parser)
        lab: __attribute__ ((unused)) int i;
      we want the attribute to attach to "i", not "lab".  */
   if (label != NULL_TREE
-      && cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+      && cp_next_tokens_can_be_gnu_attribute_p (parser))
     {
       tree attrs;
-
       cp_parser_parse_tentatively (parser);
-      attrs = cp_parser_attributes_opt (parser);
+      attrs = cp_parser_gnu_attributes_opt (parser);
       if (attrs == NULL_TREE
 	  || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
 	cp_parser_abort_tentative_parse (parser);
       else if (!cp_parser_parse_definitely (parser))
 	;
       else
-	cplus_decl_attributes (&label, attrs, 0);
+	attributes = chainon (attributes, attrs);
     }
 
+  if (attributes != NULL_TREE)
+    cplus_decl_attributes (&label, attributes, 0);
+
   parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
 }
 
@@ -10299,8 +10381,7 @@  cp_parser_block_declaration (cp_parser *parser,
       else if (cxx_dialect >= cxx0x
 	       && token2->type == CPP_NAME
 	       && ((cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ)
-		   || (cp_lexer_peek_nth_token (parser->lexer, 3)->keyword
-		       == RID_ATTRIBUTE)))
+		   || (cp_nth_tokens_can_be_attribute_p (parser, 3))))
 	cp_parser_alias_declaration (parser);
       /* Otherwise, it's a using-declaration.  */
       else
@@ -10530,6 +10611,7 @@  cp_parser_simple_declaration (cp_parser* parser,
 
    decl-specifier-seq:
      decl-specifier-seq [opt] decl-specifier
+     decl-specifier attribute-specifier-seq [opt] (C++11)
 
    decl-specifier:
      storage-class-specifier
@@ -10564,6 +10646,7 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
 			      int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
+  bool found_decl_spec = false;
   cp_token *start_token = NULL;
   cp_decl_spec ds;
 
@@ -10577,7 +10660,6 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
   while (true)
     {
       bool constructor_p;
-      bool found_decl_spec;
       cp_token *token;
       ds = ds_last;
 
@@ -10589,12 +10671,75 @@  cp_parser_decl_specifier_seq (cp_parser* parser,
       if (!start_token)
 	start_token = token;
       /* Handle attributes.  */
-      if (token->keyword == RID_ATTRIBUTE)
+      if (cp_next_tokens_can_be_attribute_p (parser))
 	{
 	  /* Parse the attributes.  */
-	  decl_specs->attributes
-	    = chainon (decl_specs->attributes,
-		       cp_parser_attributes_opt (parser));
+	  tree attrs = cp_parser_attributes_opt (parser);
+
+	  /* In a sequence of declaration specifiers, c++11 attributes
+	     appertain to the type that precede them.  So the if block
+	     below is going to apply the attributes to that type.
+
+	     However, in G++ we cannot apply attributes to an already
+	     built *tagged* type, as that breaks some invariants.  So,
+	     for tagged types, to comply with [dcl.spec]/1 which says:
+
+	         [The attribute-specifier-seq affects the type only for
+		  the declaration it appears in, not other declarations
+		  involving the same type]
+
+	    we are going to apply the attributes to the declaration
+	    that is carrying this type, just like what is done for GNU
+	    attributes.  decl_attributes then knows how to apply the
+	    attributes to the type of that declaration only.  For
+	    non-tagged types, we are going to just apply the
+	    attribute.  */
+	  if (cxx11_attribute_p (attrs))
+	    {
+	      if (!found_decl_spec)
+		/* The c++11 attribute is at the beginning of the
+		   declaration.  It appertains to the entity being
+		   declared.  */;
+	      else
+		{
+		  /* The c++11 attributes appertain to the type that
+		     precedes.  */
+		  if (decl_specs->type == NULL_TREE)
+		    {
+		      error_at (token->location,
+				"expected type specifier before attribute");
+		      attrs = NULL;
+		    }
+		  else
+		    {
+		      if (!TAGGED_TYPE_P (decl_specs->type))
+			{
+			  /* For non-tagged types, schedule these
+			     attributes to be applied to the type that
+			     precedes.  grokdeclarator is where the
+			     attribute is going to be applied, by
+			     calling decl_attributes.  */
+			  decl_specs->std_attributes =
+			    chainon (decl_specs->attributes, attrs);
+			  if (decl_specs->locations[ds_std_attribute] == 0)
+			    decl_specs->locations[ds_std_attribute]
+			      = token->location;
+			  attrs = NULL_TREE;
+			}
+		      else
+			{
+			  /*  For a tagged type, we apply the
+			      attributes to the declaration, as
+			      explained in the comment of the
+			      enclosing 'if' block.  */;
+			}
+		    }
+		}
+	    }
+
+	    decl_specs->attributes
+	      = chainon (decl_specs->attributes,
+			 attrs);
 	  if (decl_specs->locations[ds_attribute] == 0)
 	    decl_specs->locations[ds_attribute] = token->location;
 	  continue;
@@ -11321,13 +11466,14 @@  static cp_declarator *
 cp_parser_conversion_declarator_opt (cp_parser* parser)
 {
   enum tree_code code;
-  tree class_type;
+  tree class_type, std_attributes = NULL_TREE;
   cp_cv_quals cv_quals;
 
   /* We don't know if there's a ptr-operator next, or not.  */
   cp_parser_parse_tentatively (parser);
   /* Try the ptr-operator.  */
-  code = cp_parser_ptr_operator (parser, &class_type, &cv_quals);
+  code = cp_parser_ptr_operator (parser, &class_type, &cv_quals,
+				 &std_attributes);
   /* If it worked, look for more conversion-declarators.  */
   if (cp_parser_parse_definitely (parser))
     {
@@ -11336,8 +11482,11 @@  cp_parser_conversion_declarator_opt (cp_parser* parser)
       /* Parse another optional declarator.  */
       declarator = cp_parser_conversion_declarator_opt (parser);
 
-      return cp_parser_make_indirect_declarator
+      declarator = cp_parser_make_indirect_declarator
 	(code, class_type, cv_quals, declarator);
+      if (declarator != NULL || declarator != cp_error_declarator)
+	declarator->attributes = std_attributes;
+      return declarator;
    }
 
   return NULL;
@@ -14596,7 +14745,7 @@  cp_parser_enum_specifier (cp_parser* parser)
      apply them if appropriate.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
-      tree trailing_attr = cp_parser_attributes_opt (parser);
+      tree trailing_attr = cp_parser_gnu_attributes_opt (parser);
       trailing_attr = chainon (trailing_attr, attributes);
       cplus_decl_attributes (&type,
 			     trailing_attr,
@@ -15498,7 +15647,7 @@  cp_parser_init_declarator (cp_parser* parser,
            *attributes_start_token = NULL;
   cp_declarator *declarator;
   tree prefix_attributes;
-  tree attributes;
+  tree attributes = NULL;
   tree asm_specification;
   tree initializer;
   tree decl = NULL_TREE;
@@ -15564,22 +15713,20 @@  cp_parser_init_declarator (cp_parser* parser,
   decl_specifiers->type
     = maybe_update_decl_type (decl_specifiers->type, scope);
 
-  /* If we're allowing GNU extensions, look for an asm-specification
-     and attributes.  */
+  /* If we're allowing GNU extensions, look for an
+     asm-specification.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       /* Look for an asm-specification.  */
       asm_spec_start_token = cp_lexer_peek_token (parser->lexer);
       asm_specification = cp_parser_asm_specification_opt (parser);
-      /* And attributes.  */
-      attributes_start_token = cp_lexer_peek_token (parser->lexer);
-      attributes = cp_parser_attributes_opt (parser);
     }
   else
-    {
-      asm_specification = NULL_TREE;
-      attributes = NULL_TREE;
-    }
+    asm_specification = NULL_TREE;
+
+  /* Look for attributes.  */
+  attributes_start_token = cp_lexer_peek_token (parser->lexer);
+  attributes = cp_parser_attributes_opt (parser);
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -15908,7 +16055,7 @@  cp_parser_declarator (cp_parser* parser,
   enum tree_code code;
   cp_cv_quals cv_quals;
   tree class_type;
-  tree attributes = NULL_TREE;
+  tree gnu_attributes = NULL_TREE, std_attributes = NULL_TREE;
 
   /* Assume this is not a constructor, destructor, or type-conversion
      operator.  */
@@ -15916,14 +16063,16 @@  cp_parser_declarator (cp_parser* parser,
     *ctor_dtor_or_conv_p = 0;
 
   if (cp_parser_allow_gnu_extensions_p (parser))
-    attributes = cp_parser_attributes_opt (parser);
+    gnu_attributes = cp_parser_gnu_attributes_opt (parser);
 
   /* Check for the ptr-operator production.  */
   cp_parser_parse_tentatively (parser);
   /* Parse the ptr-operator.  */
   code = cp_parser_ptr_operator (parser,
 				 &class_type,
-				 &cv_quals);
+				 &cv_quals,
+				 &std_attributes);
+
   /* If that worked, then we have a ptr-operator.  */
   if (cp_parser_parse_definitely (parser))
     {
@@ -15950,6 +16099,15 @@  cp_parser_declarator (cp_parser* parser,
 
       declarator = cp_parser_make_indirect_declarator
 	(code, class_type, cv_quals, declarator);
+
+      /* For C++11 attributes, the standard at [decl.ptr]/1 says:
+
+	     the optional attribute-specifier-seq appertains to the
+	     pointer and not to the object pointed to".  */
+      if (std_attributes
+	  && declarator
+	  && (declarator != cp_error_declarator))
+	declarator->std_attributes = std_attributes;
     }
   /* Everything else is a direct-declarator.  */
   else
@@ -15962,9 +16120,8 @@  cp_parser_declarator (cp_parser* parser,
 						member_p);
     }
 
-  if (attributes && declarator && declarator != cp_error_declarator)
-    declarator->attributes = attributes;
-
+  if (gnu_attributes && declarator && declarator != cp_error_declarator)
+    declarator->attributes = gnu_attributes;
   return declarator;
 }
 
@@ -16104,6 +16261,7 @@  cp_parser_direct_declarator (cp_parser* parser,
 		  cp_virt_specifiers virt_specifiers;
 		  tree exception_specification;
 		  tree late_return;
+		  tree attrs;
 
 		  is_declarator = true;
 
@@ -16117,6 +16275,8 @@  cp_parser_direct_declarator (cp_parser* parser,
 		  exception_specification
 		    = cp_parser_exception_specification_opt (parser);
 
+		  attrs = cp_parser_std_attribute_spec_seq (parser);
+
 		  late_return = (cp_parser_late_return_type_opt
 				 (parser, member_p ? cv_quals : -1));
 
@@ -16130,6 +16290,7 @@  cp_parser_direct_declarator (cp_parser* parser,
 						     virt_specifiers,
 						     exception_specification,
 						     late_return);
+		  declarator->std_attributes = attrs;
 		  /* Any subsequent parameter lists are to do with
 		     return type, so are not those of the declared
 		     function.  */
@@ -16179,10 +16340,11 @@  cp_parser_direct_declarator (cp_parser* parser,
 	    break;
 	}
       else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
-	       && token->type == CPP_OPEN_SQUARE)
+	       && token->type == CPP_OPEN_SQUARE
+	       && !cp_next_tokens_can_be_attribute_p (parser))
 	{
 	  /* Parse an array-declarator.  */
-	  tree bounds;
+	  tree bounds, attrs;
 
 	  if (ctor_dtor_or_conv_p)
 	    *ctor_dtor_or_conv_p = 0;
@@ -16235,13 +16397,16 @@  cp_parser_direct_declarator (cp_parser* parser,
 	      break;
 	    }
 
+	  attrs = cp_parser_std_attribute_spec_seq (parser);
 	  declarator = make_array_declarator (declarator, bounds);
+	  declarator->std_attributes = attrs;
 	}
       else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
 	{
 	  {
 	    tree qualifying_scope;
 	    tree unqualified_name;
+	    tree attrs;
 	    special_function_kind sfk;
 	    bool abstract_ok;
 	    bool pack_expansion_p = false;
@@ -16308,6 +16473,8 @@  cp_parser_direct_declarator (cp_parser* parser,
 		break;
 	      }
 
+	    attrs = cp_parser_std_attribute_spec_seq (parser);
+
 	    if (qualifying_scope && at_namespace_scope_p ()
 		&& TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
 	      {
@@ -16422,6 +16589,7 @@  cp_parser_direct_declarator (cp_parser* parser,
 	    declarator = make_id_declarator (qualifying_scope,
 					     unqualified_name,
 					     sfk);
+	    declarator->std_attributes = attrs;
 	    declarator->id_loc = token->location;
 	    declarator->parameter_pack_p = pack_expansion_p;
 
@@ -16469,9 +16637,11 @@  cp_parser_direct_declarator (cp_parser* parser,
 /* Parse a ptr-operator.
 
    ptr-operator:
+     * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11)
      * cv-qualifier-seq [opt]
      &
      :: [opt] nested-name-specifier * cv-qualifier-seq [opt]
+     nested-name-specifier * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11)
 
    GNU Extension:
 
@@ -16491,10 +16661,12 @@  cp_parser_direct_declarator (cp_parser* parser,
 static enum tree_code
 cp_parser_ptr_operator (cp_parser* parser,
 			tree* type,
-			cp_cv_quals *cv_quals)
+			cp_cv_quals *cv_quals,
+			tree *attributes)
 {
   enum tree_code code = ERROR_MARK;
   cp_token *token;
+  tree attrs = NULL_TREE;
 
   /* Assume that it's not a pointer-to-member.  */
   *type = NULL_TREE;
@@ -16525,6 +16697,10 @@  cp_parser_ptr_operator (cp_parser* parser,
       if (code == INDIRECT_REF
 	  || cp_parser_allow_gnu_extensions_p (parser))
 	*cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+
+      attrs = cp_parser_std_attribute_spec_seq (parser);
+      if (attributes != NULL)
+	*attributes = attrs;
     }
   else
     {
@@ -16562,6 +16738,10 @@  cp_parser_ptr_operator (cp_parser* parser,
 	      parser->scope = NULL_TREE;
 	      parser->qualifying_scope = NULL_TREE;
 	      parser->object_scope = NULL_TREE;
+	      /* Look for optional c++11 attributes.  */
+	      attrs = cp_parser_std_attribute_spec_seq (parser);
+	      if (attributes != NULL)
+		*attributes = attrs;
 	      /* Look for the optional cv-qualifier-seq.  */
 	      *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
 	    }
@@ -16921,7 +17101,7 @@  cp_parser_type_specifier_seq (cp_parser* parser,
       bool is_cv_qualifier;
 
       /* Check for attributes first.  */
-      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+      if (cp_next_tokens_can_be_attribute_p (parser))
 	{
 	  type_specifier_seq->attributes =
 	    chainon (type_specifier_seq->attributes,
@@ -18027,7 +18207,7 @@  cp_parser_class_specifier_1 (cp_parser* parser)
   closing_brace = cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
   /* Look for trailing attributes to apply to this class.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
-    attributes = cp_parser_attributes_opt (parser);
+    attributes = cp_parser_gnu_attributes_opt (parser);
   if (type != error_mark_node)
     type = finish_struct (type, attributes);
   if (nested_name_specifier_p)
@@ -18048,6 +18228,12 @@  cp_parser_class_specifier_1 (cp_parser* parser)
     cp_token *token = cp_lexer_peek_token (parser->lexer);
     bool want_semicolon = true;
 
+    if (cp_next_tokens_can_be_std_attribute_p (parser))
+      /* Don't try to parse c++11 attributes here.  As per the
+	 grammar, that should be a task for
+	 cp_parser_decl_specifier_seq.  */
+      want_semicolon = false;
+
     switch (token->type)
       {
       case CPP_NAME:
@@ -18898,8 +19084,6 @@  cp_parser_member_declaration (cp_parser* parser)
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
 				&declares_class_or_enum);
-  prefix_attributes = decl_specifiers.attributes;
-  decl_specifiers.attributes = NULL_TREE;
   /* Check for an invalid type-name.  */
   if (!decl_specifiers.any_type_specifiers_p
       && cp_parser_parse_and_diagnose_invalid_type_name (parser))
@@ -18998,6 +19182,12 @@  cp_parser_member_declaration (cp_parser* parser)
     {
       bool assume_semicolon = false;
 
+      /* Clear attributes from the decl_specifiers but keep them
+	 around as prefix attributes that apply them to the entity
+	 being declared.  */
+      prefix_attributes = decl_specifiers.attributes;
+      decl_specifiers.attributes = NULL_TREE;
+
       /* See if these declarations will be friends.  */
       friend_p = cp_parser_friend_p (&decl_specifiers);
 
@@ -20104,6 +20294,81 @@  cp_parser_asm_label_list (cp_parser* parser)
   return nreverse (labels);
 }
 
+/* Return TRUE iff the next tokens in the stream are possibly the
+   beginning of a GNU extension attribute. */
+
+static bool
+cp_next_tokens_can_be_gnu_attribute_p (cp_parser *parser)
+{
+  return cp_nth_tokens_can_be_gnu_attribute_p (parser, 1);
+}
+
+/* Return TRUE iff the next tokens in the stream are possibly the
+   beginning of a standard C++-11 attribute.  */
+
+static bool
+cp_next_tokens_can_be_std_attribute_p (cp_parser *parser)
+{
+  return cp_nth_tokens_can_be_std_attribute_p (parser, 1);
+}
+
+/* Return TRUE iff the next Nth tokens in the stream are possibly the
+   beginning of a standard C++-11 attribute.  */
+
+static bool
+cp_nth_tokens_can_be_std_attribute_p (cp_parser *parser, size_t n)
+{
+  cp_token *token = cp_lexer_peek_nth_token (parser->lexer, n);
+
+  return (cxx_dialect >= cxx0x
+	  && token->type == CPP_OPEN_SQUARE
+	  && (token = cp_lexer_peek_nth_token (parser->lexer, n + 1))
+	  && token->type == CPP_OPEN_SQUARE);
+}
+
+/* Return TRUE iff the next Nth tokens in the stream are possibly the
+   beginning of a GNU extension attribute.  */
+
+static bool
+cp_nth_tokens_can_be_gnu_attribute_p (cp_parser *parser, size_t n)
+{
+  cp_token *token = cp_lexer_peek_nth_token (parser->lexer, n);
+
+  return token->type == CPP_KEYWORD && token->keyword == RID_ATTRIBUTE;
+}
+
+/* Return true iff the next tokens can be the beginning of either a
+   GNU attribute list, or a standard C++11 attribute sequence.  */
+
+static bool
+cp_next_tokens_can_be_attribute_p (cp_parser *parser)
+{
+  return (cp_next_tokens_can_be_gnu_attribute_p (parser)
+	  || cp_next_tokens_can_be_std_attribute_p (parser));
+}
+
+/* Return true iff the next Nth tokens can be the beginning of either
+   a GNU attribute list, or a standard C++11 attribute sequence.  */
+
+static bool
+cp_nth_tokens_can_be_attribute_p (cp_parser *parser, size_t n)
+{
+  return (cp_nth_tokens_can_be_gnu_attribute_p (parser, n)
+	  || cp_nth_tokens_can_be_std_attribute_p (parser, n));
+}
+
+/* Parse either a standard C++-11 attribute-specifier-seq, or a series
+   of GNU attributes, or return NULL.  */
+
+static tree
+cp_parser_attributes_opt (cp_parser *parser)
+{
+
+  if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+      return cp_parser_gnu_attributes_opt (parser);
+  return cp_parser_std_attribute_spec_seq (parser);
+}
+
 /* Parse an (optional) series of attributes.
 
    attributes:
@@ -20112,10 +20377,10 @@  cp_parser_asm_label_list (cp_parser* parser)
    attribute:
      __attribute__ (( attribute-list [opt] ))
 
-   The return value is as for cp_parser_attribute_list.  */
+   The return value is as for cp_parser_gnu_attribute_list.  */
 
 static tree
-cp_parser_attributes_opt (cp_parser* parser)
+cp_parser_gnu_attributes_opt (cp_parser* parser)
 {
   tree attributes = NULL_TREE;
 
@@ -20141,7 +20406,7 @@  cp_parser_attributes_opt (cp_parser* parser)
       token = cp_lexer_peek_token (parser->lexer);
       if (token->type != CPP_CLOSE_PAREN)
 	/* Parse the attribute-list.  */
-	attribute_list = cp_parser_attribute_list (parser);
+	attribute_list = cp_parser_gnu_attribute_list (parser);
       else
 	/* If the next token is a `)', then there is no attribute
 	   list.  */
@@ -20162,7 +20427,7 @@  cp_parser_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
-/* Parse an attribute-list.
+/* Parse a GNU attribute-list.
 
    attribute-list:
      attribute
@@ -20180,7 +20445,7 @@  cp_parser_attributes_opt (cp_parser* parser)
    the arguments, if any.  */
 
 static tree
-cp_parser_attribute_list (cp_parser* parser)
+cp_parser_gnu_attribute_list (cp_parser* parser)
 {
   tree attribute_list = NULL_TREE;
   bool save_translate_strings_p = parser->translate_strings_p;
@@ -20259,6 +20524,274 @@  cp_parser_attribute_list (cp_parser* parser)
   return nreverse (attribute_list);
 }
 
+/*  Parse a standard C++11 attribute.
+
+    The returned representation is a TREE_LIST which TREE_PURPOSE is
+    the scoped name of the attribute, and the TREE_VALUE is its
+    arguments list.
+
+    Note that the scoped name of the attribute is itself a TREE_LIST
+    which TREE_PURPOSE is the namespace of the attribute, and
+    TREE_VALUE its name.  This is unlike a GNU attribute -- as parsed
+    by cp_parser_gnu_attribute_list -- that doesn't have any namespace
+    and which TREE_PURPOSE is directly the attribute name.
+
+    Clients of the attribute code should use get_attribute_namespace
+    and get_attribute_name to get the actual namespace and name of
+    attributes, regardless of their being GNU or C++11 attributes.
+
+    attribute:
+      attribute-token attribute-argument-clause [opt]
+
+    attribute-token:
+      identifier
+      attribute-scoped-token
+
+    attribute-scoped-token:
+      attribute-namespace :: identifier
+
+    attribute-namespace:
+      identifier
+
+    attribute-argument-clause:
+      ( balanced-token-seq )
+
+    balanced-token-seq:
+      balanced-token [opt]
+      balanced-token-seq balanced-token
+
+    balanced-token:
+      ( balanced-token-seq )
+      [ balanced-token-seq ]
+      { balanced-token-seq }.  */
+
+static tree
+cp_parser_std_attribute (cp_parser *parser)
+{
+  tree attribute, attr_ns = NULL_TREE, attr_id, arguments;
+  cp_token *token;
+
+  /* First, parse name of the the attribute, a.k.a
+     attribute-token.  */
+
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type == CPP_NAME)
+    attr_id = token->u.value;
+  else if (token->type == CPP_KEYWORD)
+    attr_id = ridpointers[(int) token->keyword];
+  else
+    return NULL_TREE;
+  cp_lexer_consume_token (parser->lexer);
+
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type == CPP_SCOPE)
+    {
+      /* We are seeing a scoped attribute token.  */
+
+      cp_lexer_consume_token (parser->lexer);
+      attr_ns = attr_id;
+
+      token = cp_lexer_consume_token (parser->lexer);
+      if (token->type == CPP_NAME)
+	attr_id = token->u.value;
+      else if (token->type == CPP_KEYWORD)
+	attr_id = ridpointers[(int) token->keyword];
+      else
+	{
+	  error_at (token->location,
+		    "expected an identifier for the attribute name");
+	  return error_mark_node;
+	}
+      attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
+				   NULL_TREE);
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+  else
+    attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
+				 NULL_TREE);
+
+  /* Now parse the optional argument close of the attribute.  */
+
+  if (token->type != CPP_OPEN_PAREN)
+    return attribute;
+
+  {
+    VEC(tree, gc) *vec;
+    int attr_flag = attribute_takes_identifier_p (attr_id)
+      ? id_attr
+      : normal_attr;
+
+    vec = cp_parser_parenthesized_expression_list
+      (parser, attr_flag, /*cast_p=*/false,
+       /*allow_expansion_p=*/true,
+       /*non_constant_p=*/NULL);
+    if (vec == NULL)
+      arguments = error_mark_node;
+    else
+      {
+	arguments = build_tree_list_vec (vec);
+	release_tree_vector (vec);
+      }
+
+    if (arguments == error_mark_node)
+      attribute = error_mark_node;
+    else
+      TREE_VALUE (attribute) = arguments;
+  }
+
+  return attribute;
+}
+
+/* Parse a list of standard C++-11 attributes.
+
+   attribute-list:
+     attribute [opt]
+     attribute-list , attribute[opt]
+     attribute ...
+     attribute-list , attribute ...
+*/
+
+static tree
+cp_parser_std_attribute_list (cp_parser *parser)
+{
+  tree attributes = NULL_TREE, attribute = NULL_TREE;
+  cp_token *token = NULL;
+
+  while (true)
+    {
+      attribute = cp_parser_std_attribute (parser);
+      if (attribute == error_mark_node)
+	break;
+      if (attribute != NULL_TREE)
+	{
+	  TREE_CHAIN (attribute) = attributes;
+	  attributes = attribute;
+	}
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type != CPP_COMMA)
+	break;
+      cp_lexer_consume_token (parser->lexer);
+    }
+  attributes = nreverse (attributes);
+  return attributes;
+}
+
+/* Parse a standard C++-11 attribute specifier.
+
+   attribute-specifier:
+     [ [ attribute-list ] ]
+     alignment-specifier
+
+   alignment-specifier:
+     alignas ( type-id ... [opt] )
+     alignas ( alignment-expression ... [opt] ).  */
+
+static tree
+cp_parser_std_attribute_spec (cp_parser *parser)
+{
+  tree attributes = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->type == CPP_OPEN_SQUARE
+      && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_SQUARE)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      maybe_warn_cpp0x (CPP0X_ATTRIBUTES);
+      cp_lexer_consume_token (parser->lexer);
+
+      attributes = cp_parser_std_attribute_list (parser);
+
+      if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)
+	  || !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
+	cp_parser_skip_to_end_of_statement (parser);
+    }
+  else
+    {
+      tree alignas_expr;
+      bool complain = !cp_parser_uncommitted_to_tentative_parse_p (parser);
+
+      /* Look for an alignment-specifier.  */
+
+      token = cp_lexer_peek_token (parser->lexer);
+
+      if (token->type != CPP_KEYWORD
+	  || token->keyword != RID_ALIGNAS)
+	return NULL_TREE;
+
+      cp_lexer_consume_token (parser->lexer);
+      maybe_warn_cpp0x (CPP0X_ATTRIBUTES);
+
+      if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN) == NULL)
+	{
+	  cp_parser_error (parser, "expected %<(%>");
+	  return error_mark_node;
+	}
+
+      cp_parser_parse_tentatively (parser);
+      alignas_expr = cp_parser_type_id (parser);
+
+      if (!cp_parser_parse_definitely (parser))
+	{
+	  gcc_assert (alignas_expr == error_mark_node
+		      || alignas_expr == NULL_TREE);
+
+	  alignas_expr =
+	    cp_parser_assignment_expression (parser, /*cast_p=*/false,
+					     /**cp_id_kind=*/NULL);
+	  if (alignas_expr == NULL_TREE
+	      || alignas_expr == error_mark_node)
+	    return alignas_expr;
+	}
+
+      if (cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) == NULL)
+	{
+	  cp_parser_error (parser, "expected %<)%>");
+	  return error_mark_node;
+	}
+
+      alignas_expr =
+	cxx_alignas_expr (alignas_expr,
+			  complain ? tf_warning_or_error : tf_none);
+      alignas_expr = fold_non_dependent_expr (alignas_expr);
+
+      /* Build the C++-11 representation of an 'aligned'
+	 attribute.  */
+      attributes =
+	build_tree_list (build_tree_list (get_identifier ("gnu"),
+					  get_identifier ("aligned")),
+			 build_tree_list (NULL_TREE, alignas_expr));
+    }
+
+  return attributes;
+}
+
+/* Parse a standard C++-11 attribute-specifier-seq.
+
+   attribute-specifier-seq:
+     attribute-specifier-seq [opt] attribute-specifier
+ */
+
+static tree
+cp_parser_std_attribute_spec_seq (cp_parser *parser)
+{
+  tree attr_specs = NULL;
+
+  while (true)
+    {
+      tree attr_spec = cp_parser_std_attribute_spec (parser);
+      if (attr_spec == NULL_TREE)
+	break;
+      if (attr_spec == error_mark_node)
+	return error_mark_node;
+
+      TREE_CHAIN (attr_spec) = attr_specs;
+      attr_specs = attr_spec;
+    }
+
+  attr_specs = nreverse (attr_specs);
+  return attr_specs;
+}
+
 /* Parse an optional `__extension__' keyword.  Returns TRUE if it is
    present, and FALSE otherwise.  *SAVED_PEDANTIC is set to the
    current value of the PEDANTIC flag, regardless of whether or not
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ad81bab..2f21f04 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4942,7 +4942,7 @@  redeclare_class_template (tree type, tree parms)
 /* Simplify EXPR if it is a non-dependent expression.  Returns the
    (possibly simplified) expression.  */
 
-static tree
+tree
 fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
 {
   if (expr == NULL_TREE)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 25f37e8..c50e1d2 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1701,6 +1701,65 @@  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, tsubst_flags_t complain)
+{
+  if (e == NULL_TREE || e == error_mark_node)
+    return e;
+
+  if (processing_template_decl)
+    {
+      /* If E is a constant, fold it and return it right away.
+	 Otherwise, build an ALIGNOF_EXPR that will be substituted
+	 into, later at template instantiation time.  */
+      tree cst = TYPE_P (e) ? NULL_TREE : fold_non_dependent_expr_sfinae (e, tf_none);
+      if (cst != NULL && cst != error_mark_node)
+	return cst;
+      return cxx_alignof_expr (e, complain);
+    }
+
+  if (TYPE_P (e))
+    {
+      e = mark_type_use (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, 
+					 complain & tf_error
+					 || complain & tf_warning);
+    }
+
+  /* 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 = 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:
diff --git a/gcc/plugin.h b/gcc/plugin.h
index 4d2d12a..732c525 100644
--- a/gcc/plugin.h
+++ b/gcc/plugin.h
@@ -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 *,
+							     unsigned, const char *);
 
 #endif /* PLUGIN_H */
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
new file mode 100644
index 0000000..0f0ed8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
@@ -0,0 +1,3 @@ 
+// { dg-do compile { target c++11 } }
+
+int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "attribute only applies to function types" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C
new file mode 100644
index 0000000..cac568e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C
@@ -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 ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C
new file mode 100644
index 0000000..504b456
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C
@@ -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>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C
new file mode 100644
index 0000000..504b456
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C
@@ -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>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13-1.C
new file mode 100644
index 0000000..8fe5270
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13-1.C
@@ -0,0 +1,4 @@ 
+// { dg-do compile { target c++11 } }
+
+extern char *f (__const char, int) throw () [[gnu::__pure__]]; // { dg-warning "does not apply to types" }
+extern char *f (__const char *, int) throw () [[gnu::__pure__]]; // { dg-warning "does not apply to types" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C
new file mode 100644
index 0000000..a1b4a84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C
@@ -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 ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C
new file mode 100644
index 0000000..d646d27
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C
@@ -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); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C
new file mode 100644
index 0000000..bf05dbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C
@@ -0,0 +1,9 @@ 
+// { dg-do compile { target c++11 } }
+// PR c++/15317
+
+struct A
+{
+  A(char);
+};
+A::A([[gnu::unused]] char i2)
+{}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C
new file mode 100644
index 0000000..16080c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C
@@ -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))]];
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C
new file mode 100644
index 0000000..1e122b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C
new file mode 100644
index 0000000..8a5a798
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C
new file mode 100644
index 0000000..3df13e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C
@@ -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();
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C
new file mode 100644
index 0000000..5ac93d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C
new file mode 100644
index 0000000..8c777c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C
@@ -0,0 +1,11 @@ 
+// { dg-do compile { target c++11 } }
+
+struct [[gnu::packed]] A
+{
+  void f () const;
+};
+
+void
+A::f () const
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C
new file mode 100644
index 0000000..f989ab2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C
new file mode 100644
index 0000000..2a92821
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C
@@ -0,0 +1,21 @@ 
+// PR c++/20763
+// { dg-do compile { target c++11 } }
+
+typedef void *voidp;
+
+struct S
+{
+  char a;
+  voidp [[gnu::aligned (16)]] b;
+};
+
+struct T
+{
+  char a;
+  void * [[gnu::aligned (16)]] b;
+};
+
+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");
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
new file mode 100644
index 0000000..0101d84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
@@ -0,0 +1,7 @@ 
+// PR c++/27648
+// { dg-do compile { target c++11 } }
+
+void f()
+{
+  static_cast<float *[[gnu::unused]]>(0); // { dg-warning "cannot be applied to a type" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C
new file mode 100644
index 0000000..57ea6b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C
new file mode 100644
index 0000000..e1f26c3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C
@@ -0,0 +1,4 @@ 
+// PR c++/28387
+// { dg-do compile { target c++11 } }
+
+enum [[gnu::unused]] E;  // { dg-error "without previous declaration" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C
new file mode 100644
index 0000000..09486d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C
@@ -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" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C
new file mode 100644
index 0000000..00069b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C
@@ -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)
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C
new file mode 100644
index 0000000..e38d8d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C
new file mode 100644
index 0000000..94f1756
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C
@@ -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" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C
new file mode 100644
index 0000000..2817fa0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C
@@ -0,0 +1,10 @@ 
+// PR c++/33506
+// { dg-do compile { target c++11 } }
+
+extern int f1 (char *) [[gnu::warn_unused_result]];
+extern int f2 (char *) throw () [[gnu::warn_unused_result]];
+extern int f2 (char *) throw ();
+
+extern int f3 (char *) [[gnu::nonnull (1)]];
+extern int f4 (char *) throw () [[gnu::nonnull (1)]];
+extern int f4 (char *) throw ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C
new file mode 100644
index 0000000..3994787
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C
@@ -0,0 +1,21 @@ 
+// 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)]]
+
+attrib signed int a;
+static unsigned int attrib b;
+
+int foo(attrib int o)
+{
+  return (sizeof (a) != 1
+	  || sizeof (b) != 1
+	  || sizeof (o) != 1
+	  || sizeof ((attrib signed int) b) != 1);
+}
+
+int main ()
+{
+  return foo (42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C
new file mode 100644
index 0000000..bf229fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C
@@ -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 "ignoring attribute applying to missing declarator" }
+
+template<typename T> void A<T>::foo() const {}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C
new file mode 100644
index 0000000..ab58e6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C
new file mode 100644
index 0000000..0192909
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C
@@ -0,0 +1,37 @@ 
+// PR c++/35315
+// { dg-do compile { target c++11 } }
+
+typedef union { int i; } U [[gnu::transparent_union]]; // { dg-warning "applies to union types only" }
+
+static void foo(U) {}
+static void foo(int) {}
+
+void bar()
+{
+  foo(0);
+}
+
+typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "applies to union types only" }
+
+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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C
new file mode 100644
index 0000000..efb2a1a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C
new file mode 100644
index 0000000..ae8e990
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C
@@ -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" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C
new file mode 100644
index 0000000..34f20cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
new file mode 100644
index 0000000..fa32293
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
@@ -0,0 +1,13 @@ 
+// { dg-do compile { target c++11 } }
+
+struct S;
+
+typedef int (*F) (int) [[gnu::warn_unused_result]];
+
+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 (S::*F4) (int) [[gnu::warn_unused_result]];
+
+typedef int [[gnu::warn_unused_result]] (*F5) (int); // { dg-warning "only applies to function types" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C
new file mode 100644
index 0000000..2665188
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C
new file mode 100644
index 0000000..15d69e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C
@@ -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();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C
new file mode 100644
index 0000000..1a2469d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C
@@ -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 "applying to missing declarator" }
+};
+
+int main ()
+{
+  A<4>::S s;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
new file mode 100644
index 0000000..a190a80
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C
@@ -0,0 +1,10 @@ 
+// { dg-do compile { target c++11 } }
+
+int fragile_block(void) {
+  typedef 
+  [[gnu::aligned (16)]] // { dg-error "expected type specifier before attribute" }
+  struct  {
+    int i;
+  } XmmUint16;
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C
new file mode 100644
index 0000000..83fa8b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
new file mode 100644
index 0000000..78c9adb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -0,0 +1,39 @@ 
+// { dg-options "-std=c++11 -Wunused -pedantic-errors" }
+// { dg-do compile }
+// Test for syntax support of various attribute permutations.
+
+int
+[[gnu::noreturn]] // { dg-warning "does not apply to types" }
+one
+[[gnu::unused]]
+(void);
+
+int one_third [[gnu::noreturn]] [[gnu::unused]] (void);
+
+int [[gnu::unused]] one_half(); // { dg-warning "cannot be applied to a type" }
+
+static
+[[gnu::noreturn]] // { dg-error "expected type specifier before attribute" }
+void two [[gnu::unused]] (void) {}
+
+int
+three (void)
+[[gnu::noreturn]]; // { dg-warning "does not apply to types" }
+
+[[gnu::unused]]
+static
+void
+four (void) [[gnu::noreturn]] // { dg-warning "does not apply to types" }
+{ }
+
+
+[[gnu::unused]]
+int
+five(void)
+[[gnu::noreturn]] // { dg-warning "does not apply to types" }
+{}
+
+[[gnu::noreturn]]
+void
+six (void)
+;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C
new file mode 100644
index 0000000..f3ccb72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C
new file mode 100644
index 0000000..6e47a1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C
@@ -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;
+  }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C
new file mode 100644
index 0000000..7df63cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C
@@ -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" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
new file mode 100644
index 0000000..19501c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
@@ -0,0 +1,6 @@ 
+// { dg-do compile { target c++11 } }
+template <class T> struct A { };
+
+template
+[[gnu::packed]] // { dg-warning "ignoring attribute applying to missing declarator" }
+struct A<int>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C
new file mode 100644
index 0000000..788f02c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C
@@ -0,0 +1,3 @@ 
+// PR c++/52671
+// { dg-do compile { target c++11 } }
+[[gnu::deprecated]] enum E { E0 };	// { dg-warning "ignoring attribute applying to missing declarator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C
new file mode 100644
index 0000000..573a1ab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C
@@ -0,0 +1,4 @@ 
+// PR c++/52906
+// { dg-do compile { target c++11 } }
+
+[[gnu::deprecated]]; // { dg-error "does not declare anything" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C
new file mode 100644
index 0000000..53fcb77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C
@@ -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 "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C
new file mode 100644
index 0000000..af74abd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C
@@ -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" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C
new file mode 100644
index 0000000..360c093
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C
@@ -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)");
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C
new file mode 100644
index 0000000..8b68f92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C
@@ -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)");
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C
new file mode 100644
index 0000000..81b6207
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C
@@ -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];
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C
new file mode 100644
index 0000000..2479dfd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C
@@ -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)");
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C
new file mode 100644
index 0000000..f2b6602
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C
@@ -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");
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
new file mode 100644
index 0000000..68c798c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
@@ -0,0 +1,21 @@ 
+// { dg-do compile { target c++11 } }
+
+struct A {int i;} [[gnu::aligned(16)]] a;
+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");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
new file mode 100644
index 0000000..be597e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
@@ -0,0 +1,32 @@ 
+// { dg-do compile { target c++11 } }
+
+int
+foo ()
+{
+  [[gnu::unused]] good:
+    int i = 0;
+
+  // A C++11 attribute at the beginning of statement is syntactically
+  // correct, appertains to the 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;
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6-1.C
new file mode 100644
index 0000000..783a55c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6-1.C
@@ -0,0 +1,16 @@ 
+// Test that the nothrow attribute doesn't apply to types.
+// { dg-do link { target c++11} }
+
+extern void foo  () [[gnu::nothrow]]; // { dg-warning "attribute does not apply to types" }
+extern void link_error();
+
+int main()
+{
+  try {
+    foo();
+  } catch (...) {
+    link_error();
+  }
+}
+
+void foo() { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C
new file mode 100644
index 0000000..54071d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C
@@ -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() { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C
new file mode 100644
index 0000000..3341250
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C
@@ -0,0 +1,4 @@ 
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wunused-parameter" }
+
+void f (int i [[gnu::__unused__]]) {}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C
new file mode 100644
index 0000000..a842b53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C
@@ -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" }
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
new file mode 100644
index 0000000..3dc51ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
@@ -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" }
diff --git a/gcc/tree.c b/gcc/tree.c
index 655e03d..05e0207 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4352,7 +4352,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;
 
@@ -4366,7 +4366,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;
 
@@ -5289,11 +5289,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
@@ -5301,7 +5302,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)
@@ -5331,10 +5332,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
@@ -5344,11 +5346,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] == '_'
@@ -5357,7 +5359,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] == '_'
@@ -5387,7 +5389,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);
@@ -5424,9 +5426,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)
 		{
@@ -6348,7 +6352,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;
 }
 
@@ -6385,7 +6389,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))
     ;
@@ -6400,9 +6404,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)
diff --git a/gcc/tree.h b/gcc/tree.h
index b28f35a..adf7911 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4489,16 +4489,16 @@  extern tree build_type_attribute_qual_variant (tree, tree, int);
 extern int comp_type_attributes (const_tree, const_tree);
 
 /* Structure describing an attribute and a function to handle it.  */
-struct attribute_spec
+typedef 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
@@ -4506,15 +4506,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
@@ -4529,11 +4529,11 @@  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;
+} attribute_spec_t;
 
 /* Flags that may be passed in the third argument of decl_attributes, and
    to handler functions for attributes.  */
@@ -4557,7 +4557,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.  */
@@ -5643,6 +5645,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);
 
@@ -5656,6 +5660,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 */