public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
@ 2012-10-09 12:55 Dominique Dhumieres
  2012-10-09 13:48 ` Dodji Seketeli
  2012-10-10 14:32 ` Dodji Seketeli
  0 siblings, 2 replies; 22+ messages in thread
From: Dominique Dhumieres @ 2012-10-09 12:55 UTC (permalink / raw)
  To: gcc-patches; +Cc: dodji

Dodji,

The following tests are failing (with -m32):

FAIL: g++.dg/cpp0x/gen-attrs-36.C  (test for warnings, line 9)
FAIL: g++.dg/cpp0x/gen-attrs-36.C (test for excess errors)
FAIL: g++.dg/cpp0x/gen-attrs-37.C (test for excess errors)
FAIL: g++.dg/cpp0x/gen-attrs-8.C  (test for warnings, line 5)
FAIL: g++.dg/cpp0x/gen-attrs-8.C (test for excess errors)

TIA

Dominique

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-10-09 12:55 [PATCH] PR 53528 c++/ C++11 Generalized Attribute support Dominique Dhumieres
@ 2012-10-09 13:48 ` Dodji Seketeli
  2012-10-10 14:32 ` Dodji Seketeli
  1 sibling, 0 replies; 22+ messages in thread
From: Dodji Seketeli @ 2012-10-09 13:48 UTC (permalink / raw)
  To: Dominique Dhumieres; +Cc: gcc-patches

Hello Dominique,

dominiq@lps.ens.fr (Dominique Dhumieres) writes:

> The following tests are failing (with -m32):
>
> FAIL: g++.dg/cpp0x/gen-attrs-36.C  (test for warnings, line 9)
> FAIL: g++.dg/cpp0x/gen-attrs-36.C (test for excess errors)
> FAIL: g++.dg/cpp0x/gen-attrs-37.C (test for excess errors)
> FAIL: g++.dg/cpp0x/gen-attrs-8.C  (test for warnings, line 5)
> FAIL: g++.dg/cpp0x/gen-attrs-8.C (test for excess errors)

Thank you for the heads-up.  I am currently testing a patch for these.

Sorry for the inconvenience.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-10-09 12:55 [PATCH] PR 53528 c++/ C++11 Generalized Attribute support Dominique Dhumieres
  2012-10-09 13:48 ` Dodji Seketeli
@ 2012-10-10 14:32 ` Dodji Seketeli
  1 sibling, 0 replies; 22+ messages in thread
From: Dodji Seketeli @ 2012-10-10 14:32 UTC (permalink / raw)
  To: Dominique Dhumieres; +Cc: gcc-patches

dominiq@lps.ens.fr (Dominique Dhumieres) a écrit:

> The following tests are failing (with -m32):
>
> FAIL: g++.dg/cpp0x/gen-attrs-36.C  (test for warnings, line 9)
> FAIL: g++.dg/cpp0x/gen-attrs-36.C (test for excess errors)
> FAIL: g++.dg/cpp0x/gen-attrs-37.C (test for excess errors)
> FAIL: g++.dg/cpp0x/gen-attrs-8.C  (test for warnings, line 5)
> FAIL: g++.dg/cpp0x/gen-attrs-8.C (test for excess errors)

These should now be fixed in trunk by revision r192300.

Cheers.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-10-06  8:53                       ` Dodji Seketeli
  2012-10-07 20:44                         ` Jason Merrill
@ 2012-10-12 17:18                         ` Andreas Schwab
  1 sibling, 0 replies; 22+ messages in thread
From: Andreas Schwab @ 2012-10-12 17:18 UTC (permalink / raw)
  To: Dodji Seketeli
  Cc: Jason Merrill, Joseph S. Myers, Richard Henderson, GCC Patches

Dodji Seketeli <dodji@redhat.com> writes:

> 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..0f87fd4
> --- /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;}  a [[gnu::aligned(16)]];
> +struct B {int i;} __attribute__((aligned(16))) b;
> +
> +int
> +main ()
> +{
> + A aa;
> + B bb;
> +
> + static_assert (sizeof (a) == 4, "sizeof (a) should be 4");
> + static_assert (sizeof (b) == 16, "sizeof (b) should be 16");
> + static_assert (sizeof (aa) == 4, "sizeof (aa) should be 4");
> + static_assert (sizeof (bb) == 16, "sizeof (bb) should be 16");
> +
> + static_assert (__alignof__  (a) == 16, "alignof (a) should be 16");
> + static_assert (__alignof__  (b) == 16, "alignof (b) should be 16");
> + static_assert (__alignof__  (aa) == 4, "alignof (aa) should be 4");
> + static_assert (__alignof__  (bb) == 16, "alignof (bb) should be 16");
> +}

This fails on m68k.

Andreas.

	* g++.dg/cpp0x/gen-attrs-52.C: Allow alignment of aa to be less
	than 4.
---
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
index 0f87fd4..08906aa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C
@@ -16,6 +16,6 @@ main ()
 
  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__  (aa) <= 4, "alignof (aa) should be <=4");
  static_assert (__alignof__  (bb) == 16, "alignof (bb) should be 16");
 }
-- 
1.7.12.3

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-10-07 20:44                         ` Jason Merrill
@ 2012-10-08 12:12                           ` Dodji Seketeli
  0 siblings, 0 replies; 22+ messages in thread
From: Dodji Seketeli @ 2012-10-08 12:12 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> OK.

Thanks.  Committed to trunk at revision r192199.

-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-10-06  8:53                       ` Dodji Seketeli
@ 2012-10-07 20:44                         ` Jason Merrill
  2012-10-08 12:12                           ` Dodji Seketeli
  2012-10-12 17:18                         ` Andreas Schwab
  1 sibling, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2012-10-07 20:44 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

OK.

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-10-04 21:43                     ` Jason Merrill
@ 2012-10-06  8:53                       ` Dodji Seketeli
  2012-10-07 20:44                         ` Jason Merrill
  2012-10-12 17:18                         ` Andreas Schwab
  0 siblings, 2 replies; 22+ messages in thread
From: Dodji Seketeli @ 2012-10-06  8:53 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

Jason Merrill <jason@redhat.com> writes:

> On 09/20/2012 02:59 AM, Dodji Seketeli wrote:
> >>> +      if ((flags & ATTR_FLAG_CXX11)
> >>> +	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE
> >>> +	       && (TREE_CODE (*node) == RECORD_TYPE
> >>> +		   || TREE_CODE (*node) == UNION_TYPE)))
> >>> +	{
> >>> +	  /* unused is being used as a c++11 attribute.  In this mode
> >>> +	     we prevent it from applying to types, unless it's for a
> >>> +	     class defintion.  */
> >>> +	  warning (OPT_Wattributes,
> >>> +		   "attribute %qE cannot be applied to a non-class type", name);
> >>> +	  return NULL_TREE;
> >>> +	}
> >>
> >> I think this should now be covered by the general ignoring of
> >> attributes that appertain to type-specifiers, so we don't need to
> >> check it here.
> >
> > Removed.
> 
> Looks to me like it's still there.

Right, oops.  Looks like I forgot to commit that hunk.  It's hopefully
done now.

> 
> > +    int attr_flag = attribute_takes_identifier_p (attr_id)
> > +      ? id_attr
> > +      : normal_attr;
> 
> This should only apply to attributes in the gnu namespace.

Fixed.

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.
	* tree.c (comp_type_attributes, private_lookup_attribute)
	(lookup_ident_attribute, remove_attribute, merge_attribute)
	(attribute_hash_list, attribute_list_contained): Use
	get_attribute_name.
	* attribs.c (decl_attributes): Don't crash on error_mark_node.
	Forbid c++11 attributes appertaining to type-specifiers.
	(attribute_hash): Remove global variable.
	(attributes_table): New global variable.
	(find_attribute_namespace, register_scoped_attribute): New static
	functions.
	(register_scoped_attributes, lookup_scoped_attribute_spec)
	(cxx11_attribute_p, get_attribute_name, get_attribute_namespace):
	New public functions.
	(init_attributes): Register all the GNU attributes into the "gnu"
	namespace.
	(register_attribute): Use register_scoped_attribute to register
	the attribute into the "gnu" namespace.
	(lookup_attribute_spec): Use lookup_scoped_attribute_spec to
	lookup the attribute in the "gnu" namespace.
	(decl_attributes): Use new get_attribute_namespace and
	lookup_scoped_attribute_spec to consider attribute namespaces when
	looking up attributes.  When operating in c++-11 mode, pass flag
	ATTR_FLAG_CXX11 to the spec handler.

gcc/c-family/

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

gcc/cp/

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

gcc/testsuite/

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

WIP address last review comments
---
 gcc/attribs.c                               | 229 +++++++++-
 gcc/c-family/c-common.c                     | 120 ++++-
 gcc/c-family/c-common.h                     |   1 +
 gcc/cp/cp-tree.h                            |  20 +-
 gcc/cp/decl.c                               |  85 +++-
 gcc/cp/decl2.c                              |   2 +-
 gcc/cp/error.c                              |   5 +
 gcc/cp/parser.c                             | 660 ++++++++++++++++++++++++----
 gcc/cp/typeck.c                             |  50 +++
 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.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-1.C  |   3 +
 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    |  22 +
 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 |  11 +
 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    |  30 ++
 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   |   4 +
 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-1.C |   8 +
 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   |  39 ++
 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                                  |  30 +-
 70 files changed, 1900 insertions(+), 137 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.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-1.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-1.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.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

diff --git a/gcc/attribs.c b/gcc/attribs.c
index d3af414..0577bc6 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);
+DEF_VEC_ALLOC_O (attribute_spec, heap);
+
+/* Scoped attribute name representation.  */
+
+struct scoped_attributes
+{
+  const char *ns;
+  VEC (attribute_spec, heap) *attributes;
+  htab_t attribute_hash;
+};
+
+DEF_VEC_O (scoped_attributes);
+DEF_VEC_ALLOC_O (scoped_attributes, heap);
+
+/* The table of scope attributes.  */
+static VEC(scoped_attributes, heap) *attributes_table;
+
+static scoped_attributes* find_attribute_namespace (const char*);
+static void register_scoped_attribute (const struct attribute_spec *,
+				       scoped_attributes *);
+
 static bool attributes_initialized = false;
 
 /* Default empty table of attributes.  */
@@ -102,6 +121,64 @@ eq_attr (const void *p, const void *q)
   return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]);
 }
 
+/* Insert an array of attributes ATTRIBUTES into a namespace.  This
+   array must be NULL terminated.  NS is the name of attribute
+   namespace.  The function returns the namespace into which the
+   attributes have been registered.  */
+
+scoped_attributes*
+register_scoped_attributes (const struct attribute_spec * attributes,
+			    const char* ns)
+{
+  scoped_attributes *result = NULL;
+
+  /* See if we already have attributes in the namespace NS.  */
+  result = find_attribute_namespace (ns);
+
+  if (result == NULL)
+    {
+      /* We don't have any namespace NS yet.  Create one.  */
+      scoped_attributes sa;
+
+      if (attributes_table == NULL)
+	attributes_table = VEC_alloc (scoped_attributes, heap, 64);
+
+      memset (&sa, 0, sizeof (sa));
+      sa.ns = ns;
+      sa.attributes = VEC_alloc (attribute_spec, heap, 64);
+      result = VEC_safe_push (scoped_attributes, heap, attributes_table, sa);      
+    }
+
+  /* Really add the attributes to their namespace now.  */
+  for (unsigned i = 0; attributes[i].name != NULL; ++i)
+    {
+      VEC_safe_push (attribute_spec, heap,
+		     result->attributes, attributes[i]);
+      register_scoped_attribute (&attributes[i], result);
+    }
+
+  gcc_assert (result != NULL);
+
+  return result;
+}
+
+/* Return the namespace which name is NS, NULL if none exist.  */
+
+static scoped_attributes*
+find_attribute_namespace (const char* ns)
+{
+  unsigned ix;
+  scoped_attributes *iter;
+
+  FOR_EACH_VEC_ELT (scoped_attributes, attributes_table, ix, iter)
+    if (ns == iter->ns
+	|| (iter->ns != NULL
+	    && ns != NULL
+	    && !strcmp (iter->ns, ns)))
+      return iter;
+  return NULL;
+}
+
 /* Initialize attribute tables, and make some sanity checks
    if --enable-checking.  */
 
@@ -109,7 +186,6 @@ void
 init_attributes (void)
 {
   size_t i;
-  int k;
 
   if (attributes_initialized)
     return;
@@ -181,12 +257,10 @@ init_attributes (void)
     }
 #endif
 
-  attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
-  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
-    for (k = 0; attribute_tables[i][k].name != NULL; k++)
-      {
-        register_attribute (&attribute_tables[i][k]);
-      }
+  for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
+    /* Put all the GNU attributes into the "gnu" namespace.  */
+    register_scoped_attributes (attribute_tables[i], "gnu");
+
   invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
   attributes_initialized = true;
 }
@@ -196,9 +270,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 *name_space)
+{
   struct substring str;
   void **slot;
 
+  gcc_assert (attr != NULL && name_space != NULL);
+
+  if (name_space->attribute_hash == NULL)
+   name_space->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
+
   str.str = attr->name;
   str.length = strlen (str.str);
 
@@ -206,27 +294,45 @@ register_attribute (const struct attribute_spec *attr)
      in the form '__text__'.  */
   gcc_assert (str.length > 0 && str.str[0] != '_');
 
-  slot = htab_find_slot_with_hash (attribute_hash, &str,
+  slot = htab_find_slot_with_hash (name_space->attribute_hash, &str,
 				   substring_hash (str.str, str.length),
 				   INSERT);
   gcc_assert (!*slot || attr->name[0] == '*');
   *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
 }
 
-/* Return the spec for the 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 *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);
+}
+
 \f
 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
    which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
@@ -243,7 +349,7 @@ decl_attributes (tree *node, tree attributes, int flags)
   tree a;
   tree returned_attrs = NULL_TREE;
 
-  if (TREE_TYPE (*node) == error_mark_node)
+  if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
     return NULL_TREE;
 
   if (!attributes_initialized)
@@ -302,10 +408,12 @@ decl_attributes (tree *node, tree attributes, int flags)
 
   for (a = attributes; a; a = TREE_CHAIN (a))
     {
-      tree name = TREE_PURPOSE (a);
+      tree ns = get_attribute_namespace (a);
+      tree name = get_attribute_name (a);
       tree args = TREE_VALUE (a);
       tree *anode = node;
-      const struct attribute_spec *spec = lookup_attribute_spec (name);
+      const struct attribute_spec *spec =
+	lookup_scoped_attribute_spec (ns, name);
       bool no_add_attrs = 0;
       int fn_ptr_quals = 0;
       tree fn_ptr_tmp = NULL_TREE;
@@ -313,8 +421,15 @@ decl_attributes (tree *node, tree attributes, int flags)
       if (spec == NULL)
 	{
 	  if (!(flags & (int) ATTR_FLAG_BUILT_IN))
-	    warning (OPT_Wattributes, "%qE attribute directive ignored",
-		     name);
+	    {
+	      if (ns == NULL_TREE || !cxx11_attribute_p (a))
+		warning (OPT_Wattributes, "%qE attribute directive ignored",
+			 name);
+	      else
+		warning (OPT_Wattributes,
+			 "%<%E::%E%> scoped attribute directive ignored",
+			 ns, name);
+	    }
 	  continue;
 	}
       else if (list_length (args) < spec->min_length
@@ -327,6 +442,20 @@ decl_attributes (tree *node, tree attributes, int flags)
 	}
       gcc_assert (is_attribute_p (spec->name, name));
 
+      if (TYPE_P (*node)
+	  && cxx11_attribute_p (a)
+	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
+	{
+	  /* This is a c++11 attribute that appertain to a type-specifier,
+	     outside of the definition of, a class type.  Ignore
+	     it.  */
+	  warning (OPT_Wattributes, "attribute ignored");
+	  inform (input_location,
+		  "an attribute that appertains to a type-specifier "
+		  "is ignored");
+	  continue;
+	}
+
       if (spec->decl_required && !DECL_P (*anode))
 	{
 	  if (flags & ((int) ATTR_FLAG_DECL_NEXT
@@ -406,9 +535,15 @@ decl_attributes (tree *node, tree attributes, int flags)
 	}
 
       if (spec->handler != NULL)
-	returned_attrs = chainon ((*spec->handler) (anode, name, args,
-						    flags, &no_add_attrs),
-				  returned_attrs);
+	{
+	  int cxx11_flag =
+	    cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
+
+	  returned_attrs = chainon ((*spec->handler) (anode, name, args,
+						      flags|cxx11_flag,
+						      &no_add_attrs),
+				    returned_attrs);
+	}
 
       /* Layout the decl in case anything changed.  */
       if (spec->type_required && DECL_P (*node)
@@ -488,6 +623,56 @@ decl_attributes (tree *node, tree attributes, int flags)
   return returned_attrs;
 }
 
+/* Return TRUE iff ATTR has been parsed by the front-end as a C++-11
+   attribute.
+
+   When G++ parses a C++11 attribute, it is represented as
+   a TREE_LIST which TREE_PURPOSE is itself a TREE_LIST.  TREE_PURPOSE
+   (TREE_PURPOSE (ATTR)) is the namespace of the attribute, and the
+   TREE_VALUE (TREE_PURPOSE (ATTR)) is its non-qualified name.  Please
+   use get_attribute_namespace and get_attribute_name to retrieve the
+   namespace and name of the attribute, as these accessors work with
+   GNU attributes as well.  */
+
+bool
+cxx11_attribute_p (const_tree attr)
+{
+  if (attr == NULL_TREE
+      || TREE_CODE (attr) != TREE_LIST)
+    return false;
+
+  return (TREE_CODE (TREE_PURPOSE (attr)) == TREE_LIST);
+}
+
+/* Return the name of the attribute ATTR.  This accessor works on GNU
+   and C++11 (scoped) attributes.
+
+   Please read the comments of cxx11_attribute_p to understand the
+   format of attributes.  */
+
+tree
+get_attribute_name (const_tree attr)
+{
+  if (cxx11_attribute_p (attr))
+    return TREE_VALUE (TREE_PURPOSE (attr));
+  return TREE_PURPOSE (attr);
+}
+
+/* Return the namespace of the attribute ATTR.  This accessor works on
+   GNU and C++11 (scoped) attributes.  On GNU attributes,
+   it returns an identifier tree for the string "gnu".
+
+   Please read the comments of cxx11_attribute_p to understand the
+   format of attributes.  */
+
+tree
+get_attribute_namespace (const_tree attr)
+{
+  if (cxx11_attribute_p (attr))
+    return TREE_PURPOSE (TREE_PURPOSE (attr));
+  return get_identifier ("gnu");
+}
+
 /* Subroutine of set_method_tm_attributes.  Apply TM attribute ATTR
    to the method FNDECL.  */
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 6de2f1c..e242789 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -484,6 +484,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
   { "__volatile",	RID_VOLATILE,	0 },
   { "__volatile__",	RID_VOLATILE,	0 },
+  { "alignas",		RID_ALIGNAS,	D_CXXONLY | D_CXX0X | D_CXXWARN },
   { "alignof",		RID_ALIGNOF,	D_CXXONLY | D_CXX0X | D_CXXWARN },
   { "asm",		RID_ASM,	D_ASM },
   { "auto",		RID_AUTO,	0 },
@@ -6665,7 +6666,9 @@ handle_transparent_union_attribute (tree *node, tree name,
 
   *no_add_attrs = true;
 
-  if (TREE_CODE (*node) == TYPE_DECL)
+
+  if (TREE_CODE (*node) == TYPE_DECL
+      && ! (flags & ATTR_FLAG_CXX11))
     node = &TREE_TYPE (*node);
   type = *node;
 
@@ -7137,6 +7140,89 @@ check_user_alignment (const_tree align, bool allow_zero)
   return i;
 }
 
+/* 
+   If in c++-11, check if the c++-11 alignment constraint with respect
+   to fundamental alignment (in [dcl.align]) are satisfied.  If not in
+   c++-11 mode, does nothing.
+
+   [dcl.align]2/ says:
+
+   [* if the constant expression evaluates to a fundamental alignment,
+   the alignment requirement of the declared entity shall be the
+   specified fundamental alignment.
+
+   * if the constant expression evaluates to an extended alignment
+   and the implementation supports that alignment in the context
+   of the declaration, the alignment of the declared entity shall
+   be that alignment
+
+   * if the constant expression evaluates to an extended alignment
+   and the implementation does not support that alignment in the
+   context of the declaration, the program is ill-formed].  */
+
+static bool
+check_cxx_fundamental_alignment_constraints (tree node,
+					     unsigned align_log,
+					     int flags)
+{
+  bool alignment_too_large_p = false;
+  unsigned requested_alignment = 1U << align_log;
+  unsigned max_align = 0;
+
+  if ((!(flags & ATTR_FLAG_CXX11) && !warn_cxx_compat)
+      || (node == NULL_TREE || node == error_mark_node))
+    return true;
+
+  if (cxx_fundamental_alignment_p (requested_alignment))
+    return true;
+
+  if (DECL_P (node))
+    {
+      if (TREE_STATIC (node))
+	{
+	  /* For file scope variables and static members, the target
+	     supports alignments that are at most
+	     MAX_OFILE_ALIGNMENT.  */
+	  if (requested_alignment > (max_align = MAX_OFILE_ALIGNMENT))
+	    alignment_too_large_p = true;
+	}
+      else
+	{
+#ifdef BIGGEST_FIELD_ALIGNMENT
+#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_FIELD_ALIGNMENT
+#else
+#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_ALIGNMENT
+#endif
+	  /* For non-static members, the target supports either
+	     alignments that at most either BIGGEST_FIELD_ALIGNMENT
+	     if it is defined or BIGGEST_ALIGNMENT.  */
+	  max_align = MAX_TARGET_FIELD_ALIGNMENT;
+	  if (TREE_CODE (node) == FIELD_DECL
+	      && requested_alignment > (max_align = MAX_TARGET_FIELD_ALIGNMENT))
+	    alignment_too_large_p = true;
+#undef MAX_TARGET_FIELD_ALIGNMENT
+	  /* For stack variables, the target supports at most
+	     MAX_STACK_ALIGNMENT.  */
+	  else if (decl_function_context (node) != NULL
+		   && requested_alignment > (max_align = MAX_STACK_ALIGNMENT))
+	    alignment_too_large_p = true;
+	}
+    }
+  else if (TYPE_P (node))
+    {
+      /* Let's be liberal for types.  */
+      if (requested_alignment > (max_align = BIGGEST_ALIGNMENT))
+	alignment_too_large_p = true;
+    }
+
+  if (alignment_too_large_p)
+    pedwarn (input_location, OPT_Wattributes,
+	     "requested alignment %d is larger than %d",
+	     requested_alignment, max_align);
+
+  return !alignment_too_large_p;
+}
+
 /* Handle a "aligned" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -7160,7 +7246,8 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   else if (TYPE_P (*node))
     type = node, is_type = 1;
 
-  if ((i = check_user_alignment (align_expr, false)) == -1)
+  if ((i = check_user_alignment (align_expr, false)) == -1
+      || !check_cxx_fundamental_alignment_constraints (*node, i, flags))
     *no_add_attrs = true;
   else if (is_type)
     {
@@ -7190,6 +7277,17 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       error ("alignment may not be specified for %q+D", decl);
       *no_add_attrs = true;
     }
+  else if (DECL_USER_ALIGN (decl)
+	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
+    /* C++-11 [dcl.align/4]:
+
+           When multiple alignment-specifiers are specified for an
+	   entity, the alignment requirement shall be set to the
+	   strictest specified alignment.
+
+      This formally comes from the c++11 specification but we are
+      doing it for the GNU attribute syntax as well.  */
+    *no_add_attrs = true;
   else if (TREE_CODE (decl) == FUNCTION_DECL
 	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
     {
@@ -11154,4 +11252,22 @@ convert_vector_to_pointer_for_subscript (location_t loc,
     }
 }
 
+/* Return true iff ALIGN is an integral constant that is a fundamental
+   alignment, as defined by [basic.align] in the c++-11
+   specifications.
+
+   That is:
+
+       [A fundamental alignment is represented by an alignment less than or
+        equal to the greatest alignment supported by the implementation
+        in all contexts, which is equal to
+        alignof(max_align_t)].  */
+
+bool
+cxx_fundamental_alignment_p  (unsigned align)
+{
+  return (align <=  MAX (TYPE_ALIGN (long_long_integer_type_node),
+			 TYPE_ALIGN (long_double_type_node)));
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index cefe92d..5b23bd3 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -789,6 +789,7 @@ extern bool keyword_begins_type_specifier (enum rid);
 extern bool keyword_is_storage_class_specifier (enum rid);
 extern bool keyword_is_type_qualifier (enum rid);
 extern bool keyword_is_decl_specifier (enum rid);
+extern bool cxx_fundamental_alignment_p (unsigned);
 
 #define c_sizeof(LOC, T)  c_sizeof_or_alignof_type (LOC, T, true, 1)
 #define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bfe7ad7..6827fa6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -417,7 +417,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. */
@@ -4679,6 +4681,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.  */
@@ -4697,6 +4700,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;
@@ -4765,8 +4770,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;
@@ -5063,7 +5074,9 @@ extern tree build_cp_library_fn_ptr		(const char *, tree);
 extern tree push_library_fn			(tree, tree, tree);
 extern tree push_void_library_fn		(tree, tree);
 extern tree push_throw_library_fn		(tree, tree);
-extern tree check_tag_decl			(cp_decl_specifier_seq *);
+extern void warn_misplaced_attr_for_class_type  (source_location location,
+						 tree class_type);
+extern tree check_tag_decl			(cp_decl_specifier_seq *, bool);
 extern tree shadow_tag				(cp_decl_specifier_seq *);
 extern tree groktypename			(cp_decl_specifier_seq *, const cp_declarator *, bool);
 extern tree start_decl				(const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
@@ -5824,6 +5837,7 @@ extern int comp_cv_qualification		(const_tree, const_tree);
 extern int comp_cv_qual_signature		(tree, tree);
 extern tree cxx_sizeof_or_alignof_expr		(tree, enum tree_code, bool);
 extern tree cxx_sizeof_or_alignof_type		(tree, enum tree_code, bool);
+extern tree cxx_alignas_expr                    (tree);
 extern tree cxx_sizeof_nowarn                   (tree);
 extern tree is_bitfield_expr_with_lowered_type  (const_tree);
 extern tree unlowered_expr_type                 (const_tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d0933ef..d6e0b60 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4131,13 +4131,32 @@ fixup_anonymous_aggr (tree t)
     }
 }
 
+/* Warn for an attribute located at LOCATION that appertains to the
+   class type CLASS_TYPE that has not been properly placed after its
+   class-key, in it class-specifier.  */
+
+void
+warn_misplaced_attr_for_class_type (source_location location,
+				    tree class_type)
+{
+  gcc_assert (TAGGED_TYPE_P (class_type));
+
+  warning_at (location, OPT_Wattributes,
+	      "attribute ignored in declaration "
+	      "of %q#T", class_type);
+  inform (location,
+	  "attribute for %q#T must follow the %qs keyword",
+	  class_type, class_key_or_enum_as_string (class_type));
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
    just declares a tagged type or anonymous union.
 
    Returns the type declared; or NULL_TREE if none.  */
 
 tree
-check_tag_decl (cp_decl_specifier_seq *declspecs)
+check_tag_decl (cp_decl_specifier_seq *declspecs,
+		bool explicit_type_instantiation_p)
 {
   int saw_friend = decl_spec_seq_has_spec_p (declspecs, ds_friend);
   int saw_typedef = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
@@ -4246,10 +4265,22 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
 	/* For a template class (an explicit instantiation), use the
 	   current location.  */
 	loc = input_location;
-      warning_at (loc, OPT_Wattributes, "attribute ignored in declaration "
-		  "of %q#T", declared_type);
-      inform (loc, "attribute for %q#T must follow the %qs keyword",
-	      declared_type, class_key_or_enum_as_string (declared_type));
+
+      if (explicit_type_instantiation_p)
+	/* [dcl.attr.grammar]/4:
+
+	       No attribute-specifier-seq shall appertain to an explicit
+	       instantiation.  */
+	{
+	  warning_at (loc, OPT_Wattributes,
+		      "attribute ignored in explicit instantiation %q#T",
+		      declared_type);
+	  inform (loc,
+		  "no attribute can be applied to "
+		  "an explicit instantiation");
+	}
+      else
+	warn_misplaced_attr_for_class_type (loc, declared_type);
     }
 
   return declared_type;
@@ -4271,7 +4302,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
 tree
 shadow_tag (cp_decl_specifier_seq *declspecs)
 {
-  tree t = check_tag_decl (declspecs);
+  tree t = check_tag_decl (declspecs,
+			   /*explicit_type_instantiation_p=*/false);
 
   if (!t)
     return NULL_TREE;
@@ -9134,6 +9166,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)
@@ -9171,6 +9212,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:
@@ -9367,6 +9415,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;
 
@@ -9529,6 +9584,17 @@ grokdeclarator (const cp_declarator *declarator,
 					   declarator->u.pointer.qualifiers);
 	      type_quals = cp_type_quals (type);
 	    }
+
+	  /* Apply C++11 attributes to the pointer, and not to the
+	     type pointed to.  This is unlike what is done for GNU
+	     attributes above.  It is to comply with [dcl.ptr]/1:
+
+		 [the optional attribute-specifier-seq (7.6.1) appertains
+		  to the pointer and not to the object pointed to].  */
+	  if (declarator->std_attributes)
+	    decl_attributes (&type, declarator->std_attributes,
+			     0);
+
 	  ctype = NULL_TREE;
 	  break;
 
@@ -9654,6 +9720,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 9b1a5a1..ae115dc 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 c8b614b..62a30c4 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3372,6 +3372,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 155b51a..acc6822 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1197,13 +1197,13 @@ static cp_declarator *make_call_declarator
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
-  (cp_cv_quals, cp_declarator *);
+  (cp_cv_quals, cp_declarator *, tree);
 static cp_declarator *make_reference_declarator
-  (cp_cv_quals, cp_declarator *, bool);
+  (cp_cv_quals, cp_declarator *, bool, tree);
 static cp_parameter_declarator *make_parameter_declarator
   (cp_decl_specifier_seq *, cp_declarator *, tree);
 static cp_declarator *make_ptrmem_declarator
-  (cp_cv_quals, tree, cp_declarator *);
+  (cp_cv_quals, tree, cp_declarator *, tree);
 
 /* An erroneous declarator.  */
 static cp_declarator *cp_error_declarator;
@@ -1231,6 +1231,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;
@@ -1277,10 +1278,12 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name,
 
 /* Make a declarator for a pointer to TARGET.  CV_QUALIFIERS is a list
    of modifiers such as const or volatile to apply to the pointer
-   type, represented as identifiers.  */
+   type, represented as identifiers.  ATTRIBUTES represent the attributes that
+   appertain to the pointer or reference.  */
 
 cp_declarator *
-make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
+make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
+			 tree attributes)
 {
   cp_declarator *declarator;
 
@@ -1297,14 +1300,18 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
   else
     declarator->parameter_pack_p = false;
 
+  declarator->std_attributes = attributes;
+
   return declarator;
 }
 
-/* Like make_pointer_declarator -- but for references.  */
+/* Like make_pointer_declarator -- but for references.  ATTRIBUTES
+   represent the attributes that appertain to the pointer or
+   reference.  */
 
 cp_declarator *
 make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
-			   bool rvalue_ref)
+			   bool rvalue_ref, tree attributes)
 {
   cp_declarator *declarator;
 
@@ -1321,15 +1328,19 @@ make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
   else
     declarator->parameter_pack_p = false;
 
+  declarator->std_attributes = attributes;
+
   return declarator;
 }
 
 /* Like make_pointer_declarator -- but for a pointer to a non-static
-   member of CLASS_TYPE.  */
+   member of CLASS_TYPE.  ATTRIBUTES represent the attributes that
+   appertain to the pointer or reference.  */
 
 cp_declarator *
 make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
-			cp_declarator *pointee)
+			cp_declarator *pointee,
+			tree attributes)
 {
   cp_declarator *declarator;
 
@@ -1346,6 +1357,8 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
   else
     declarator->parameter_pack_p = false;
 
+  declarator->std_attributes = attributes;
+
   return declarator;
 }
 
@@ -1853,7 +1866,7 @@ static void cp_parser_lambda_body
 static void cp_parser_statement
   (cp_parser *, tree, bool, bool *);
 static void cp_parser_label_for_labeled_statement
-  (cp_parser *);
+(cp_parser *, tree);
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
@@ -1957,7 +1970,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
@@ -2099,9 +2112,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 *);
@@ -2308,7 +2341,7 @@ static bool cp_parser_is_keyword
 static tree cp_parser_make_typename_type
   (cp_parser *, tree, tree, location_t location);
 static cp_declarator * cp_parser_make_indirect_declarator
-  (enum tree_code, tree, cp_cv_quals, cp_declarator *);
+ (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree);
 
 /* Returns nonzero if we are parsing tentatively.  */
 
@@ -3178,24 +3211,30 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope,
    make_{pointer,ptrmem,reference}_declarator functions that decides
    which one to call based on the CODE and CLASS_TYPE arguments. The
    CODE argument should be one of the values returned by
-   cp_parser_ptr_operator. */
+   cp_parser_ptr_operator.  ATTRIBUTES represent the attributes that
+   appertain to the pointer or reference.  */
+
 static cp_declarator *
 cp_parser_make_indirect_declarator (enum tree_code code, tree class_type,
 				    cp_cv_quals cv_qualifiers,
-				    cp_declarator *target)
+				    cp_declarator *target,
+				    tree attributes)
 {
   if (code == ERROR_MARK)
     return cp_error_declarator;
 
   if (code == INDIRECT_REF)
     if (class_type == NULL_TREE)
-      return make_pointer_declarator (cv_qualifiers, target);
+      return make_pointer_declarator (cv_qualifiers, target, attributes);
     else
-      return make_ptrmem_declarator (cv_qualifiers, class_type, target);
+      return make_ptrmem_declarator (cv_qualifiers, class_type,
+				     target, attributes);
   else if (code == ADDR_EXPR && class_type == NULL_TREE)
-    return make_reference_declarator (cv_qualifiers, target, false);
+    return make_reference_declarator (cv_qualifiers, target,
+				      false, attributes);
   else if (code == NON_LVALUE_EXPR && class_type == NULL_TREE)
-    return make_reference_declarator (cv_qualifiers, target, true);
+    return make_reference_declarator (cv_qualifiers, target,
+				      true, attributes);
   gcc_unreachable ();
 }
 
@@ -5605,6 +5644,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,
@@ -6850,13 +6896,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))
     {
@@ -6865,8 +6911,10 @@ 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
-	(code, type, cv_quals, declarator);
+      declarator = cp_parser_make_indirect_declarator
+	(code, type, cv_quals, declarator, std_attributes);
+
+      return declarator;
     }
 
   /* If the next token is a `[', there is a direct-new-declarator.  */
@@ -8605,6 +8653,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:
@@ -8621,15 +8681,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.  */
@@ -8647,7 +8712,7 @@ 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.  */
-	  cp_parser_label_for_labeled_statement (parser);
+	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  goto restart;
 
 	case RID_IF:
@@ -8710,7 +8775,8 @@ 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.  */
-	  cp_parser_label_for_labeled_statement (parser);
+
+	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  goto restart;
 	}
     }
@@ -8746,6 +8812,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);
@@ -8760,6 +8834,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.
@@ -8776,7 +8857,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
    have to return the label.  */
 
 static void
-cp_parser_label_for_labeled_statement (cp_parser* parser)
+cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
 {
   cp_token *token;
   tree label = NULL_TREE;
@@ -8856,21 +8937,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;
 }
 
@@ -10296,8 +10379,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
@@ -10527,6 +10609,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
@@ -10561,6 +10644,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;
 
@@ -10574,7 +10658,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
   while (true)
     {
       bool constructor_p;
-      bool found_decl_spec;
       cp_token *token;
       ds = ds_last;
 
@@ -10586,12 +10669,55 @@ 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. In that case
+	     [dcl.spec]/1 says:
+
+	         The attribute-specifier-seq affects the type only for
+		 the declaration it appears in, not other declarations
+		 involving the same type.
+
+             But for now let's force the user to position the
+             attribute either at the beginning of the declaration or
+             after the declarator-id, which would clearly mean that it
+             applies to the declarator.  */
+	  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
+		{
+		  if (decl_specs->type && CLASS_TYPE_P (decl_specs->type))
+		    {
+		      /*  This is an attribute following a
+			  class-specifier.  */
+		      if (decl_specs->type_definition_p)
+			warn_misplaced_attr_for_class_type (token->location,
+							    decl_specs->type);
+		      attrs = NULL_TREE;
+		    }
+		  else
+		    {
+		      decl_specs->std_attributes
+			= chainon (decl_specs->std_attributes,
+				   attrs);
+		      if (decl_specs->locations[ds_std_attribute] == 0)
+			decl_specs->locations[ds_std_attribute] = token->location;
+		    }
+		  continue;
+		}
+	    }
+
+	    decl_specs->attributes
+	      = chainon (decl_specs->attributes,
+			 attrs);
 	  if (decl_specs->locations[ds_attribute] == 0)
 	    decl_specs->locations[ds_attribute] = token->location;
 	  continue;
@@ -11318,13 +11444,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))
     {
@@ -11333,8 +11460,10 @@ 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
-	(code, class_type, cv_quals, declarator);
+      declarator = cp_parser_make_indirect_declarator
+	(code, class_type, cv_quals, declarator, std_attributes);
+
+      return declarator;
    }
 
   return NULL;
@@ -13165,7 +13294,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     {
       tree type;
 
-      type = check_tag_decl (&decl_specifiers);
+      type = check_tag_decl (&decl_specifiers,
+			     /*explicit_type_instantiation_p=*/true);
       /* Turn access control back on for names used during
 	 template instantiation.  */
       pop_deferring_access_checks ();
@@ -14596,7 +14726,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 +15628,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 +15694,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 +16036,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 +16044,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))
     {
@@ -15949,7 +16079,7 @@ cp_parser_declarator (cp_parser* parser,
 	declarator = NULL;
 
       declarator = cp_parser_make_indirect_declarator
-	(code, class_type, cv_quals, declarator);
+	(code, class_type, cv_quals, declarator, std_attributes);
     }
   /* Everything else is a direct-declarator.  */
   else
@@ -15962,9 +16092,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 +16233,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 +16247,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 +16262,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 +16312,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 +16369,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 +16445,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 +16561,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 +16609,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 +16633,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 +16669,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 +16710,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 +17073,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 +18179,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 +18200,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 +19056,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))
@@ -18931,7 +19087,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	  friend_p = cp_parser_friend_p (&decl_specifiers);
 	  /* If there were decl-specifiers, check to see if there was
 	     a class-declaration.  */
-	  type = check_tag_decl (&decl_specifiers);
+	  type = check_tag_decl (&decl_specifiers,
+				 /*explicit_type_instantiation_p=*/false);
 	  /* Nested classes have already been added to the class, but
 	     a `friend' needs to be explicitly registered.  */
 	  if (friend_p)
@@ -18998,6 +19155,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 +20267,80 @@ 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 +20349,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 +20378,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 +20399,7 @@ cp_parser_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
-/* Parse an attribute-list.
+/* Parse a GNU attribute-list.
 
    attribute-list:
      attribute
@@ -20180,7 +20417,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 +20496,277 @@ 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 = NULL_TREE, 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 if (token->flags & NAMED_OP)
+    attr_id = get_identifier (cpp_type2name (token->type, token->flags));
+
+  if (attr_id == NULL_TREE)
+    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 clause of the attribute.  */
+
+  if (token->type != CPP_OPEN_PAREN)
+    return attribute;
+
+  {
+    VEC(tree, gc) *vec;
+    int attr_flag = normal_attr;
+
+    if (attr_ns == get_identifier ("gnu")
+	&& attribute_takes_identifier_p (attr_id))
+      /* A GNU attribute that takes an identifier in parameter.  */
+      attr_flag = id_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;
+
+      /* 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);
+
+      /* 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/typeck.c b/gcc/cp/typeck.c
index 884f7d0..b427921 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1701,6 +1701,56 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain)
   else
     return cxx_alignof_expr (e, complain? tf_warning_or_error : tf_none);
 }
+
+/*  Build a representation of an expression 'alignas(E).'  Return the
+    folded integer value of E if it is an integral constant expression
+    that resolves to a valid alignment.  If E depends on a template
+    parameter, return a syntactic representation tree of kind
+    ALIGNOF_EXPR.  Otherwise, return an error_mark_node if the
+    expression is ill formed, or NULL_TREE if E is NULL_TREE.  */
+
+tree
+cxx_alignas_expr (tree e)
+{
+  if (e == NULL_TREE || e == error_mark_node
+      || (!TYPE_P (e) && !require_potential_rvalue_constant_expression (e)))
+    return e;
+  
+  if (TYPE_P (e))
+    /* [dcl.align]/3:
+       
+	   When the alignment-specifier is of the form
+	   alignas(type-id ), it shall have the same effect as
+	   alignas( alignof(type-id )).  */
+
+    return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, false);
+  
+
+  /* If we reach this point, it means the alignas expression if of
+     the form "alignas(assignment-expression)", so we should follow
+     what is stated by [dcl.align]/2.  */
+
+  e = mark_rvalue_use (e);
+
+  /* [dcl.align]/2 says:
+
+         the assignment-expression shall be an integral constant
+	 expression.  */
+  
+  e = fold_non_dependent_expr (e);
+  if (value_dependent_expression_p (e))
+    /* Leave value-dependent expression alone for now. */;
+  else
+    e = cxx_constant_value (e);
+
+  if (e == NULL_TREE
+      || e == error_mark_node
+      || TREE_CODE (e) != INTEGER_CST)
+    return error_mark_node;
+
+  return e;
+}
+
 \f
 /* 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..c514e67 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 *,
+							     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..a55698c
--- /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 "ignored" }
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.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..4adefdb
--- /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..636f9a9
--- /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..566461b0
--- /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-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
new file mode 100644
index 0000000..2f47b32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
@@ -0,0 +1,3 @@
+// { dg-do compile { target c++11 } }
+
+struct [[gnu::unused]] A {};
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..2d5ad04
--- /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 b [[gnu::aligned (16)]];
+};
+
+struct T
+{
+  char a;
+  void * b [[gnu::aligned (16)]];
+};
+
+static_assert (sizeof (S) == sizeof (T),
+	       "struct S and T should have the same size");
+
+static_assert (sizeof (S) == 32, "sizeof (S) == 8 + 16 + 8");
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..4c07df9
--- /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 "ignored" }
+}
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..f3da452
--- /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 [[gnu::warn_unused_result]] (char *) ;
+extern int f2 [[gnu::warn_unused_result]] (char *) throw () ;
+extern int f2 (char *) throw ();
+
+extern int f3 [[gnu::nonnull (1)]] (char *) ;
+extern int f4 [[gnu::nonnull (1)]] (char *) throw ();
+extern int f4 (char *) throw ();
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..edd1067
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C
@@ -0,0 +1,22 @@
+// Test that attributes work in a variety of situations.
+// { dg-options "-O -ftrack-macro-expansion=0" }
+// { dg-do run { target c++11 } }
+
+#define attrib [[gnu::mode (QI)]]
+#define gnu_attrib __attribute((mode (QI)))
+
+attrib signed int a;
+static unsigned int b attrib;
+
+int foo(attrib int o)
+{
+  return (sizeof (a) != 1
+	  || sizeof (b) != 1
+	  || sizeof (o) != 1
+	  || sizeof ((gnu_attrib signed int) b) != 1);
+}
+
+int main ()
+{
+  return foo (42);
+}
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..537dec5
--- /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 "ignored" }
+
+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..f344661
--- /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 "ignored" }
+
+static void foo(U) {}
+static void foo(int) {}
+
+void bar()
+{
+  foo(0);
+}
+
+typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" }
+
+static void foo2(U1) {}		// { dg-error "previously defined" }
+static void foo2(U2) {}		// { dg-error "redefinition" }
+
+void bar2(U1 u1, U2 u2)
+{
+  foo2(u1);
+  foo2(u2);
+}
+
+// PR c++/36410
+struct A
+{
+  typedef union [[gnu::transparent_union]]
+  {
+    int i;
+  } B;
+};
+
+void foo(A::B b)
+{
+  b.i;
+}
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..2aae9ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+
+struct S;
+
+typedef int (*F [[gnu::warn_unused_result]]) (int);
+
+typedef int (*F2 [[gnu::warn_unused_result]]) (int);
+
+typedef int (S::*F3 [[gnu::warn_unused_result]]) (int); // { dg-warning "only applies to function types" }
+
+typedef int [[gnu::warn_unused_result]] (*F5) (int); // { dg-warning "ignored" }
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..3db981a
--- /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 "ignored" }
+};
+
+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..453fc01
--- /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-warning "ignored" }
+  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..bad33d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -0,0 +1,30 @@
+// { dg-options "-std=c++11 -Wunused -pedantic-errors" }
+// { dg-do compile }
+// Test for syntax support of various attribute permutations.
+
+int
+[[gnu::noreturn]] // { dg-warning "ignored" }
+one
+[[gnu::unused]]
+(void);
+
+int one_third [[gnu::noreturn]] [[gnu::unused]] (void);
+
+int [[gnu::unused]] one_half(); // { dg-warning "ignored" }
+
+static
+[[gnu::noreturn]] // { dg-warning "ignored" }
+void two [[gnu::unused]] (void) {}
+
+
+
+[[gnu::unused]]
+int
+five(void)
+[[gnu::noreturn]] // { dg-warning "ignored" }
+{}
+
+[[gnu::noreturn]]
+void
+six (void)
+;
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..c850622
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
@@ -0,0 +1,4 @@
+// { dg-do compile { target c++11 } }
+template <class T> struct A { };
+
+template [[gnu::packed]] struct A<int>;  // { dg-warning "ignored in explicit instantiation" }
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..81d70e5
--- /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 "ignored in declaration" }
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-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
new file mode 100644
index 0000000..4a5d73a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+int
+foo ()
+{
+  int i [[and, bitor, xor_eq, compl, bitand]]; // { dg-warning "ignored" }
+  i = 0;
+  return i;
+}
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..83de121
--- /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..0f87fd4
--- /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;}  a [[gnu::aligned(16)]];
+struct B {int i;} __attribute__((aligned(16))) b;
+
+int
+main ()
+{
+ A aa;
+ B bb;
+
+ static_assert (sizeof (a) == 4, "sizeof (a) should be 4");
+ static_assert (sizeof (b) == 16, "sizeof (b) should be 16");
+ static_assert (sizeof (aa) == 4, "sizeof (aa) should be 4");
+ static_assert (sizeof (bb) == 16, "sizeof (bb) should be 16");
+
+ static_assert (__alignof__  (a) == 16, "alignof (a) should be 16");
+ static_assert (__alignof__  (b) == 16, "alignof (b) should be 16");
+ static_assert (__alignof__  (aa) == 4, "alignof (aa) should be 4");
+ static_assert (__alignof__  (bb) == 16, "alignof (bb) should be 16");
+}
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..723c8ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
@@ -0,0 +1,39 @@
+// { dg-do compile { target c++11 } }
+
+int
+toto ()
+{
+  [[gnu::unused]] good:
+    return 0;
+}
+
+int
+foo ()
+{
+  [[gnu::unused]] good:
+    int i = 0;
+
+  // A C++11 attribute at the beginning of the return statement is
+  // syntactically correct, appertains to the return statement (not to
+  // the label) but is currently ignored by this implementation.
+ good_ignored : [[gnu::unused]] // { dg-warning "attributes at the beginning of statement are ignored" }
+    return i;
+}
+
+int
+bar ()
+{
+  // A GNU attribute after the label appertains to the label.
+ good: __attribute__((unused));
+  return 0;
+}
+
+int
+baz ()
+{
+  // The c++ attribute after the label appertains to the (empty)
+  // statement.
+ bad: [[gnu::unused]]; // { dg-warning "attributes at the beginning of statement are ignored" }
+  return 0;
+}
+
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 7f620e5..8df1b86 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4350,7 +4350,7 @@ comp_type_attributes (const_tree type1, const_tree type2)
       const struct attribute_spec *as;
       const_tree attr;
 
-      as = lookup_attribute_spec (TREE_PURPOSE (a));
+      as = lookup_attribute_spec (get_attribute_name (a));
       if (!as || as->affects_type_identity == false)
         continue;
 
@@ -4364,7 +4364,7 @@ comp_type_attributes (const_tree type1, const_tree type2)
 	{
 	  const struct attribute_spec *as;
 
-	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+	  as = lookup_attribute_spec (get_attribute_name (a));
 	  if (!as || as->affects_type_identity == false)
 	    continue;
 
@@ -5287,11 +5287,12 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
 {
   while (list)
     {
-      size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list));
+      size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
 
       if (ident_len == attr_len)
 	{
-	  if (strcmp (attr_name, IDENTIFIER_POINTER (TREE_PURPOSE (list))) == 0)
+	  if (!strcmp (attr_name,
+		       IDENTIFIER_POINTER (get_attribute_name (list))))
 	    break;
 	}
       /* TODO: If we made sure that attributes were stored in the
@@ -5299,7 +5300,7 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
 	 to '__text__') then we could avoid the following case.  */
       else if (ident_len == attr_len + 4)
 	{
-	  const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
+	  const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
 	  if (p[0] == '_' && p[1] == '_'
 	      && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
 	      && strncmp (attr_name, p + 2, attr_len) == 0)
@@ -5329,10 +5330,11 @@ lookup_ident_attribute (tree attr_identifier, tree list)
 
   while (list)
     {
-      gcc_checking_assert (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE);
+      gcc_checking_assert (TREE_CODE (get_attribute_name (list))
+			   == IDENTIFIER_NODE);
 
       /* Identifiers can be compared directly for equality.  */
-      if (attr_identifier == TREE_PURPOSE (list))
+      if (attr_identifier == get_attribute_name (list))
 	break;
 
       /* If they are not equal, they may still be one in the form
@@ -5342,11 +5344,11 @@ lookup_ident_attribute (tree attr_identifier, tree list)
 	 the fact that we're comparing identifiers. :-)  */
       {
 	size_t attr_len = IDENTIFIER_LENGTH (attr_identifier);
-	size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list));
+	size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
 
 	if (ident_len == attr_len + 4)
 	  {
-	    const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
+	    const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
 	    const char *q = IDENTIFIER_POINTER (attr_identifier);
 	    if (p[0] == '_' && p[1] == '_'
 		&& p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
@@ -5355,7 +5357,7 @@ lookup_ident_attribute (tree attr_identifier, tree list)
 	  }
 	else if (ident_len + 4 == attr_len)
 	  {
-	    const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list));
+	    const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
 	    const char *q = IDENTIFIER_POINTER (attr_identifier);
 	    if (q[0] == '_' && q[1] == '_'
 		&& q[attr_len - 2] == '_' && q[attr_len - 1] == '_'
@@ -5385,7 +5387,7 @@ remove_attribute (const char *attr_name, tree list)
       tree l = *p;
       /* TODO: If we were storing attributes in normalized form, here
 	 we could use a simple strcmp().  */
-      if (private_is_attribute_p (attr_name, attr_len, TREE_PURPOSE (l)))
+      if (private_is_attribute_p (attr_name, attr_len, get_attribute_name (l)))
 	*p = TREE_CHAIN (l);
       else
 	p = &TREE_CHAIN (l);
@@ -5422,9 +5424,11 @@ merge_attributes (tree a1, tree a2)
 	  for (; a2 != 0; a2 = TREE_CHAIN (a2))
 	    {
 	      tree a;
-	      for (a = lookup_ident_attribute (TREE_PURPOSE (a2), attributes);
+	      for (a = lookup_ident_attribute (get_attribute_name (a2),
+					       attributes);
 		   a != NULL_TREE && !attribute_value_equal (a, a2);
-		   a = lookup_ident_attribute (TREE_PURPOSE (a2), TREE_CHAIN (a)))
+		   a = lookup_ident_attribute (get_attribute_name (a2),
+					       TREE_CHAIN (a)))
 		;
 	      if (a == NULL_TREE)
 		{
@@ -6346,7 +6350,7 @@ attribute_hash_list (const_tree list, hashval_t hashcode)
   for (tail = list; tail; tail = TREE_CHAIN (tail))
     /* ??? Do we want to add in TREE_VALUE too? */
     hashcode = iterative_hash_object
-      (IDENTIFIER_HASH_VALUE (TREE_PURPOSE (tail)), hashcode);
+      (IDENTIFIER_HASH_VALUE (get_attribute_name (tail)), hashcode);
   return hashcode;
 }
 
@@ -6383,7 +6387,7 @@ attribute_list_contained (const_tree l1, const_tree l2)
   /* Maybe the lists are similar.  */
   for (t1 = l1, t2 = l2;
        t1 != 0 && t2 != 0
-        && TREE_PURPOSE (t1) == TREE_PURPOSE (t2)
+        && get_attribute_name (t1) == get_attribute_name (t2)
         && TREE_VALUE (t1) == TREE_VALUE (t2);
        t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
     ;
@@ -6398,9 +6402,9 @@ attribute_list_contained (const_tree l1, const_tree l2)
       /* This CONST_CAST is okay because lookup_attribute does not
 	 modify its argument and the return value is assigned to a
 	 const_tree.  */
-      for (attr = lookup_ident_attribute (TREE_PURPOSE (t2), CONST_CAST_TREE(l1));
+      for (attr = lookup_ident_attribute (get_attribute_name (t2), CONST_CAST_TREE(l1));
 	   attr != NULL_TREE && !attribute_value_equal (t2, attr);
-	   attr = lookup_ident_attribute (TREE_PURPOSE (t2), TREE_CHAIN (attr)))
+	   attr = lookup_ident_attribute (get_attribute_name (t2), TREE_CHAIN (attr)))
 	;
 
       if (attr == NULL_TREE)
diff --git a/gcc/tree.h b/gcc/tree.h
index ff4ae52..e7cef18 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4903,12 +4903,12 @@ struct attribute_spec
 {
   /* The name of the attribute (without any leading or trailing __),
      or NULL to mark the end of a table of attributes.  */
-  const char *const name;
+  const char *name;
   /* The minimum length of the list of arguments of the attribute.  */
-  const int min_length;
+  int min_length;
   /* The maximum length of the list of arguments of the attribute
      (-1 for no maximum).  */
-  const int max_length;
+  int max_length;
   /* Whether this attribute requires a DECL.  If it does, it will be passed
      from types of DECLs, function return types and array element types to
      the DECLs, function types and array types respectively; but when
@@ -4916,15 +4916,15 @@ struct attribute_spec
      a warning.  (If greater control is desired for a given attribute,
      this should be false, and the flags argument to the handler may be
      used to gain greater control in that case.)  */
-  const bool decl_required;
+  bool decl_required;
   /* Whether this attribute requires a type.  If it does, it will be passed
      from a DECL to the type of that DECL.  */
-  const bool type_required;
+  bool type_required;
   /* Whether this attribute requires a function (or method) type.  If it does,
      it will be passed from a function pointer type to the target type,
      and from a function return type (which is not itself a function
      pointer type) to the function type.  */
-  const bool function_type_required;
+  bool function_type_required;
   /* Function to handle this attribute.  NODE points to the node to which
      the attribute is to be applied.  If a DECL, it should be modified in
      place; if a TYPE, a copy should be created.  NAME is the name of the
@@ -4939,10 +4939,10 @@ struct attribute_spec
      otherwise the return value should be NULL_TREE.  This pointer may be
      NULL if no special handling is required beyond the checks implied
      by the rest of this structure.  */
-  tree (*const handler) (tree *node, tree name, tree args,
-				 int flags, bool *no_add_attrs);
+  tree (*handler) (tree *node, tree name, tree args,
+		   int flags, bool *no_add_attrs);
   /* Specifies if attribute affects type's identity.  */
-  const bool affects_type_identity;
+  bool affects_type_identity;
 };
 
 /* Flags that may be passed in the third argument of decl_attributes, and
@@ -4967,7 +4967,9 @@ enum attribute_flags
   /* The attributes are being applied by default to a library function whose
      name indicates known behavior, and should be silently ignored if they
      are not in fact compatible with the function type.  */
-  ATTR_FLAG_BUILT_IN = 16
+  ATTR_FLAG_BUILT_IN = 16,
+  /* A given attribute has been parsed as a C++-11 attribute.  */
+  ATTR_FLAG_CXX11 = 32
 };
 
 /* Default versions of target-overridable functions.  */
@@ -6054,6 +6056,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree);
 /* In attribs.c.  */
 
 extern const struct attribute_spec *lookup_attribute_spec (const_tree);
+extern const struct attribute_spec *lookup_scoped_attribute_spec (const_tree,
+								  const_tree);
 
 extern void init_attributes (void);
 
@@ -6067,6 +6071,12 @@ extern void init_attributes (void);
    a decl attribute to the declaration rather than to its type).  */
 extern tree decl_attributes (tree *, tree, int);
 
+extern bool cxx11_attribute_p (const_tree);
+
+extern tree get_attribute_name (const_tree);
+
+extern tree get_attribute_namespace (const_tree);
+
 extern void apply_tm_attr (tree, tree);
 
 /* In stor-layout.c */
-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-09-20  7:51                   ` Dodji Seketeli
@ 2012-10-04 21:43                     ` Jason Merrill
  2012-10-06  8:53                       ` Dodji Seketeli
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2012-10-04 21:43 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

On 09/20/2012 02:59 AM, Dodji Seketeli wrote:
>>> +      if ((flags & ATTR_FLAG_CXX11)
>>> +	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE
>>> +	       && (TREE_CODE (*node) == RECORD_TYPE
>>> +		   || TREE_CODE (*node) == UNION_TYPE)))
>>> +	{
>>> +	  /* unused is being used as a c++11 attribute.  In this mode
>>> +	     we prevent it from applying to types, unless it's for a
>>> +	     class defintion.  */
>>> +	  warning (OPT_Wattributes,
>>> +		   "attribute %qE cannot be applied to a non-class type", name);
>>> +	  return NULL_TREE;
>>> +	}
>>
>> I think this should now be covered by the general ignoring of
>> attributes that appertain to type-specifiers, so we don't need to
>> check it here.
>
> Removed.

Looks to me like it's still there.

> +    int attr_flag = attribute_takes_identifier_p (attr_id)
> +      ? id_attr
> +      : normal_attr;

This should only apply to attributes in the gnu namespace.

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-09-18 16:53                 ` Jason Merrill
@ 2012-09-20  7:51                   ` Dodji Seketeli
  2012-10-04 21:43                     ` Jason Merrill
  0 siblings, 1 reply; 22+ messages in thread
From: Dodji Seketeli @ 2012-09-20  7:51 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

> On 09/18/2012 09:51 AM, Dodji Seketeli wrote:
> > +      VEC_safe_push (scoped_attributes, heap, attributes_table, sa);
> > +      result = &VEC_last (scoped_attributes, attributes_table);
> 
> Here you can set result from the return value of VEC_safe_push.

Done.

> 
> > +      if ((flags & ATTR_FLAG_CXX11)
> > +	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE
> > +	       && (TREE_CODE (*node) == RECORD_TYPE
> > +		   || TREE_CODE (*node) == UNION_TYPE)))
> > +	{
> > +	  /* unused is being used as a c++11 attribute.  In this mode
> > +	     we prevent it from applying to types, unless it's for a
> > +	     class defintion.  */
> > +	  warning (OPT_Wattributes,
> > +		   "attribute %qE cannot be applied to a non-class type", name);
> > +	  return NULL_TREE;
> > +	}
> 
> I think this should now be covered by the general ignoring of
> attributes that appertain to type-specifiers, so we don't need to
> check it here.

Removed.

> 
> > +      error ("requested alignment %d is larger than %d",
> > +	     requested_alignment, max_align);
> 
> Let's make this a pedwarn.

Done.

> > +cxx_fundamental_alignment_p  (unsigned align)
> > +{
> > +
> > +  return (align <=  MAX (TYPE_ALIGN (long_long_integer_type_node),
> > +			 TYPE_ALIGN (long_double_type_node)));
> > +}
> 
> Unneeded blank line.

Fixed.

> 
> > +		      inform (token->location,
> > +			      "an attribute for a declaration should be either "
> > +			      "at the begining of the declaration or after "
> > +			      "the declarator-id");
> 
> Putting this code here means that we give the diagnostic for
> attributes in the decl-specifier-seq, but not for attributes that
> apply to type parts of the declarator such as a ptr-operator or a
> function declarator. I think the best place to implement this in
> decl_attributes; there you can just ignore any attributes applied to a
> type without ATTR_FLAG_TYPE_IN_PLACE.

Done.

> > +      declarator = cp_parser_make_indirect_declarator
> >  	(code, type, cv_quals, declarator);
> > +      if (declarator != NULL && declarator != cp_error_declarator)
> > +	declarator->attributes = std_attributes;
> 
> Let's pass std_attributes to make_indirect_declarator.

Done.

> >        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;
> 
> Here too.

Done.

> 
> > +cp_parser_attributes_opt (cp_parser *parser)
> > +{
> > +
> > +  if (cp_next_tokens_can_be_gnu_attribute_p (parser))
> 
> Unneeded newline.

Fixed.

> 
> > +	  alignas_expr =
> > +	    cp_parser_assignment_expression (parser, /*cast_p=*/false,
> > +					     /**cp_id_kind=*/NULL);
> 
> Let's require_potential_rvalue_constant_expression here or in
> cxx_alignas_expr.

Done in cxx_alignas_expr.

> 
> > +      alignas_expr = fold_non_dependent_expr (alignas_expr);
> 
> You don't need this both in the parser and in cxx_alignas_expr.

Remove from here.

> > +cxx_alignas_expr (tree e, tsubst_flags_t complain)
> 
> I don't think you need the complain parameter anymore, so you don't
> need to make fold_non_dependent_expr_sfinae non-static either.

Done.

> > +  /* [dcl.align]/2 says:
> > +
> > +     [the assignment-expression shall be an integral constant
> > +      expression].  */
> > +  e = fold_non_dependent_expr_sfinae (e, complain);
> > +  if (e == NULL_TREE
> > +      || e == error_mark_node
> > +      || TREE_CODE (e) != INTEGER_CST)
> > +    return error_mark_node;
> 
> This needs to allow value-dependent expressions.  I'd say
> 
> e = fold_non_dependent_expr (e);
> if (value_dependent_expression_p (e))
>   /* Leave value-dependent expression alone for now. */;
> else
>   e = cxx_constant_value (e);

Done.


Tested on x86_64-unknown-linux-gnu.


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

gcc/c-family/

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

gcc/cp/

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

gcc/testsuite/

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

WIP address last review comments
---
 gcc/attribs.c                               |  229 +++++++++-
 gcc/c-family/c-common.c                     |  132 ++++++-
 gcc/c-family/c-common.h                     |    1 +
 gcc/cp/cp-tree.h                            |   20 +-
 gcc/cp/decl.c                               |   85 ++++-
 gcc/cp/decl2.c                              |    2 +-
 gcc/cp/error.c                              |    5 +
 gcc/cp/parser.c                             |  657 +++++++++++++++++++++++---
 gcc/cp/typeck.c                             |   50 ++
 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.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-1.C  |    3 +
 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    |   22 +
 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 |   11 +
 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    |   30 ++
 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   |    4 +
 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-1.C |    8 +
 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   |   39 ++
 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                                  |   30 +-
 70 files changed, 1909 insertions(+), 137 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.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-1.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-1.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.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

diff --git a/gcc/attribs.c b/gcc/attribs.c
index d3af414..0577bc6 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);
+DEF_VEC_ALLOC_O (attribute_spec, heap);
+
+/* Scoped attribute name representation.  */
+
+struct scoped_attributes
+{
+  const char *ns;
+  VEC (attribute_spec, heap) *attributes;
+  htab_t attribute_hash;
+};
+
+DEF_VEC_O (scoped_attributes);
+DEF_VEC_ALLOC_O (scoped_attributes, heap);
+
+/* The table of scope attributes.  */
+static VEC(scoped_attributes, heap) *attributes_table;
+
+static scoped_attributes* find_attribute_namespace (const char*);
+static void register_scoped_attribute (const struct attribute_spec *,
+				       scoped_attributes *);
+
 static bool attributes_initialized = false;
 
 /* Default empty table of attributes.  */
@@ -102,6 +121,64 @@ eq_attr (const void *p, const void *q)
   return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]);
 }
 
+/* Insert an array of attributes ATTRIBUTES into a namespace.  This
+   array must be NULL terminated.  NS is the name of attribute
+   namespace.  The function returns the namespace into which the
+   attributes have been registered.  */
+
+scoped_attributes*
+register_scoped_attributes (const struct attribute_spec * attributes,
+			    const char* ns)
+{
+  scoped_attributes *result = NULL;
+
+  /* See if we already have attributes in the namespace NS.  */
+  result = find_attribute_namespace (ns);
+
+  if (result == NULL)
+    {
+      /* We don't have any namespace NS yet.  Create one.  */
+      scoped_attributes sa;
+
+      if (attributes_table == NULL)
+	attributes_table = VEC_alloc (scoped_attributes, heap, 64);
+
+      memset (&sa, 0, sizeof (sa));
+      sa.ns = ns;
+      sa.attributes = VEC_alloc (attribute_spec, heap, 64);
+      result = VEC_safe_push (scoped_attributes, heap, attributes_table, sa);      
+    }
+
+  /* Really add the attributes to their namespace now.  */
+  for (unsigned i = 0; attributes[i].name != NULL; ++i)
+    {
+      VEC_safe_push (attribute_spec, heap,
+		     result->attributes, attributes[i]);
+      register_scoped_attribute (&attributes[i], result);
+    }
+
+  gcc_assert (result != NULL);
+
+  return result;
+}
+
+/* Return the namespace which name is NS, NULL if none exist.  */
+
+static scoped_attributes*
+find_attribute_namespace (const char* ns)
+{
+  unsigned ix;
+  scoped_attributes *iter;
+
+  FOR_EACH_VEC_ELT (scoped_attributes, attributes_table, ix, iter)
+    if (ns == iter->ns
+	|| (iter->ns != NULL
+	    && ns != NULL
+	    && !strcmp (iter->ns, ns)))
+      return iter;
+  return NULL;
+}
+
 /* Initialize attribute tables, and make some sanity checks
    if --enable-checking.  */
 
@@ -109,7 +186,6 @@ void
 init_attributes (void)
 {
   size_t i;
-  int k;
 
   if (attributes_initialized)
     return;
@@ -181,12 +257,10 @@ init_attributes (void)
     }
 #endif
 
-  attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
-  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
-    for (k = 0; attribute_tables[i][k].name != NULL; k++)
-      {
-        register_attribute (&attribute_tables[i][k]);
-      }
+  for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
+    /* Put all the GNU attributes into the "gnu" namespace.  */
+    register_scoped_attributes (attribute_tables[i], "gnu");
+
   invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
   attributes_initialized = true;
 }
@@ -196,9 +270,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 *name_space)
+{
   struct substring str;
   void **slot;
 
+  gcc_assert (attr != NULL && name_space != NULL);
+
+  if (name_space->attribute_hash == NULL)
+   name_space->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
+
   str.str = attr->name;
   str.length = strlen (str.str);
 
@@ -206,27 +294,45 @@ register_attribute (const struct attribute_spec *attr)
      in the form '__text__'.  */
   gcc_assert (str.length > 0 && str.str[0] != '_');
 
-  slot = htab_find_slot_with_hash (attribute_hash, &str,
+  slot = htab_find_slot_with_hash (name_space->attribute_hash, &str,
 				   substring_hash (str.str, str.length),
 				   INSERT);
   gcc_assert (!*slot || attr->name[0] == '*');
   *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
 }
 
-/* Return the spec for the 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 *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);
+}
+
 \f
 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
    which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
@@ -243,7 +349,7 @@ decl_attributes (tree *node, tree attributes, int flags)
   tree a;
   tree returned_attrs = NULL_TREE;
 
-  if (TREE_TYPE (*node) == error_mark_node)
+  if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
     return NULL_TREE;
 
   if (!attributes_initialized)
@@ -302,10 +408,12 @@ decl_attributes (tree *node, tree attributes, int flags)
 
   for (a = attributes; a; a = TREE_CHAIN (a))
     {
-      tree name = TREE_PURPOSE (a);
+      tree ns = get_attribute_namespace (a);
+      tree name = get_attribute_name (a);
       tree args = TREE_VALUE (a);
       tree *anode = node;
-      const struct attribute_spec *spec = lookup_attribute_spec (name);
+      const struct attribute_spec *spec =
+	lookup_scoped_attribute_spec (ns, name);
       bool no_add_attrs = 0;
       int fn_ptr_quals = 0;
       tree fn_ptr_tmp = NULL_TREE;
@@ -313,8 +421,15 @@ decl_attributes (tree *node, tree attributes, int flags)
       if (spec == NULL)
 	{
 	  if (!(flags & (int) ATTR_FLAG_BUILT_IN))
-	    warning (OPT_Wattributes, "%qE attribute directive ignored",
-		     name);
+	    {
+	      if (ns == NULL_TREE || !cxx11_attribute_p (a))
+		warning (OPT_Wattributes, "%qE attribute directive ignored",
+			 name);
+	      else
+		warning (OPT_Wattributes,
+			 "%<%E::%E%> scoped attribute directive ignored",
+			 ns, name);
+	    }
 	  continue;
 	}
       else if (list_length (args) < spec->min_length
@@ -327,6 +442,20 @@ decl_attributes (tree *node, tree attributes, int flags)
 	}
       gcc_assert (is_attribute_p (spec->name, name));
 
+      if (TYPE_P (*node)
+	  && cxx11_attribute_p (a)
+	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
+	{
+	  /* This is a c++11 attribute that appertain to a type-specifier,
+	     outside of the definition of, a class type.  Ignore
+	     it.  */
+	  warning (OPT_Wattributes, "attribute ignored");
+	  inform (input_location,
+		  "an attribute that appertains to a type-specifier "
+		  "is ignored");
+	  continue;
+	}
+
       if (spec->decl_required && !DECL_P (*anode))
 	{
 	  if (flags & ((int) ATTR_FLAG_DECL_NEXT
@@ -406,9 +535,15 @@ decl_attributes (tree *node, tree attributes, int flags)
 	}
 
       if (spec->handler != NULL)
-	returned_attrs = chainon ((*spec->handler) (anode, name, args,
-						    flags, &no_add_attrs),
-				  returned_attrs);
+	{
+	  int cxx11_flag =
+	    cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
+
+	  returned_attrs = chainon ((*spec->handler) (anode, name, args,
+						      flags|cxx11_flag,
+						      &no_add_attrs),
+				    returned_attrs);
+	}
 
       /* Layout the decl in case anything changed.  */
       if (spec->type_required && DECL_P (*node)
@@ -488,6 +623,56 @@ decl_attributes (tree *node, tree attributes, int flags)
   return returned_attrs;
 }
 
+/* Return TRUE iff ATTR has been parsed by the front-end as a C++-11
+   attribute.
+
+   When G++ parses a C++11 attribute, it is represented as
+   a TREE_LIST which TREE_PURPOSE is itself a TREE_LIST.  TREE_PURPOSE
+   (TREE_PURPOSE (ATTR)) is the namespace of the attribute, and the
+   TREE_VALUE (TREE_PURPOSE (ATTR)) is its non-qualified name.  Please
+   use get_attribute_namespace and get_attribute_name to retrieve the
+   namespace and name of the attribute, as these accessors work with
+   GNU attributes as well.  */
+
+bool
+cxx11_attribute_p (const_tree attr)
+{
+  if (attr == NULL_TREE
+      || TREE_CODE (attr) != TREE_LIST)
+    return false;
+
+  return (TREE_CODE (TREE_PURPOSE (attr)) == TREE_LIST);
+}
+
+/* Return the name of the attribute ATTR.  This accessor works on GNU
+   and C++11 (scoped) attributes.
+
+   Please read the comments of cxx11_attribute_p to understand the
+   format of attributes.  */
+
+tree
+get_attribute_name (const_tree attr)
+{
+  if (cxx11_attribute_p (attr))
+    return TREE_VALUE (TREE_PURPOSE (attr));
+  return TREE_PURPOSE (attr);
+}
+
+/* Return the namespace of the attribute ATTR.  This accessor works on
+   GNU and C++11 (scoped) attributes.  On GNU attributes,
+   it returns an identifier tree for the string "gnu".
+
+   Please read the comments of cxx11_attribute_p to understand the
+   format of attributes.  */
+
+tree
+get_attribute_namespace (const_tree attr)
+{
+  if (cxx11_attribute_p (attr))
+    return TREE_PURPOSE (TREE_PURPOSE (attr));
+  return get_identifier ("gnu");
+}
+
 /* Subroutine of set_method_tm_attributes.  Apply TM attribute ATTR
    to the method FNDECL.  */
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 6de2f1c..9325147 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 },
@@ -6588,6 +6589,18 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     }
   else
     {
+      if ((flags & ATTR_FLAG_CXX11)
+	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE
+	       && (TREE_CODE (*node) == RECORD_TYPE
+		   || TREE_CODE (*node) == UNION_TYPE)))
+	{
+	  /* unused is being used as a c++11 attribute.  In this mode
+	     we prevent it from applying to types, unless it's for a
+	     class defintion.  */
+	  warning (OPT_Wattributes,
+		   "attribute %qE cannot be applied to a non-class type", name);
+	  return NULL_TREE;
+	}
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
 	*node = build_variant_type_copy (*node);
       TREE_USED (*node) = 1;
@@ -6665,7 +6678,9 @@ handle_transparent_union_attribute (tree *node, tree name,
 
   *no_add_attrs = true;
 
-  if (TREE_CODE (*node) == TYPE_DECL)
+
+  if (TREE_CODE (*node) == TYPE_DECL
+      && ! (flags & ATTR_FLAG_CXX11))
     node = &TREE_TYPE (*node);
   type = *node;
 
@@ -7137,6 +7152,89 @@ check_user_alignment (const_tree align, bool allow_zero)
   return i;
 }
 
+/* 
+   If in c++-11, check if the c++-11 alignment constraint with respect
+   to fundamental alignment (in [dcl.align]) are satisfied.  If not in
+   c++-11 mode, does nothing.
+
+   [dcl.align]2/ says:
+
+   [* if the constant expression evaluates to a fundamental alignment,
+   the alignment requirement of the declared entity shall be the
+   specified fundamental alignment.
+
+   * if the constant expression evaluates to an extended alignment
+   and the implementation supports that alignment in the context
+   of the declaration, the alignment of the declared entity shall
+   be that alignment
+
+   * if the constant expression evaluates to an extended alignment
+   and the implementation does not support that alignment in the
+   context of the declaration, the program is ill-formed].  */
+
+static bool
+check_cxx_fundamental_alignment_constraints (tree node,
+					     unsigned align_log,
+					     int flags)
+{
+  bool alignment_too_large_p = false;
+  unsigned requested_alignment = 1U << align_log;
+  unsigned max_align = 0;
+
+  if ((!(flags & ATTR_FLAG_CXX11) && !warn_cxx_compat)
+      || (node == NULL_TREE || node == error_mark_node))
+    return true;
+
+  if (cxx_fundamental_alignment_p (requested_alignment))
+    return true;
+
+  if (DECL_P (node))
+    {
+      if (TREE_STATIC (node))
+	{
+	  /* For file scope variables and static members, the target
+	     supports alignments that are at most
+	     MAX_OFILE_ALIGNMENT.  */
+	  if (requested_alignment > (max_align = MAX_OFILE_ALIGNMENT))
+	    alignment_too_large_p = true;
+	}
+      else
+	{
+#ifdef BIGGEST_FIELD_ALIGNMENT
+#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_FIELD_ALIGNMENT
+#else
+#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_ALIGNMENT
+#endif
+	  /* For non-static members, the target supports either
+	     alignments that at most either BIGGEST_FIELD_ALIGNMENT
+	     if it is defined or BIGGEST_ALIGNMENT.  */
+	  max_align = MAX_TARGET_FIELD_ALIGNMENT;
+	  if (TREE_CODE (node) == FIELD_DECL
+	      && requested_alignment > (max_align = MAX_TARGET_FIELD_ALIGNMENT))
+	    alignment_too_large_p = true;
+#undef MAX_TARGET_FIELD_ALIGNMENT
+	  /* For stack variables, the target supports at most
+	     MAX_STACK_ALIGNMENT.  */
+	  else if (decl_function_context (node) != NULL
+		   && requested_alignment > (max_align = MAX_STACK_ALIGNMENT))
+	    alignment_too_large_p = true;
+	}
+    }
+  else if (TYPE_P (node))
+    {
+      /* Let's be liberal for types.  */
+      if (requested_alignment > (max_align = BIGGEST_ALIGNMENT))
+	alignment_too_large_p = true;
+    }
+
+  if (alignment_too_large_p)
+    pedwarn (input_location, OPT_Wattributes,
+	     "requested alignment %d is larger than %d",
+	     requested_alignment, max_align);
+
+  return !alignment_too_large_p;
+}
+
 /* Handle a "aligned" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -7160,7 +7258,8 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   else if (TYPE_P (*node))
     type = node, is_type = 1;
 
-  if ((i = check_user_alignment (align_expr, false)) == -1)
+  if ((i = check_user_alignment (align_expr, false)) == -1
+      || !check_cxx_fundamental_alignment_constraints (*node, i, flags))
     *no_add_attrs = true;
   else if (is_type)
     {
@@ -7190,6 +7289,17 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       error ("alignment may not be specified for %q+D", decl);
       *no_add_attrs = true;
     }
+  else if (DECL_USER_ALIGN (decl)
+	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
+    /* C++-11 [dcl.align/4]:
+
+           When multiple alignment-specifiers are specified for an
+	   entity, the alignment requirement shall be set to the
+	   strictest specified alignment.
+
+      This formally comes from the c++11 specification but we are
+      doing it for the GNU attribute syntax as well.  */
+    *no_add_attrs = true;
   else if (TREE_CODE (decl) == FUNCTION_DECL
 	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
     {
@@ -11154,4 +11264,22 @@ convert_vector_to_pointer_for_subscript (location_t loc,
     }
 }
 
+/* Return true iff ALIGN is an integral constant that is a fundamental
+   alignment, as defined by [basic.align] in the c++-11
+   specifications.
+
+   That is:
+
+       [A fundamental alignment is represented by an alignment less than or
+        equal to the greatest alignment supported by the implementation
+        in all contexts, which is equal to
+        alignof(max_align_t)].  */
+
+bool
+cxx_fundamental_alignment_p  (unsigned align)
+{
+  return (align <=  MAX (TYPE_ALIGN (long_long_integer_type_node),
+			 TYPE_ALIGN (long_double_type_node)));
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 9298e3d..87c1da8 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -790,6 +790,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 ded247d..fed7723 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. */
@@ -4668,6 +4670,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.  */
@@ -4686,6 +4689,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;
@@ -4754,8 +4759,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;
@@ -5052,7 +5063,9 @@ extern tree build_cp_library_fn_ptr		(const char *, tree);
 extern tree push_library_fn			(tree, tree, tree);
 extern tree push_void_library_fn		(tree, tree);
 extern tree push_throw_library_fn		(tree, tree);
-extern tree check_tag_decl			(cp_decl_specifier_seq *);
+extern void warn_misplaced_attr_for_class_type  (source_location location,
+						 tree class_type);
+extern tree check_tag_decl			(cp_decl_specifier_seq *, bool);
 extern tree shadow_tag				(cp_decl_specifier_seq *);
 extern tree groktypename			(cp_decl_specifier_seq *, const cp_declarator *, bool);
 extern tree start_decl				(const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
@@ -5812,6 +5825,7 @@ extern int comp_cv_qualification		(const_tree, const_tree);
 extern int comp_cv_qual_signature		(tree, tree);
 extern tree cxx_sizeof_or_alignof_expr		(tree, enum tree_code, bool);
 extern tree cxx_sizeof_or_alignof_type		(tree, enum tree_code, bool);
+extern tree cxx_alignas_expr                    (tree);
 extern tree cxx_sizeof_nowarn                   (tree);
 extern tree is_bitfield_expr_with_lowered_type  (const_tree);
 extern tree unlowered_expr_type                 (const_tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6b5b986..d41899f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4125,13 +4125,32 @@ fixup_anonymous_aggr (tree t)
     }
 }
 
+/* Warn for an attribute located at LOCATION that appertains to the
+   class type CLASS_TYPE that has not been properly placed after its
+   class-key, in it class-specifier.  */
+
+void
+warn_misplaced_attr_for_class_type (source_location location,
+				    tree class_type)
+{
+  gcc_assert (TAGGED_TYPE_P (class_type));
+
+  warning_at (location, OPT_Wattributes,
+	      "attribute ignored in declaration "
+	      "of %q#T", class_type);
+  inform (location,
+	  "attribute for %q#T must follow the %qs keyword",
+	  class_type, class_key_or_enum_as_string (class_type));
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
    just declares a tagged type or anonymous union.
 
    Returns the type declared; or NULL_TREE if none.  */
 
 tree
-check_tag_decl (cp_decl_specifier_seq *declspecs)
+check_tag_decl (cp_decl_specifier_seq *declspecs,
+		bool explicit_type_instantiation_p)
 {
   int saw_friend = decl_spec_seq_has_spec_p (declspecs, ds_friend);
   int saw_typedef = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
@@ -4240,10 +4259,22 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
 	/* For a template class (an explicit instantiation), use the
 	   current location.  */
 	loc = input_location;
-      warning_at (loc, OPT_Wattributes, "attribute ignored in declaration "
-		  "of %q#T", declared_type);
-      inform (loc, "attribute for %q#T must follow the %qs keyword",
-	      declared_type, class_key_or_enum_as_string (declared_type));
+
+      if (explicit_type_instantiation_p)
+	/* [dcl.attr.grammar]/4:
+
+	       No attribute-specifier-seq shall appertain to an explicit
+	       instantiation.  */
+	{
+	  warning_at (loc, OPT_Wattributes,
+		      "attribute ignored in explicit instantiation %q#T",
+		      declared_type);
+	  inform (loc,
+		  "no attribute can be applied to "
+		  "an explicit instantiation");
+	}
+      else
+	warn_misplaced_attr_for_class_type (loc, declared_type);
     }
 
   return declared_type;
@@ -4265,7 +4296,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
 tree
 shadow_tag (cp_decl_specifier_seq *declspecs)
 {
-  tree t = check_tag_decl (declspecs);
+  tree t = check_tag_decl (declspecs,
+			   /*explicit_type_instantiation_p=*/false);
 
   if (!t)
     return NULL_TREE;
@@ -9124,6 +9156,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)
@@ -9161,6 +9202,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:
@@ -9357,6 +9405,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;
 
@@ -9519,6 +9574,17 @@ grokdeclarator (const cp_declarator *declarator,
 					   declarator->u.pointer.qualifiers);
 	      type_quals = cp_type_quals (type);
 	    }
+
+	  /* Apply C++11 attributes to the pointer, and not to the
+	     type pointed to.  This is unlike what is done for GNU
+	     attributes above.  It is to comply with [dcl.ptr]/1:
+
+		 [the optional attribute-specifier-seq (7.6.1) appertains
+		  to the pointer and not to the object pointed to].  */
+	  if (declarator->std_attributes)
+	    decl_attributes (&type, declarator->std_attributes,
+			     0);
+
 	  ctype = NULL_TREE;
 	  break;
 
@@ -9644,6 +9710,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 0df4613..065c436 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 30fa018..3dd37aa 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3372,6 +3372,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 e8c0378..ae7670a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1197,13 +1197,13 @@ static cp_declarator *make_call_declarator
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
-  (cp_cv_quals, cp_declarator *);
+  (cp_cv_quals, cp_declarator *, tree);
 static cp_declarator *make_reference_declarator
-  (cp_cv_quals, cp_declarator *, bool);
+  (cp_cv_quals, cp_declarator *, bool, tree);
 static cp_parameter_declarator *make_parameter_declarator
   (cp_decl_specifier_seq *, cp_declarator *, tree);
 static cp_declarator *make_ptrmem_declarator
-  (cp_cv_quals, tree, cp_declarator *);
+  (cp_cv_quals, tree, cp_declarator *, tree);
 
 /* An erroneous declarator.  */
 static cp_declarator *cp_error_declarator;
@@ -1231,6 +1231,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;
@@ -1277,10 +1278,12 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name,
 
 /* Make a declarator for a pointer to TARGET.  CV_QUALIFIERS is a list
    of modifiers such as const or volatile to apply to the pointer
-   type, represented as identifiers.  */
+   type, represented as identifiers.  ATTRIBUTES represent the attributes that
+   appertain to the pointer or reference.  */
 
 cp_declarator *
-make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
+make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
+			 tree attributes)
 {
   cp_declarator *declarator;
 
@@ -1297,14 +1300,18 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
   else
     declarator->parameter_pack_p = false;
 
+  declarator->std_attributes = attributes;
+
   return declarator;
 }
 
-/* Like make_pointer_declarator -- but for references.  */
+/* Like make_pointer_declarator -- but for references.  ATTRIBUTES
+   represent the attributes that appertain to the pointer or
+   reference.  */
 
 cp_declarator *
 make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
-			   bool rvalue_ref)
+			   bool rvalue_ref, tree attributes)
 {
   cp_declarator *declarator;
 
@@ -1321,15 +1328,19 @@ make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
   else
     declarator->parameter_pack_p = false;
 
+  declarator->std_attributes = attributes;
+
   return declarator;
 }
 
 /* Like make_pointer_declarator -- but for a pointer to a non-static
-   member of CLASS_TYPE.  */
+   member of CLASS_TYPE.  ATTRIBUTES represent the attributes that
+   appertain to the pointer or reference.  */
 
 cp_declarator *
 make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
-			cp_declarator *pointee)
+			cp_declarator *pointee,
+			tree attributes)
 {
   cp_declarator *declarator;
 
@@ -1346,6 +1357,8 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
   else
     declarator->parameter_pack_p = false;
 
+  declarator->std_attributes = attributes;
+
   return declarator;
 }
 
@@ -1853,7 +1866,7 @@ static void cp_parser_lambda_body
 static void cp_parser_statement
   (cp_parser *, tree, bool, bool *);
 static void cp_parser_label_for_labeled_statement
-  (cp_parser *);
+(cp_parser *, tree);
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
@@ -1957,7 +1970,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
@@ -2099,9 +2112,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 *);
@@ -2308,7 +2341,7 @@ static bool cp_parser_is_keyword
 static tree cp_parser_make_typename_type
   (cp_parser *, tree, tree, location_t location);
 static cp_declarator * cp_parser_make_indirect_declarator
-  (enum tree_code, tree, cp_cv_quals, cp_declarator *);
+ (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree);
 
 /* Returns nonzero if we are parsing tentatively.  */
 
@@ -3178,24 +3211,30 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope,
    make_{pointer,ptrmem,reference}_declarator functions that decides
    which one to call based on the CODE and CLASS_TYPE arguments. The
    CODE argument should be one of the values returned by
-   cp_parser_ptr_operator. */
+   cp_parser_ptr_operator.  ATTRIBUTES represent the attributes that
+   appertain to the pointer or reference.  */
+
 static cp_declarator *
 cp_parser_make_indirect_declarator (enum tree_code code, tree class_type,
 				    cp_cv_quals cv_qualifiers,
-				    cp_declarator *target)
+				    cp_declarator *target,
+				    tree attributes)
 {
   if (code == ERROR_MARK)
     return cp_error_declarator;
 
   if (code == INDIRECT_REF)
     if (class_type == NULL_TREE)
-      return make_pointer_declarator (cv_qualifiers, target);
+      return make_pointer_declarator (cv_qualifiers, target, attributes);
     else
-      return make_ptrmem_declarator (cv_qualifiers, class_type, target);
+      return make_ptrmem_declarator (cv_qualifiers, class_type,
+				     target, attributes);
   else if (code == ADDR_EXPR && class_type == NULL_TREE)
-    return make_reference_declarator (cv_qualifiers, target, false);
+    return make_reference_declarator (cv_qualifiers, target,
+				      false, attributes);
   else if (code == NON_LVALUE_EXPR && class_type == NULL_TREE)
-    return make_reference_declarator (cv_qualifiers, target, true);
+    return make_reference_declarator (cv_qualifiers, target,
+				      true, attributes);
   gcc_unreachable ();
 }
 
@@ -5605,6 +5644,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,
@@ -6849,13 +6895,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))
     {
@@ -6864,8 +6910,10 @@ 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
-	(code, type, cv_quals, declarator);
+      declarator = cp_parser_make_indirect_declarator
+	(code, type, cv_quals, declarator, std_attributes);
+
+      return declarator;
     }
 
   /* If the next token is a `[', there is a direct-new-declarator.  */
@@ -8604,6 +8652,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:
@@ -8620,15 +8680,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.  */
@@ -8646,7 +8711,7 @@ 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.  */
-	  cp_parser_label_for_labeled_statement (parser);
+	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  goto restart;
 
 	case RID_IF:
@@ -8709,7 +8774,8 @@ 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.  */
-	  cp_parser_label_for_labeled_statement (parser);
+
+	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  goto restart;
 	}
     }
@@ -8745,6 +8811,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);
@@ -8759,6 +8833,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.
@@ -8775,7 +8856,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
    have to return the label.  */
 
 static void
-cp_parser_label_for_labeled_statement (cp_parser* parser)
+cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
 {
   cp_token *token;
   tree label = NULL_TREE;
@@ -8855,21 +8936,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;
 }
 
@@ -10295,8 +10378,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
@@ -10526,6 +10608,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
@@ -10560,6 +10643,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;
 
@@ -10573,7 +10657,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
   while (true)
     {
       bool constructor_p;
-      bool found_decl_spec;
       cp_token *token;
       ds = ds_last;
 
@@ -10585,12 +10668,55 @@ 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. In that case
+	     [dcl.spec]/1 says:
+
+	         The attribute-specifier-seq affects the type only for
+		 the declaration it appears in, not other declarations
+		 involving the same type.
+
+             But for now let's force the user to position the
+             attribute either at the beginning of the declaration or
+             after the declarator-id, which would clearly mean that it
+             applies to the declarator.  */
+	  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
+		{
+		  if (decl_specs->type && CLASS_TYPE_P (decl_specs->type))
+		    {
+		      /*  This is an attribute following a
+			  class-specifier.  */
+		      if (decl_specs->type_definition_p)
+			warn_misplaced_attr_for_class_type (token->location,
+							    decl_specs->type);
+		      attrs = NULL_TREE;
+		    }
+		  else
+		    {
+		      decl_specs->std_attributes
+			= chainon (decl_specs->std_attributes,
+				   attrs);
+		      if (decl_specs->locations[ds_std_attribute] == 0)
+			decl_specs->locations[ds_std_attribute] = token->location;
+		    }
+		  continue;
+		}
+	    }
+
+	    decl_specs->attributes
+	      = chainon (decl_specs->attributes,
+			 attrs);
 	  if (decl_specs->locations[ds_attribute] == 0)
 	    decl_specs->locations[ds_attribute] = token->location;
 	  continue;
@@ -11317,13 +11443,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))
     {
@@ -11332,8 +11459,10 @@ 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
-	(code, class_type, cv_quals, declarator);
+      declarator = cp_parser_make_indirect_declarator
+	(code, class_type, cv_quals, declarator, std_attributes);
+
+      return declarator;
    }
 
   return NULL;
@@ -13161,7 +13290,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     {
       tree type;
 
-      type = check_tag_decl (&decl_specifiers);
+      type = check_tag_decl (&decl_specifiers,
+			     /*explicit_type_instantiation_p=*/true);
       /* Turn access control back on for names used during
 	 template instantiation.  */
       pop_deferring_access_checks ();
@@ -14592,7 +14722,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,
@@ -15494,7 +15624,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;
@@ -15560,22 +15690,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);
@@ -15904,7 +16032,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.  */
@@ -15912,14 +16040,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))
     {
@@ -15945,7 +16075,7 @@ cp_parser_declarator (cp_parser* parser,
 	declarator = NULL;
 
       declarator = cp_parser_make_indirect_declarator
-	(code, class_type, cv_quals, declarator);
+	(code, class_type, cv_quals, declarator, std_attributes);
     }
   /* Everything else is a direct-declarator.  */
   else
@@ -15958,9 +16088,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;
 }
 
@@ -16100,6 +16229,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 		  cp_virt_specifiers virt_specifiers;
 		  tree exception_specification;
 		  tree late_return;
+		  tree attrs;
 
 		  is_declarator = true;
 
@@ -16113,6 +16243,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));
 
@@ -16126,6 +16258,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.  */
@@ -16175,10 +16308,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;
@@ -16231,13 +16365,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;
@@ -16304,6 +16441,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)
 	      {
@@ -16418,6 +16557,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;
 
@@ -16465,9 +16605,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:
 
@@ -16487,10 +16629,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;
@@ -16521,6 +16665,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
     {
@@ -16558,6 +16706,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);
 	    }
@@ -16917,7 +17069,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,
@@ -18023,7 +18175,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)
@@ -18044,6 +18196,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:
@@ -18894,8 +19052,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))
@@ -18927,7 +19083,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	  friend_p = cp_parser_friend_p (&decl_specifiers);
 	  /* If there were decl-specifiers, check to see if there was
 	     a class-declaration.  */
-	  type = check_tag_decl (&decl_specifiers);
+	  type = check_tag_decl (&decl_specifiers,
+				 /*explicit_type_instantiation_p=*/false);
 	  /* Nested classes have already been added to the class, but
 	     a `friend' needs to be explicitly registered.  */
 	  if (friend_p)
@@ -18994,6 +19151,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);
 
@@ -20100,6 +20263,80 @@ 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:
@@ -20108,10 +20345,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;
 
@@ -20137,7 +20374,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.  */
@@ -20158,7 +20395,7 @@ cp_parser_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
-/* Parse an attribute-list.
+/* Parse a GNU attribute-list.
 
    attribute-list:
      attribute
@@ -20176,7 +20413,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;
@@ -20255,6 +20492,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 = NULL_TREE, 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 if (token->flags & NAMED_OP)
+    attr_id = get_identifier (cpp_type2name (token->type, token->flags));
+
+  if (attr_id == NULL_TREE)
+    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 clause 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;
+
+      /* 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);
+
+      /* 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/typeck.c b/gcc/cp/typeck.c
index ad4b090..4a518cc 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1701,6 +1701,56 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain)
   else
     return cxx_alignof_expr (e, complain? tf_warning_or_error : tf_none);
 }
+
+/*  Build a representation of an expression 'alignas(E).'  Return the
+    folded integer value of E if it is an integral constant expression
+    that resolves to a valid alignment.  If E depends on a template
+    parameter, return a syntactic representation tree of kind
+    ALIGNOF_EXPR.  Otherwise, return an error_mark_node if the
+    expression is ill formed, or NULL_TREE if E is NULL_TREE.  */
+
+tree
+cxx_alignas_expr (tree e)
+{
+  if (e == NULL_TREE || e == error_mark_node
+      || (!TYPE_P (e) && !require_potential_rvalue_constant_expression (e)))
+    return e;
+  
+  if (TYPE_P (e))
+    /* [dcl.align]/3:
+       
+	   When the alignment-specifier is of the form
+	   alignas(type-id ), it shall have the same effect as
+	   alignas( alignof(type-id )).  */
+
+    return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, false);
+  
+
+  /* If we reach this point, it means the alignas expression if of
+     the form "alignas(assignment-expression)", so we should follow
+     what is stated by [dcl.align]/2.  */
+
+  e = mark_rvalue_use (e);
+
+  /* [dcl.align]/2 says:
+
+         the assignment-expression shall be an integral constant
+	 expression.  */
+  
+  e = fold_non_dependent_expr (e);
+  if (value_dependent_expression_p (e))
+    /* Leave value-dependent expression alone for now. */;
+  else
+    e = cxx_constant_value (e);
+
+  if (e == NULL_TREE
+      || e == error_mark_node
+      || TREE_CODE (e) != INTEGER_CST)
+    return error_mark_node;
+
+  return e;
+}
+
 \f
 /* 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..c514e67 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 *,
+							     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..a55698c
--- /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 "ignored" }
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.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..4adefdb
--- /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..636f9a9
--- /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..566461b0
--- /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-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
new file mode 100644
index 0000000..2f47b32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
@@ -0,0 +1,3 @@
+// { dg-do compile { target c++11 } }
+
+struct [[gnu::unused]] A {};
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..2d5ad04
--- /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 b [[gnu::aligned (16)]];
+};
+
+struct T
+{
+  char a;
+  void * b [[gnu::aligned (16)]];
+};
+
+static_assert (sizeof (S) == sizeof (T),
+	       "struct S and T should have the same size");
+
+static_assert (sizeof (S) == 32, "sizeof (S) == 8 + 16 + 8");
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..4c07df9
--- /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 "ignored" }
+}
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..f3da452
--- /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 [[gnu::warn_unused_result]] (char *) ;
+extern int f2 [[gnu::warn_unused_result]] (char *) throw () ;
+extern int f2 (char *) throw ();
+
+extern int f3 [[gnu::nonnull (1)]] (char *) ;
+extern int f4 [[gnu::nonnull (1)]] (char *) throw ();
+extern int f4 (char *) throw ();
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..edd1067
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C
@@ -0,0 +1,22 @@
+// Test that attributes work in a variety of situations.
+// { dg-options "-O -ftrack-macro-expansion=0" }
+// { dg-do run { target c++11 } }
+
+#define attrib [[gnu::mode (QI)]]
+#define gnu_attrib __attribute((mode (QI)))
+
+attrib signed int a;
+static unsigned int b attrib;
+
+int foo(attrib int o)
+{
+  return (sizeof (a) != 1
+	  || sizeof (b) != 1
+	  || sizeof (o) != 1
+	  || sizeof ((gnu_attrib signed int) b) != 1);
+}
+
+int main ()
+{
+  return foo (42);
+}
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..537dec5
--- /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 "ignored" }
+
+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..f344661
--- /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 "ignored" }
+
+static void foo(U) {}
+static void foo(int) {}
+
+void bar()
+{
+  foo(0);
+}
+
+typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" }
+
+static void foo2(U1) {}		// { dg-error "previously defined" }
+static void foo2(U2) {}		// { dg-error "redefinition" }
+
+void bar2(U1 u1, U2 u2)
+{
+  foo2(u1);
+  foo2(u2);
+}
+
+// PR c++/36410
+struct A
+{
+  typedef union [[gnu::transparent_union]]
+  {
+    int i;
+  } B;
+};
+
+void foo(A::B b)
+{
+  b.i;
+}
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..2aae9ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+
+struct S;
+
+typedef int (*F [[gnu::warn_unused_result]]) (int);
+
+typedef int (*F2 [[gnu::warn_unused_result]]) (int);
+
+typedef int (S::*F3 [[gnu::warn_unused_result]]) (int); // { dg-warning "only applies to function types" }
+
+typedef int [[gnu::warn_unused_result]] (*F5) (int); // { dg-warning "ignored" }
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..3db981a
--- /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 "ignored" }
+};
+
+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..453fc01
--- /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-warning "ignored" }
+  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..bad33d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -0,0 +1,30 @@
+// { dg-options "-std=c++11 -Wunused -pedantic-errors" }
+// { dg-do compile }
+// Test for syntax support of various attribute permutations.
+
+int
+[[gnu::noreturn]] // { dg-warning "ignored" }
+one
+[[gnu::unused]]
+(void);
+
+int one_third [[gnu::noreturn]] [[gnu::unused]] (void);
+
+int [[gnu::unused]] one_half(); // { dg-warning "ignored" }
+
+static
+[[gnu::noreturn]] // { dg-warning "ignored" }
+void two [[gnu::unused]] (void) {}
+
+
+
+[[gnu::unused]]
+int
+five(void)
+[[gnu::noreturn]] // { dg-warning "ignored" }
+{}
+
+[[gnu::noreturn]]
+void
+six (void)
+;
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..c850622
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
@@ -0,0 +1,4 @@
+// { dg-do compile { target c++11 } }
+template <class T> struct A { };
+
+template [[gnu::packed]] struct A<int>;  // { dg-warning "ignored in explicit instantiation" }
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..81d70e5
--- /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 "ignored in declaration" }
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-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
new file mode 100644
index 0000000..4a5d73a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+int
+foo ()
+{
+  int i [[and, bitor, xor_eq, compl, bitand]]; // { dg-warning "ignored" }
+  i = 0;
+  return i;
+}
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..83de121
--- /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..0f87fd4
--- /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;}  a [[gnu::aligned(16)]];
+struct B {int i;} __attribute__((aligned(16))) b;
+
+int
+main ()
+{
+ A aa;
+ B bb;
+
+ static_assert (sizeof (a) == 4, "sizeof (a) should be 4");
+ static_assert (sizeof (b) == 16, "sizeof (b) should be 16");
+ static_assert (sizeof (aa) == 4, "sizeof (aa) should be 4");
+ static_assert (sizeof (bb) == 16, "sizeof (bb) should be 16");
+
+ static_assert (__alignof__  (a) == 16, "alignof (a) should be 16");
+ static_assert (__alignof__  (b) == 16, "alignof (b) should be 16");
+ static_assert (__alignof__  (aa) == 4, "alignof (aa) should be 4");
+ static_assert (__alignof__  (bb) == 16, "alignof (bb) should be 16");
+}
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..723c8ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
@@ -0,0 +1,39 @@
+// { dg-do compile { target c++11 } }
+
+int
+toto ()
+{
+  [[gnu::unused]] good:
+    return 0;
+}
+
+int
+foo ()
+{
+  [[gnu::unused]] good:
+    int i = 0;
+
+  // A C++11 attribute at the beginning of the return statement is
+  // syntactically correct, appertains to the return statement (not to
+  // the label) but is currently ignored by this implementation.
+ good_ignored : [[gnu::unused]] // { dg-warning "attributes at the beginning of statement are ignored" }
+    return i;
+}
+
+int
+bar ()
+{
+  // A GNU attribute after the label appertains to the label.
+ good: __attribute__((unused));
+  return 0;
+}
+
+int
+baz ()
+{
+  // The c++ attribute after the label appertains to the (empty)
+  // statement.
+ bad: [[gnu::unused]]; // { dg-warning "attributes at the beginning of statement are ignored" }
+  return 0;
+}
+
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 a7492de..82ec551 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4351,7 +4351,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;
 
@@ -4365,7 +4365,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;
 
@@ -5288,11 +5288,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
@@ -5300,7 +5301,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)
@@ -5330,10 +5331,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
@@ -5343,11 +5345,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] == '_'
@@ -5356,7 +5358,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] == '_'
@@ -5386,7 +5388,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);
@@ -5423,9 +5425,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)
 		{
@@ -6347,7 +6351,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;
 }
 
@@ -6384,7 +6388,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))
     ;
@@ -6399,9 +6403,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 f9c9a7f..0253f0f 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4892,12 +4892,12 @@ struct attribute_spec
 {
   /* The name of the attribute (without any leading or trailing __),
      or NULL to mark the end of a table of attributes.  */
-  const char *const name;
+  const char *name;
   /* The minimum length of the list of arguments of the attribute.  */
-  const int min_length;
+  int min_length;
   /* The maximum length of the list of arguments of the attribute
      (-1 for no maximum).  */
-  const int max_length;
+  int max_length;
   /* Whether this attribute requires a DECL.  If it does, it will be passed
      from types of DECLs, function return types and array element types to
      the DECLs, function types and array types respectively; but when
@@ -4905,15 +4905,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
@@ -4928,10 +4928,10 @@ struct attribute_spec
      otherwise the return value should be NULL_TREE.  This pointer may be
      NULL if no special handling is required beyond the checks implied
      by the rest of this structure.  */
-  tree (*const handler) (tree *node, tree name, tree args,
-				 int flags, bool *no_add_attrs);
+  tree (*handler) (tree *node, tree name, tree args,
+		   int flags, bool *no_add_attrs);
   /* Specifies if attribute affects type's identity.  */
-  const bool affects_type_identity;
+  bool affects_type_identity;
 };
 
 /* Flags that may be passed in the third argument of decl_attributes, and
@@ -4956,7 +4956,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.  */
@@ -6042,6 +6044,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);
 
@@ -6055,6 +6059,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 */
-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-09-18 13:52               ` Dodji Seketeli
@ 2012-09-18 16:53                 ` Jason Merrill
  2012-09-20  7:51                   ` Dodji Seketeli
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2012-09-18 16:53 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

On 09/18/2012 09:51 AM, Dodji Seketeli wrote:
> +      VEC_safe_push (scoped_attributes, heap, attributes_table, sa);
> +      result = &VEC_last (scoped_attributes, attributes_table);

Here you can set result from the return value of VEC_safe_push.

> +      if ((flags & ATTR_FLAG_CXX11)
> +	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE
> +	       && (TREE_CODE (*node) == RECORD_TYPE
> +		   || TREE_CODE (*node) == UNION_TYPE)))
> +	{
> +	  /* unused is being used as a c++11 attribute.  In this mode
> +	     we prevent it from applying to types, unless it's for a
> +	     class defintion.  */
> +	  warning (OPT_Wattributes,
> +		   "attribute %qE cannot be applied to a non-class type", name);
> +	  return NULL_TREE;
> +	}

I think this should now be covered by the general ignoring of attributes 
that appertain to type-specifiers, so we don't need to check it here.

> +      error ("requested alignment %d is larger than %d",
> +	     requested_alignment, max_align);

Let's make this a pedwarn.

> +cxx_fundamental_alignment_p  (unsigned align)
> +{
> +
> +  return (align <=  MAX (TYPE_ALIGN (long_long_integer_type_node),
> +			 TYPE_ALIGN (long_double_type_node)));
> +}

Unneeded blank line.

> +		      inform (token->location,
> +			      "an attribute for a declaration should be either "
> +			      "at the begining of the declaration or after "
> +			      "the declarator-id");

Putting this code here means that we give the diagnostic for attributes 
in the decl-specifier-seq, but not for attributes that apply to type 
parts of the declarator such as a ptr-operator or a function declarator. 
  I think the best place to implement this in decl_attributes; there you 
can just ignore any attributes applied to a type without 
ATTR_FLAG_TYPE_IN_PLACE.

> +      declarator = cp_parser_make_indirect_declarator
>  	(code, type, cv_quals, declarator);
> +      if (declarator != NULL && declarator != cp_error_declarator)
> +	declarator->attributes = std_attributes;

Let's pass std_attributes to make_indirect_declarator.

>        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;

Here too.

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

Unneeded newline.

> +	  alignas_expr =
> +	    cp_parser_assignment_expression (parser, /*cast_p=*/false,
> +					     /**cp_id_kind=*/NULL);

Let's require_potential_rvalue_constant_expression here or in 
cxx_alignas_expr.

> +      alignas_expr = fold_non_dependent_expr (alignas_expr);

You don't need this both in the parser and in cxx_alignas_expr.

> +cxx_alignas_expr (tree e, tsubst_flags_t complain)

I don't think you need the complain parameter anymore, so you don't need 
to make fold_non_dependent_expr_sfinae non-static either.

> +  /* [dcl.align]/2 says:
> +
> +     [the assignment-expression shall be an integral constant
> +      expression].  */
> +  e = fold_non_dependent_expr_sfinae (e, complain);
> +  if (e == NULL_TREE
> +      || e == error_mark_node
> +      || TREE_CODE (e) != INTEGER_CST)
> +    return error_mark_node;

This needs to allow value-dependent expressions.  I'd say

e = fold_non_dependent_expr (e);
if (value_dependent_expression_p (e))
   /* Leave value-dependent expression alone for now. */;
else
   e = cxx_constant_value (e);

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-09-17 18:34             ` Jason Merrill
@ 2012-09-18 13:52               ` Dodji Seketeli
  2012-09-18 16:53                 ` Jason Merrill
  0 siblings, 1 reply; 22+ messages in thread
From: Dodji Seketeli @ 2012-09-18 13:52 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

> Did you send me an old patch by mistake?

Yes, sorry for that.  I am replying here to the comments that apply to
the new patch I should have sent, and I am sending you that new patch,
hopefully appropriately amended.


> > +	  found_attrs = true;
> 
> You don't need a separate found_attrs variable; you can just check
> whether attrs is set or not.  VEC_iterate sets the element pointer to
> NULL at the end of the vector.  You should also be able to share more
> of the code between the cases where you do or do not already have the
> appropriate namespace set up.
> 

Done.

> > +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);
> > +      }
> 
> Rather than write the code to search the table in two places, let's
> call this function from register_scoped_attributes.
> 
> You don't need to do another VEC_index since you already have the
> pointer you want in 'iter'.

Done.

> > +attributes_array_length (const struct attribute_spec *attributes_array)
> 
> Rather than calculate this first and then pass it to
> register_scoped_attributes, why not just have
> register_scoped_attributes stop at a null entry?

Fixed.

> > +  if (name_space->attribute_hash == NULL)
> > +   name_space->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
> 
> Why do we need this both here and in find_attribute_namespace?

I have removed it from find_attribute_namespace.

> >  }
> > +/*
> > +   If in c++-11, check if the c++-11 alignment constraint with respect
> 
> Need a blank line after the }.

Fixed.



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

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

gcc/c-family/

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

gcc/cp/

	* cp-tree.h (enum cpp0x_warn_str::CPP0X_ATTRIBUTES): New member.
	(enum cp_decl_spec::ds_std_attribute): New enumerator.
	(struct cp_decl_specifier_seq::std_attributes): New field.
	(fold_non_dependent_expr_sfinae): This is now public.
	(cxx_alignas_expr, warn_misplaced_attr_for_class_type): Declare
	new functions.
	(check_tag_decl): Take an extra parameter for explicit
	instantiations.
	* decl.c (warn_misplaced_attr_for_class_type): Extract from ...
	(check_tag_decl): ... here.  Add check for c++11 attributes being
	applied to an explicit instantiation.  Take an extra parameter for
	explicit instantiations.
	(grokdeclarator): Make sure a c++11 attribute after an array
	declarator appertains to the array, an attribute after a function
	declarator appertains to the function type, an attribute after a
	declarator-id appertains to the entity being declared, and an
	attribute after a pointer declarator appertain to the pointer.
	* decl2.c (is_late_template_attribute): Use get_attribute_name.
	* error.c (maybe_warn_cpp0x): Support
	CPP0X_GENERALIZED_ATTRIBUTES.
	* parser.c (cp_next_tokens_can_be_attribute_p)
	(cp_next_tokens_can_be_gnu_attribute_p)
	(cp_next_tokens_can_be_std_attribute_p)
	(cp_nth_tokens_can_be_attribute_p)
	(cp_nth_tokens_can_be_gnu_attribute_p)
	(cp_nth_tokens_can_be_std_attribute_p)
	(cp_parser_gnu_attribute_list, cp_parser_std_attribute)
	(cp_parser_std_attribute_spec, cp_parser_std_attribute_spec_seq)
	(cp_parser_attributes_opt, cp_parser_std_attribute_list): New
	static functions.
	(cp_parser_gnu_attributes_opt): Replace cp_parser_attributes_opt.
	(cp_parser_gnu_attribute_list): Replace cp_parser_attribute_list.
	(cp_parser_postfix_expression): Disallow "[[" tokens here.
	(cp_parser_label_for_labeled_statement): Use take an extra
	parameter for attributes.
	(cp_parser_block_declaration): Use
	cp_nth_tokens_can_be_std_attribute_p here.
	(cp_parser_decl_specifier_seq): Likewise.  Forbid C++11 attributes
	in decl specifiers, unless it's at the very beginning of the
	declaration.  Emit proper warning about misplaced c++11 attributes.
	(cp_parser_explicit_instantiation): Adjust call to check_tag_decl.
	(cp_parser_init_declarator):  Parsing attributes here is no more a
	GNU extension in c++-11.
	(cp_parser_type_specifier_seq): Use
	cp_next_tokens_can_be_attribute_p.
	(cp_parser_direct_declarator): Likewise.  Hang c++11 attributes
	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, unless when calling
	cp_parser_label_for_labeled_statement.
	(cp_parser_label_for_labeled_statement): Take c++11 attributes
	in parameter.
	* semantics.c (potential_constant_expression_1): Likewise.
	* typeck.c (fundamental_alignment_p, cxx_alignas_expr): New public
	functions.
	* 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-2-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-3.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-4.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-5.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-6.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-7.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-8.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-9.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-10.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-11.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-12.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-13.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-14.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-15.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-16.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-17.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-18.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-19.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-20.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-21.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-22.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-23.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-24.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-25.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-26.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-27.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-28.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-29.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-30.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-31.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-32.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-33.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-34.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-35.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-36.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-36-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-37.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-38.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-39.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-39-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-40.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-41.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-42.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-43.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-44.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-45.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-46.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-47.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-47-1.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-48.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-49.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-50.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-51.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-52.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-53.C: Likewise.

WIP address last review comments
---
 gcc/attribs.c                               |  216 +++++++++-
 gcc/c-family/c-common.c                     |  134 ++++++-
 gcc/c-family/c-common.h                     |    1 +
 gcc/cp/cp-tree.h                            |   21 +-
 gcc/cp/decl.c                               |   85 ++++-
 gcc/cp/decl2.c                              |    2 +-
 gcc/cp/error.c                              |    5 +
 gcc/cp/parser.c                             |  615 ++++++++++++++++++++++++---
 gcc/cp/pt.c                                 |    2 +-
 gcc/cp/typeck.c                             |   44 ++
 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.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-1.C  |    3 +
 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    |   30 ++
 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   |    4 +
 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-1.C |    8 +
 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   |   39 ++
 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                                  |   30 +-
 71 files changed, 1872 insertions(+), 119 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.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-1.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-1.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.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

diff --git a/gcc/attribs.c b/gcc/attribs.c
index d3af414..ed4c4a3 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);
+DEF_VEC_ALLOC_O (attribute_spec, heap);
+
+/* Scoped attribute name representation.  */
+
+struct scoped_attributes
+{
+  const char *ns;
+  VEC (attribute_spec, heap) *attributes;
+  htab_t attribute_hash;
+};
+
+DEF_VEC_O (scoped_attributes);
+DEF_VEC_ALLOC_O (scoped_attributes, heap);
+
+/* The table of scope attributes.  */
+static VEC(scoped_attributes, heap) *attributes_table;
+
+static scoped_attributes* find_attribute_namespace (const char*);
+static void register_scoped_attribute (const struct attribute_spec *,
+				       scoped_attributes *);
+
 static bool attributes_initialized = false;
 
 /* Default empty table of attributes.  */
@@ -102,6 +121,65 @@ eq_attr (const void *p, const void *q)
   return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]);
 }
 
+/* Insert an array of attributes ATTRIBUTES into a namespace.  This
+   array must be NULL terminated.  NS is the name of attribute
+   namespace.  The function returns the namespace into which the
+   attributes have been registered.  */
+
+scoped_attributes*
+register_scoped_attributes (const struct attribute_spec * attributes,
+			    const char* ns)
+{
+  scoped_attributes *result = NULL;
+
+  /* See if we already have attributes in the namespace NS.  */
+  result = find_attribute_namespace (ns);
+
+  if (result == NULL)
+    {
+      /* We don't have any namespace NS yet.  Create one.  */
+      scoped_attributes sa;
+
+      if (attributes_table == NULL)
+	attributes_table = VEC_alloc (scoped_attributes, heap, 64);
+
+      memset (&sa, 0, sizeof (sa));
+      sa.ns = ns;
+      sa.attributes = VEC_alloc (attribute_spec, heap, 64);
+      VEC_safe_push (scoped_attributes, heap, attributes_table, sa);
+      result = &VEC_last (scoped_attributes, attributes_table);
+    }
+
+  /* Really add the attributes to their namespace now.  */
+  for (unsigned i = 0; attributes[i].name != NULL; ++i)
+    {
+      VEC_safe_push (attribute_spec, heap,
+		     result->attributes, attributes[i]);
+      register_scoped_attribute (&attributes[i], result);
+    }
+
+  gcc_assert (result != NULL);
+
+  return result;
+}
+
+/* Return the namespace which name is NS, NULL if none exist.  */
+
+static scoped_attributes*
+find_attribute_namespace (const char* ns)
+{
+  unsigned ix;
+  scoped_attributes *iter;
+
+  FOR_EACH_VEC_ELT (scoped_attributes, attributes_table, ix, iter)
+    if (ns == iter->ns
+	|| (iter->ns != NULL
+	    && ns != NULL
+	    && !strcmp (iter->ns, ns)))
+      return iter;
+  return NULL;
+}
+
 /* Initialize attribute tables, and make some sanity checks
    if --enable-checking.  */
 
@@ -109,7 +187,6 @@ void
 init_attributes (void)
 {
   size_t i;
-  int k;
 
   if (attributes_initialized)
     return;
@@ -181,12 +258,10 @@ init_attributes (void)
     }
 #endif
 
-  attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
-  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
-    for (k = 0; attribute_tables[i][k].name != NULL; k++)
-      {
-        register_attribute (&attribute_tables[i][k]);
-      }
+  for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
+    /* Put all the GNU attributes into the "gnu" namespace.  */
+    register_scoped_attributes (attribute_tables[i], "gnu");
+
   invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
   attributes_initialized = true;
 }
@@ -196,9 +271,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 *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 +295,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 *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);
+}
+
 \f
 /* 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 +350,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 +409,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 +422,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 +522,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 +610,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 6de2f1c..fa513a8 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 },
@@ -6588,6 +6589,18 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     }
   else
     {
+      if ((flags & ATTR_FLAG_CXX11)
+	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE
+	       && (TREE_CODE (*node) == RECORD_TYPE
+		   || TREE_CODE (*node) == UNION_TYPE)))
+	{
+	  /* unused is being used as a c++11 attribute.  In this mode
+	     we prevent it from applying to types, unless it's for a
+	     class defintion.  */
+	  warning (OPT_Wattributes,
+		   "attribute %qE cannot be applied to a non-class type", name);
+	  return NULL_TREE;
+	}
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
 	*node = build_variant_type_copy (*node);
       TREE_USED (*node) = 1;
@@ -6665,7 +6678,9 @@ handle_transparent_union_attribute (tree *node, tree name,
 
   *no_add_attrs = true;
 
-  if (TREE_CODE (*node) == TYPE_DECL)
+
+  if (TREE_CODE (*node) == TYPE_DECL
+      && ! (flags & ATTR_FLAG_CXX11))
     node = &TREE_TYPE (*node);
   type = *node;
 
@@ -7137,6 +7152,90 @@ check_user_alignment (const_tree align, bool allow_zero)
   return i;
 }
 
+/* 
+   If in c++-11, check if the c++-11 alignment constraint with respect
+   to fundamental alignment (in [dcl.align]) are satisfied.  If not in
+   c++-11 mode, does nothing.
+
+   [dcl.align]2/ says:
+
+   [* if the constant expression evaluates to a fundamental alignment,
+   the alignment requirement of the declared entity shall be the
+   specified fundamental alignment.
+
+   * if the constant expression evaluates to an extended alignment
+   and the implementation supports that alignment in the context
+   of the declaration, the alignment of the declared entity shall
+   be that alignment
+
+   * if the constant expression evaluates to an extended alignment
+   and the implementation does not support that alignment in the
+   context of the declaration, the program is ill-formed].  */
+
+static bool
+check_cxx_fundamental_alignment_constraints (tree node,
+					     unsigned align_log,
+					     int flags)
+{
+  bool alignment_too_large_p = false;
+  unsigned requested_alignment = 1U << align_log;
+  unsigned max_align = 0;
+
+  if ((!(flags & ATTR_FLAG_CXX11) && !warn_cxx_compat)
+      || (node == NULL_TREE || node == error_mark_node))
+    return true;
+
+  if (cxx_fundamental_alignment_p (requested_alignment))
+    return true;
+
+  if (DECL_P (node))
+    {
+      if (TREE_STATIC (node))
+	{
+	  /* For file scope variables and static members, the target
+	     supports alignments that are at most
+	     MAX_OFILE_ALIGNMENT.  */
+	  if (requested_alignment > (max_align = MAX_OFILE_ALIGNMENT))
+	    alignment_too_large_p = true;
+	}
+      else
+	{
+#ifdef BIGGEST_FIELD_ALIGNMENT
+#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_FIELD_ALIGNMENT
+#else
+#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_ALIGNMENT
+#endif
+	  /* For non-static members, the target supports either
+	     alignments that at most either BIGGEST_FIELD_ALIGNMENT
+	     if it is defined or BIGGEST_ALIGNMENT.  */
+	  max_align = MAX_TARGET_FIELD_ALIGNMENT;
+	  if (TREE_CODE (node) == FIELD_DECL
+	      && requested_alignment > (max_align = MAX_TARGET_FIELD_ALIGNMENT))
+	    alignment_too_large_p = true;
+#undef MAX_TARGET_FIELD_ALIGNMENT
+	  /* For stack variables, the target supports at most
+	     MAX_STACK_ALIGNMENT.  */
+	  else if (decl_function_context (node) != NULL
+		   && requested_alignment > (max_align = MAX_STACK_ALIGNMENT))
+	    alignment_too_large_p = true;
+	}
+    }
+  else if (TYPE_P (node))
+    {
+      /* Let's be liberal for types.  */
+      if (requested_alignment > (max_align = BIGGEST_ALIGNMENT))
+	alignment_too_large_p = true;
+    }
+
+  if (alignment_too_large_p)
+    {
+      error ("requested alignment %d is larger than %d",
+	     requested_alignment, max_align);
+    }
+
+  return !alignment_too_large_p;
+}
+
 /* Handle a "aligned" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -7160,7 +7259,8 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   else if (TYPE_P (*node))
     type = node, is_type = 1;
 
-  if ((i = check_user_alignment (align_expr, false)) == -1)
+  if ((i = check_user_alignment (align_expr, false)) == -1
+      || !check_cxx_fundamental_alignment_constraints (*node, i, flags))
     *no_add_attrs = true;
   else if (is_type)
     {
@@ -7190,6 +7290,17 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       error ("alignment may not be specified for %q+D", decl);
       *no_add_attrs = true;
     }
+  else if (DECL_USER_ALIGN (decl)
+	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
+    /* C++-11 [dcl.align/4]:
+
+           When multiple alignment-specifiers are specified for an
+	   entity, the alignment requirement shall be set to the
+	   strictest specified alignment.
+
+      This formally comes from the c++11 specification but we are
+      doing it for the GNU attribute syntax as well.  */
+    *no_add_attrs = true;
   else if (TREE_CODE (decl) == FUNCTION_DECL
 	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
     {
@@ -11154,4 +11265,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(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 9298e3d..87c1da8 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -790,6 +790,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 ded247d..f120d0b 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. */
@@ -4668,6 +4670,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.  */
@@ -4686,6 +4689,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;
@@ -4754,8 +4759,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;
@@ -5052,7 +5063,9 @@ extern tree build_cp_library_fn_ptr		(const char *, tree);
 extern tree push_library_fn			(tree, tree, tree);
 extern tree push_void_library_fn		(tree, tree);
 extern tree push_throw_library_fn		(tree, tree);
-extern tree check_tag_decl			(cp_decl_specifier_seq *);
+extern void warn_misplaced_attr_for_class_type  (source_location location,
+						 tree class_type);
+extern tree check_tag_decl			(cp_decl_specifier_seq *, bool);
 extern tree shadow_tag				(cp_decl_specifier_seq *);
 extern tree groktypename			(cp_decl_specifier_seq *, const cp_declarator *, bool);
 extern tree start_decl				(const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
@@ -5394,6 +5407,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);
@@ -5812,6 +5826,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 6b5b986..ecc8970 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4125,13 +4125,32 @@ fixup_anonymous_aggr (tree t)
     }
 }
 
+/* Warn for an attribute located at LOCATION that appertains to the
+   class type CLASS_TYPE that has not been properly placed after its
+   class-key, in it class-specifier.  */
+
+void
+warn_misplaced_attr_for_class_type (source_location location,
+				    tree class_type)
+{
+  gcc_assert (TAGGED_TYPE_P (class_type));
+
+  warning_at (location, OPT_Wattributes,
+	      "attribute ignored in declaration "
+	      "of %q#T", class_type);
+  inform (location,
+	  "attribute for %q#T must follow the %qs keyword",
+	  class_type, class_key_or_enum_as_string (class_type));
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
    just declares a tagged type or anonymous union.
 
    Returns the type declared; or NULL_TREE if none.  */
 
 tree
-check_tag_decl (cp_decl_specifier_seq *declspecs)
+check_tag_decl (cp_decl_specifier_seq *declspecs,
+		bool explicit_type_instantiation_p)
 {
   int saw_friend = decl_spec_seq_has_spec_p (declspecs, ds_friend);
   int saw_typedef = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
@@ -4240,10 +4259,22 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
 	/* For a template class (an explicit instantiation), use the
 	   current location.  */
 	loc = input_location;
-      warning_at (loc, OPT_Wattributes, "attribute ignored in declaration "
-		  "of %q#T", declared_type);
-      inform (loc, "attribute for %q#T must follow the %qs keyword",
-	      declared_type, class_key_or_enum_as_string (declared_type));
+
+      if (explicit_type_instantiation_p)
+	/* [dcl.attr.grammar]/4:
+
+	       No attribute-specifier-seq shall appertain to an explicit
+	       instantiation.  */
+	{
+	  warning_at (loc, OPT_Wattributes,
+		      "attribute ignored in explicit instantiation %q#T",
+		      declared_type);
+	  inform (loc,
+		  "no attribute can be applied to "
+		  "an explicit instantiation");
+	}
+      else
+	warn_misplaced_attr_for_class_type (loc, declared_type);
     }
 
   return declared_type;
@@ -4265,7 +4296,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
 tree
 shadow_tag (cp_decl_specifier_seq *declspecs)
 {
-  tree t = check_tag_decl (declspecs);
+  tree t = check_tag_decl (declspecs,
+			   /*explicit_type_instantiation_p=*/false);
 
   if (!t)
     return NULL_TREE;
@@ -9124,6 +9156,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)
@@ -9161,6 +9202,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:
@@ -9357,6 +9405,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;
 
@@ -9519,6 +9574,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;
 
@@ -9644,6 +9710,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 0df4613..065c436 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 30fa018..3dd37aa 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3372,6 +3372,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 e8c0378..886f54e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1231,6 +1231,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;
@@ -1853,7 +1854,7 @@ static void cp_parser_lambda_body
 static void cp_parser_statement
   (cp_parser *, tree, bool, bool *);
 static void cp_parser_label_for_labeled_statement
-  (cp_parser *);
+(cp_parser *, tree);
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
@@ -1957,7 +1958,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
@@ -2099,9 +2100,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 *);
@@ -5605,6 +5626,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,
@@ -6849,13 +6877,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))
     {
@@ -6864,8 +6892,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.  */
@@ -8604,6 +8635,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:
@@ -8620,15 +8663,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.  */
@@ -8646,7 +8694,7 @@ 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.  */
-	  cp_parser_label_for_labeled_statement (parser);
+	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  goto restart;
 
 	case RID_IF:
@@ -8709,7 +8757,8 @@ 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.  */
-	  cp_parser_label_for_labeled_statement (parser);
+
+	  cp_parser_label_for_labeled_statement (parser, std_attrs);
 	  goto restart;
 	}
     }
@@ -8745,6 +8794,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);
@@ -8759,6 +8816,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.
@@ -8775,7 +8839,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
    have to return the label.  */
 
 static void
-cp_parser_label_for_labeled_statement (cp_parser* parser)
+cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
 {
   cp_token *token;
   tree label = NULL_TREE;
@@ -8855,21 +8919,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;
 }
 
@@ -10295,8 +10361,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
@@ -10526,6 +10591,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
@@ -10560,6 +10626,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;
 
@@ -10573,7 +10640,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
   while (true)
     {
       bool constructor_p;
-      bool found_decl_spec;
       cp_token *token;
       ds = ds_last;
 
@@ -10585,12 +10651,55 @@ 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. In that case
+	     [dcl.spec]/1 says:
+
+	         The attribute-specifier-seq affects the type only for
+		 the declaration it appears in, not other declarations
+		 involving the same type.
+
+             But for now let's force the user to position the
+             attribute either at the beginning of the declaration or
+             after the declarator-id, which would clearly mean that it
+             applies to the declarator.  */
+	  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
+		{
+		  if (decl_specs->type && CLASS_TYPE_P (decl_specs->type))
+		    {
+		      /*  This is an attribute following a
+			  class-specifier.  */
+		      if (decl_specs->type_definition_p)
+			warn_misplaced_attr_for_class_type (token->location,
+							    decl_specs->type);
+		    }
+		  else
+		    {
+		      warning_at (token->location, OPT_Wattributes,
+			      "attribute ignored");
+		      inform (token->location,
+			      "an attribute for a declaration should be either "
+			      "at the begining of the declaration or after "
+			      "the declarator-id");
+		    }
+		  attrs = NULL_TREE;
+		}
+	    }
+
+	    decl_specs->attributes
+	      = chainon (decl_specs->attributes,
+			 attrs);
 	  if (decl_specs->locations[ds_attribute] == 0)
 	    decl_specs->locations[ds_attribute] = token->location;
 	  continue;
@@ -11317,13 +11426,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))
     {
@@ -11332,8 +11442,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;
@@ -13161,7 +13274,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     {
       tree type;
 
-      type = check_tag_decl (&decl_specifiers);
+      type = check_tag_decl (&decl_specifiers,
+			     /*explicit_type_instantiation_p=*/true);
       /* Turn access control back on for names used during
 	 template instantiation.  */
       pop_deferring_access_checks ();
@@ -14592,7 +14706,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,
@@ -15494,7 +15608,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;
@@ -15560,22 +15674,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);
@@ -15904,7 +16016,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.  */
@@ -15912,14 +16024,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))
     {
@@ -15946,6 +16060,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
@@ -15958,9 +16081,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;
 }
 
@@ -16100,6 +16222,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 		  cp_virt_specifiers virt_specifiers;
 		  tree exception_specification;
 		  tree late_return;
+		  tree attrs;
 
 		  is_declarator = true;
 
@@ -16113,6 +16236,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));
 
@@ -16126,6 +16251,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.  */
@@ -16175,10 +16301,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;
@@ -16231,13 +16358,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;
@@ -16304,6 +16434,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)
 	      {
@@ -16418,6 +16550,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;
 
@@ -16465,9 +16598,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:
 
@@ -16487,10 +16622,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;
@@ -16521,6 +16658,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
     {
@@ -16558,6 +16699,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);
 	    }
@@ -16917,7 +17062,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,
@@ -18023,7 +18168,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)
@@ -18044,6 +18189,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:
@@ -18894,8 +19045,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))
@@ -18927,7 +19076,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	  friend_p = cp_parser_friend_p (&decl_specifiers);
 	  /* If there were decl-specifiers, check to see if there was
 	     a class-declaration.  */
-	  type = check_tag_decl (&decl_specifiers);
+	  type = check_tag_decl (&decl_specifiers,
+				 /*explicit_type_instantiation_p=*/false);
 	  /* Nested classes have already been added to the class, but
 	     a `friend' needs to be explicitly registered.  */
 	  if (friend_p)
@@ -18994,6 +19144,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);
 
@@ -20100,6 +20256,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:
@@ -20108,10 +20339,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;
 
@@ -20137,7 +20368,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.  */
@@ -20158,7 +20389,7 @@ cp_parser_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
-/* Parse an attribute-list.
+/* Parse a GNU attribute-list.
 
    attribute-list:
      attribute
@@ -20176,7 +20407,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;
@@ -20255,6 +20486,276 @@ 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 = NULL_TREE, 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 if (token->flags & NAMED_OP)
+    attr_id = get_identifier (cpp_type2name (token->type, token->flags));
+
+  if (attr_id == NULL_TREE)
+    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 clause 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;
+
+      /* 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, tf_warning_or_error);
+      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 16952bf..bf1fdb1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5020,7 +5020,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 ad4b090..b0d2036 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1701,6 +1701,50 @@ 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 (TYPE_P (e))
+    /* [dcl.align]/3:
+       
+	   When the alignment-specifier is of the form
+	   alignas(type-id ), it shall have the same effect as
+	   alignas( alignof(type-id )).  */
+
+    return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, 
+				       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 = fold_non_dependent_expr_sfinae (e, complain);
+  if (e == NULL_TREE
+      || e == error_mark_node
+      || TREE_CODE (e) != INTEGER_CST)
+    return error_mark_node;
+
+  return e;
+}
+
 \f
 /* 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..c514e67 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 *,
+							     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.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..4adefdb
--- /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..636f9a9
--- /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..566461b0
--- /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-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
new file mode 100644
index 0000000..2f47b32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C
@@ -0,0 +1,3 @@
+// { dg-do compile { target c++11 } }
+
+struct [[gnu::unused]] A {};
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..2d5ad04
--- /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 b [[gnu::aligned (16)]];
+};
+
+struct T
+{
+  char a;
+  void * b [[gnu::aligned (16)]];
+};
+
+static_assert (sizeof (S) == sizeof (T),
+	       "struct S and T should have the same size");
+
+static_assert (sizeof (S) == 32, "sizeof (S) == 8 + 16 + 8");
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..a34ba4f
--- /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 non-class 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..9c036bf
--- /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 b attrib;
+
+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..537dec5
--- /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 "ignored" }
+
+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..f344661
--- /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 "ignored" }
+
+static void foo(U) {}
+static void foo(int) {}
+
+void bar()
+{
+  foo(0);
+}
+
+typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" }
+
+static void foo2(U1) {}		// { dg-error "previously defined" }
+static void foo2(U2) {}		// { dg-error "redefinition" }
+
+void bar2(U1 u1, U2 u2)
+{
+  foo2(u1);
+  foo2(u2);
+}
+
+// PR c++/36410
+struct A
+{
+  typedef union [[gnu::transparent_union]]
+  {
+    int i;
+  } B;
+};
+
+void foo(A::B b)
+{
+  b.i;
+}
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..0b87857
--- /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 "ignored" }
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..3db981a
--- /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 "ignored" }
+};
+
+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..453fc01
--- /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-warning "ignored" }
+  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..9583d51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -0,0 +1,30 @@
+// { dg-options "-std=c++11 -Wunused -pedantic-errors" }
+// { dg-do compile }
+// Test for syntax support of various attribute permutations.
+
+int
+[[gnu::noreturn]] // { dg-warning "ignored" }
+one
+[[gnu::unused]]
+(void);
+
+int one_third [[gnu::noreturn]] [[gnu::unused]] (void);
+
+int [[gnu::unused]] one_half(); // { dg-warning "ignored" }
+
+static
+[[gnu::noreturn]] // { dg-warning "ignored" }
+void two [[gnu::unused]] (void) {}
+
+
+
+[[gnu::unused]]
+int
+five(void)
+[[gnu::noreturn]] // { dg-warning "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..c850622
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C
@@ -0,0 +1,4 @@
+// { dg-do compile { target c++11 } }
+template <class T> struct A { };
+
+template [[gnu::packed]] struct A<int>;  // { dg-warning "ignored in explicit instantiation" }
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..81d70e5
--- /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 "ignored in declaration" }
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-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
new file mode 100644
index 0000000..4a5d73a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+int
+foo ()
+{
+  int i [[and, bitor, xor_eq, compl, bitand]]; // { dg-warning "ignored" }
+  i = 0;
+  return i;
+}
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..83de121
--- /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..0f87fd4
--- /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;}  a [[gnu::aligned(16)]];
+struct B {int i;} __attribute__((aligned(16))) b;
+
+int
+main ()
+{
+ A aa;
+ B bb;
+
+ static_assert (sizeof (a) == 4, "sizeof (a) should be 4");
+ static_assert (sizeof (b) == 16, "sizeof (b) should be 16");
+ static_assert (sizeof (aa) == 4, "sizeof (aa) should be 4");
+ static_assert (sizeof (bb) == 16, "sizeof (bb) should be 16");
+
+ static_assert (__alignof__  (a) == 16, "alignof (a) should be 16");
+ static_assert (__alignof__  (b) == 16, "alignof (b) should be 16");
+ static_assert (__alignof__  (aa) == 4, "alignof (aa) should be 4");
+ static_assert (__alignof__  (bb) == 16, "alignof (bb) should be 16");
+}
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..723c8ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C
@@ -0,0 +1,39 @@
+// { dg-do compile { target c++11 } }
+
+int
+toto ()
+{
+  [[gnu::unused]] good:
+    return 0;
+}
+
+int
+foo ()
+{
+  [[gnu::unused]] good:
+    int i = 0;
+
+  // A C++11 attribute at the beginning of the return statement is
+  // syntactically correct, appertains to the return statement (not to
+  // the label) but is currently ignored by this implementation.
+ good_ignored : [[gnu::unused]] // { dg-warning "attributes at the beginning of statement are ignored" }
+    return i;
+}
+
+int
+bar ()
+{
+  // A GNU attribute after the label appertains to the label.
+ good: __attribute__((unused));
+  return 0;
+}
+
+int
+baz ()
+{
+  // The c++ attribute after the label appertains to the (empty)
+  // statement.
+ bad: [[gnu::unused]]; // { dg-warning "attributes at the beginning of statement are ignored" }
+  return 0;
+}
+
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 a7492de..82ec551 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4351,7 +4351,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;
 
@@ -4365,7 +4365,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;
 
@@ -5288,11 +5288,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
@@ -5300,7 +5301,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)
@@ -5330,10 +5331,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
@@ -5343,11 +5345,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] == '_'
@@ -5356,7 +5358,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] == '_'
@@ -5386,7 +5388,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);
@@ -5423,9 +5425,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)
 		{
@@ -6347,7 +6351,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;
 }
 
@@ -6384,7 +6388,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))
     ;
@@ -6399,9 +6403,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 f9c9a7f..0253f0f 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4892,12 +4892,12 @@ struct attribute_spec
 {
   /* The name of the attribute (without any leading or trailing __),
      or NULL to mark the end of a table of attributes.  */
-  const char *const name;
+  const char *name;
   /* The minimum length of the list of arguments of the attribute.  */
-  const int min_length;
+  int min_length;
   /* The maximum length of the list of arguments of the attribute
      (-1 for no maximum).  */
-  const int max_length;
+  int max_length;
   /* Whether this attribute requires a DECL.  If it does, it will be passed
      from types of DECLs, function return types and array element types to
      the DECLs, function types and array types respectively; but when
@@ -4905,15 +4905,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
@@ -4928,10 +4928,10 @@ struct attribute_spec
      otherwise the return value should be NULL_TREE.  This pointer may be
      NULL if no special handling is required beyond the checks implied
      by the rest of this structure.  */
-  tree (*const handler) (tree *node, tree name, tree args,
-				 int flags, bool *no_add_attrs);
+  tree (*handler) (tree *node, tree name, tree args,
+		   int flags, bool *no_add_attrs);
   /* Specifies if attribute affects type's identity.  */
-  const bool affects_type_identity;
+  bool affects_type_identity;
 };
 
 /* Flags that may be passed in the third argument of decl_attributes, and
@@ -4956,7 +4956,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.  */
@@ -6042,6 +6044,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);
 
@@ -6055,6 +6059,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 */
-- 
1.7.7.6


-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-09-17 15:36           ` Dodji Seketeli
@ 2012-09-17 18:34             ` Jason Merrill
  2012-09-18 13:52               ` Dodji Seketeli
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2012-09-17 18:34 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

On 09/17/2012 11:35 AM, Dodji Seketeli wrote:
>> >And I wonder if we want to offer this as an optional warning for GNU
>    attribute syntax.
>
> What option would be used to control this optional feature?  Would
> you accept this a separate patch?

Let's not worry about this for now.

> +	  found_attrs = true;

You don't need a separate found_attrs variable; you can just check 
whether attrs is set or not.  VEC_iterate sets the element pointer to 
NULL at the end of the vector.  You should also be able to share more of 
the code between the cases where you do or do not already have the 
appropriate namespace set up.

> +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);
> +      }

Rather than write the code to search the table in two places, let's call 
this function from register_scoped_attributes.

You don't need to do another VEC_index since you already have the 
pointer you want in 'iter'.

> +attributes_array_length (const struct attribute_spec *attributes_array)

Rather than calculate this first and then pass it to 
register_scoped_attributes, why not just have register_scoped_attributes 
stop at a null entry?

> +  if (name_space->attribute_hash == NULL)
> +   name_space->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);

Why do we need this both here and in find_attribute_namespace?

>  }
> +/*
> +   If in c++-11, check if the c++-11 alignment constraint with respect

Need a blank line after the }.

>>> +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.
>
> Done.

I don't see that:

> +  if (alignment_too_large_p)
> +    error ("requested alignment is too large");

>> 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.
>
> Done.  I realized that I forgot to check for DECL_USER_ALIGNED there.
> Fixed too.

I don't see this either:

> +  else if (flags & ATTR_FLAG_CXX11
> +	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)

Did you send me an old patch by mistake?

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-08-23  3:29         ` Jason Merrill
@ 2012-09-17 15:36           ` Dodji Seketeli
  2012-09-17 18:34             ` Jason Merrill
  0 siblings, 1 reply; 22+ messages in thread
From: Dodji Seketeli @ 2012-09-17 15:36 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

> 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.

OK, I have forbidden c++11 attributes in declspecs altogether then.
They are parsed, a warning is emitted, and they are dropped on the
floor.

> 
> >>> 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.

Done.

> 
> > +  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.

Done.

> > +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.

Done.

> And I wonder if we want to offer this as an optional warning for GNU
  attribute syntax.

What option would be used to control this optional feature?  Would
you accept this a separate patch?

> 
> > +  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.

Done.  I realized that I forgot to check for DECL_USER_ALIGNED there.
Fixed too.

> > +      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)?

The only case I see where a c++11 attribute would follow the
class-specifier is when the attribute is part of a sequence of decl
specifier, following the type-specifier that happens to be a
class-specifier.  I am saying this because the production for the
class-specifier doesn't mention attributes coming after it.  Am I
missing a relevant production?

Now that I am preventing attributes from appearing among decl
specifiers, I think an attribute simply cannot come after a
class-specifier anymore.  So this warning in check_tag_decl is only
for the case where the attribute is at the beginning of the
declaration now.  I have thus re-instated the former warning message,
unless we are warning for an explicit instantiation like in
g++.dg/cpp0x/gen-attrs-43.C.

When the later case that you mention happens, the diagnostic is the
message from within cp_parser_decl_specifier_seq.

> 
> > +         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.

I didn't mean that the attributes were being applied to the label.
Just that for practical purposes (the purpose of handling both gnu and
c++11 attributes in the same function, namely
cp_parser_label_for_labeled_statement).  In the patch, I believe the
c++11 attributes are properly applied to the label, like what
g++.dg/cpp0x/gen-attrs-53.C shows.  I realize now that the comment in
that test might have been misleading.  I have updated it.

Anyhow, for more clarity, I changed this to just pass the attributes
to cp_parser_label_for_labeled_statement.

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

Fixed.

> 
> > +cp_parser_attributes_opt (cp_parser *parser)
> > +{
> > +
> 
> Extra newline.

Fixed.

> 
> > +  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"?

Of course not.  Good catch.  Looks like I dropped that case on the
floor.  Hopefully handled in the updated patch.  Thanks.

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

Fixed.

> > +      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?

Right, done.

> >   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?

Yes, fixed.

> 
> >       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.

Done.

> > +  if (TYPE_P (e))
> > +    {
> > +      e = mark_type_use (e);
> 
> mark_type_use is to be used on expressions, not types.

Removed.

> > +  float bar [[gnu::aligned(__alignof__(double))]];
> 
> Let's use alignof rather than __alignof__.

Fixed.
 
> > +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.

I removed these.  I was just tactically using the differences to test
that a given attribute, given its position was binding to the right
thing.

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

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.

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.
	* 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.
---
 gcc/attribs.c                               |  269 ++++++++++++-
 gcc/c-family/c-common.c                     |  108 +++++-
 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                             |  566 ++++++++++++++++++++++++--
 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.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    |   40 ++
 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-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 +-
 69 files changed, 1829 insertions(+), 104 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.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-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

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);
+}
+
 \f
 /* 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..fd135d5 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 },
@@ -6993,6 +6994,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 +7096,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 +7127,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 +11098,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..4247200 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.  */
@@ -8859,7 +8890,7 @@ 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;
 
@@ -10299,8 +10330,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 +10560,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 +10595,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 +10609,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 +10620,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 +11415,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 +11431,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 +14694,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 +15596,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 +15662,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 +16004,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 +16012,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 +16048,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 +16069,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 +16210,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 +16224,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 +16239,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 +16289,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 +16346,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 +16422,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 +16538,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 +16586,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 +16610,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 +16646,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 +16687,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 +17050,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 +18156,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 +18177,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:
@@ -20104,6 +20239,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 +20322,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 +20351,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 +20372,7 @@ cp_parser_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
-/* Parse an attribute-list.
+/* Parse a GNU attribute-list.
 
    attribute-list:
      attribute
@@ -20180,7 +20390,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 +20469,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;
+}
+
 \f
 /* 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.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..97d6037
--- /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);
+}
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..5ca1c7c
--- /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]];
+
+static void foo(U) {}
+static void foo(int) {}
+
+void bar()
+{
+  foo(0);
+}
+
+typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" }
+
+static void foo2(U1) {}		// { dg-error "previously defined" }
+static void foo2(U2) {}		// { dg-error "redefinition" }
+
+void bar2(U1 u1, U2 u2)
+{
+  foo2(u1);
+  foo2(u2);
+}
+
+// PR c++/36410
+struct A
+{
+  typedef union
+  {
+    int i;
+  } B [[gnu::transparent_union]];
+};
+
+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..699f1c9
--- /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 [[gnu::__stdcall__]] A(L *listener) = 0; // { dg-warning "only applies to function types" }
+    virtual void [[gnu::__stdcall__]] R(L *listener) = 0; // { dg-warning "only applies to function types" }
+};
+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..3895c27
--- /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 [[gnu::__stdcall__]] getS();
+
+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..06cee02
--- /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)]];
+};
+
+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..7be9476
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -0,0 +1,40 @@
+// { 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(); // We should warn for this, but
+                                // this would require more work.x
+
+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" }
+{ }
+
+
+int
+five(void)
+[[gnu::unused]]
+[[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..39a2263
--- /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 (sizeof (A) == sizeof (double),
+	       "size of struct A must be sizeof (double)");
+
+struct alignas (alignof (long double)) B {
+  layout_type member;
+};
+
+static_assert (sizeof (B) == sizeof (long double),
+	       "size of struct A must be sizeof (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..241a8e2
--- /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 (sizeof (A<int>) == sizeof (double),
+	       "size of struct A must be sizeof (double)");
+
+template<class> struct alignas (alignof (long double)) B {
+  layout_type member;
+};
+
+static_assert (sizeof (B<int>) == sizeof (long double),
+	       "size of struct A must be sizeof (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..91d36c2
--- /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 (sizeof (A<int>) == sizeof (double),
+	       "size of struct A must be sizeof (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 (sizeof (B<int>) == sizeof (long double),
+	       "size of struct A must be sizeof (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-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..db841ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+
+class [[gnu::unused]] C;
+struct [[gnu::unused]] S;
+union [[gnu::unused]] 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 */
-- 
1.7.7.6


-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-08-15  7:43       ` Dodji Seketeli
@ 2012-08-23  3:29         ` Jason Merrill
  2012-09-17 15:36           ` Dodji Seketeli
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2012-08-23  3:29 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-08-12  4:42     ` Jason Merrill
@ 2012-08-15  7:43       ` Dodji Seketeli
  2012-08-23  3:29         ` Jason Merrill
  0 siblings, 1 reply; 22+ messages in thread
From: Dodji Seketeli @ 2012-08-15  7:43 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

> > 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

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);
+}
+
 \f
 /* 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;
+}
+
 \f
 /* 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 */
-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-08-10 20:05   ` Dodji Seketeli
@ 2012-08-12  4:42     ` Jason Merrill
  2012-08-15  7:43       ` Dodji Seketeli
  0 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2012-08-12  4:42 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: Joseph S. Myers, Richard Henderson, GCC Patches

On 08/10/2012 04:04 PM, Dodji Seketeli wrote:
> In cp_parser_decl_specifier_seq, I first tried to apply the c++11
> attribute to the (already constructed) type it follows, like what you
> suggest.  But then I am getting the warning:
>
>     warning: ignoring attributes applied to 'A' after definition
>
> issued by build_type_attribute_qual_variant when called by
> decl_attribute.  Basically, this is because we are not allowed to
> build a distinct copy of a class type.

Right.

> 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.  Again, I don't think we want to extend the flexible 
binding of GNU attributes to C++11 attributes.

>>> +typedef union { int i; } U [[gnu::transparent_union]];
>>
>> For the same reason, this should also be rejected; the testcase should
>> put the attribute before the opening brace.  We accept this with
>> GNU-style attributes for backward compatibility, but there's no reason
>> to propagate that lossage into the new syntax.
>
> Syntactically, why can't we say that the attribute applies to the
> typedef?  My understanding is that this is syntactically allowed by
> the noptr-declarator production.

Yes, syntactically it's fine.  But semantically it doesn't make sense, 
because the attribute only applies to types, not declarations.  Even if 
we looked through typedefs, it would be applying an attribute to a class 
after its definition was complete.

> If you want the attribute to be rejected for this particular kind of
> cases, how would you like to do it?

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

> 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.

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-07-27 23:22 ` Jason Merrill
@ 2012-08-10 20:05   ` Dodji Seketeli
  2012-08-12  4:42     ` Jason Merrill
  0 siblings, 1 reply; 22+ messages in thread
From: Dodji Seketeli @ 2012-08-10 20:05 UTC (permalink / raw)
  To: Jason Merrill, Joseph S. Myers, Richard Henderson; +Cc: GCC Patches

Hello,

I am replying to Joseph, Richard and Jason in the same message, along
with the patch that hopefully addresses most of the concerns that were
raised.

"Joseph S. Myers" <joseph@codesourcery.com> writes:

> Do you handle how, in certain syntactic locations, a C++11 attribute binds 
> differently to a GNU attribute?  (I haven't studied the patch, so feel 
> free to point me to testcases it adds that verify such differences, if 
> applicable.)

> Do you handle how, in certain syntactic locations, a C++11 attribute binds 
> differently to a GNU attribute?  (I haven't studied the patch, so feel 
> free to point me to testcases it adds that verify such differences, if 
> applicable.)

This is a broad question.  :-)

Here is how I'd synthesize the big differences between the two kinds
of attributes.

In a sequence of declaration specifiers, a c++11 attribute usually
applies to the type that precedes it and only for the current
declaration.  For class/enum types, when the attribute is in the
class-head it applies to the type for any subsequent use of that type.
When the attribute follows a declarator, it applies to the entity or
type being declared.  Last, when a c++11 attribute starts a
declaration, it applies to the entity being declared, even though the
declarator-id for that entity might be on the far right of the
declaration.


A GNU attribute that appears in a sequence of declaration specifiers
or that starts a declaration applies to the entity being declared.  In
a declarator, what the attribute applies to varies depending on the
particular kind of declarator.

Examples of tests that exhibit these differences in bindings in the
updated patch below are:

    g++.dg/cpp0x/gen-attrs-1.C          vs g++.dg/ext/attrib1.C
    g++.dg/cpp0x/gen-attrs-3.C          vs g++.dg/ext/attrib3.C
    g++.dg/cpp0x/gen-attrs-4.C          vs g++.dg/ext/attrib4.C
    g++.dg/cpp0x/gen-attrs-{6,6-1}.C    vs g++.dg/ext/attrib6.C
    g++.dg/cpp0x/gen-attrs-8.C          vs g++.dg/ext/attrib8.C
    g++.dg/cpp0x/gen-attrs-13-1.C       vs g++.dg/ext/attrib13.C
    g++.dg/cpp0x/gen-attrs-30.C         vs g++.dg/ext/attrib30.C
    g++.dg/cpp0x/gen-attrs-33.C         vs g++.dg/ext/attrib33.C
    g++.dg/cpp0x/gen-attrs-34.C         vs g++.dg/ext/attrib34.C
    g++.dg/cpp0x/gen-attrs-{36,36-1}.C  vs g++.dg/ext/attrib36.C
    g++.dg/cpp0x/gen-attrs-37.C         vs g++.dg/ext/attrib37.C
    g++.dg/cpp0x/gen-attrs-38.C         vs g++.dg/ext/attrib38.C
    g++.dg/cpp0x/gen-attrs-{39,39-1}.C  vs g++.dg/ext/attrib39.C
    g++.dg/cpp0x/gen-attrs-41.C         vs g++.dg/ext/attrib41.C
    g++.dg/cpp0x/gen-attrs-43.C         vs g++.dg/ext/attrib43.C
    g++.dg/cpp0x/gen-attrs-44.C         vs g++.dg/ext/attrib44.C
    g++.dg/cpp0x/gen-attrs-52.C
    g++.dg/cpp0x/gen-attrs-53.C

Richard Henderson <rth@redhat.com> writes:

> > +      attributes_table->scoped = XRESIZEVEC (struct scoped_attributes,
> > +					     attributes_table->scoped,
> > +					     attributes_table->len + 1);
> 
> A good clue that you want VEC's instead, with VEC_safe_push.

OK.  While doing this, I realized that to write:

    DEF_VEC_O (attribute_spec_t);
    DEF_VEC_ALLOC_O (attribute_spec_t, heap);

We need attribute_spec_t (which is really struct attribute_spec) to be
"writable".  But in it current form in mainline, all of its fields are
const.  So I removed these consts from struct attribute_spec and did the
change you suggested in the patch below.


Jason Merrill <jason@redhat.com> writes:

> On 07/26/2012 11:19 AM, Dodji Seketeli wrote:
> > +// Example taken from dcl.attr.grammar:
> > +
> > +int p[10];
> > +void f()
> > +{
> > +    int x = 42, y[5];
> > +    /* Here, the '[[gnu::' should have introduced an attribute, ont a
> > +       lambda invocation an array subscripting expression.  */
> > +    int(p[[gnu::x] { return x; }()]); // { dg-error "expected|consecutive" }
> > +    /* Likewise, the '[[gnu::' is invalid here.  */
> > +    y[[gnu::] { return 2; }()] = 2; // { dg-error "expected|consecutive" }
> 
> The example in the standard doesn't have gnu:: in it.  Search and
> replace error?

Fixed.

> 
> > +      if (cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) == NULL
> > +         || cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) == NULL)
> 
> Let's use ! rather than == NULL so that these lines fit in 80 chars.

Fixed.

> > +      /* 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 : cxx_constant_value (e);
> 
> I think you want fold_non_dependent_expr_sfinae rather than
> cxx_constant_value.

Fixed.

> > +      /*
> > +        [dcl.align]/3
> 
> Extra newline.
> 
> > +int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...);
> 
> This seems wrong; you can't apply the format attribute to a pointer type.

Correct.  The issue here was that the c++11 attribute was being
wrongly bound to the function, like what is done for GNU attributes.

I have changed this in several steps:
 - I augmented the handling of the ptr-declarator construct to support
 parsing attributes that come after the pointer, unlike what is done
 for GNU attributes in that case.
 - I added  a std_attribute field to struct cp_declarator to
 stick the C++11 attributes parsed as part of the declarator
 constructs there.
 - I modified grokdeclarator to apply these c++11 attributes to the
 pointer type itself, rather than to the pointed to type.

> About your earlier question on IRC, the solution to the problem you're
> having with
> 
> > struct A {int i;} [[gnu::aligned(16)]] a;
> 
> is that C++11 attributes after the closing brace should not be passed
> to finish_struct.  Instead, we should apply them to the type (without
> TYPE_IN_PLACE) after the type is complete.

Yes, this is what I figured after we had the chat.  I have updated
the patch to just avoid parsing c++11 attributes as part of the class
specifier construct.  Rather, I am letting them be parsed as part of
the declarator specifiers, by cp_parser_decl_specifier_seq -- this
complies with the decl-specifier-seq production, btw.

In cp_parser_decl_specifier_seq, I first tried to apply the c++11
attribute to the (already constructed) type it follows, like what you
suggest.  But then I am getting the warning:

    warning: ignoring attributes applied to 'A' after definition

issued by build_type_attribute_qual_variant when called by
decl_attribute.  Basically, this is because we are not allowed to
build a distinct copy of a class type.

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.

I have added the test g++.dg/cpp0x/gen-attrs-52.C for this.

> 
> > +typedef union { int i; } U [[gnu::transparent_union]];
> 
> For the same reason, this should also be rejected; the testcase should
> put the attribute before the opening brace.  We accept this with
> GNU-style attributes for backward compatibility, but there's no reason
> to propagate that lossage into the new syntax.

Syntactically, why can't we say that the attribute applies to the
typedef?  My understanding is that this is syntactically allowed by
the noptr-declarator production.

If you want the attribute to be rejected for this particular kind of
cases, how would you like to do it?

> > +template<typename T> struct A
> > +{
> > +  void foo() const;
> > +} [[gnu::aligned(4)]];
> 
> Likewise.

Now in this case shadow_tag now kicks in and displays a meaningful
warning.  I have updated the test case accordingly.

> 
> > +  typedef void ([[gnu::__stdcall__]] T::*F) (L*);
> 
> I don't think a C++11 attribute can appear in this position.  I think
> it should be
> 
>  typedef void (T::*F)(L*) [[gnu::__stdcall__]]

Fixed.

> 
> > +    virtual void [[gnu::__stdcall__]] A(L *listener) = 0;
> 
> Similarly, here the stdcall attribute appertains to "void", which
> makes no sense.

Fixed.  I have added more test cases in g++.dg/cpp0x/gen-attrs-36-1.C.

> > +S [[gnu::__stdcall__]] getS();
> > +extern int * ([[gnu::stdcall]] *fooPtr)( void);
> > +int * [[gnu::stdcall]] myFn01( void) { return 0; }
> 
> Likewise.

Fixed.

> 
> > +  typedef [[gnu::aligned (16)]] struct {
> 
> This also seems ill-formed, as there are no type-specifiers before the
> attribute, so there's nothing for it to appertain to.

Fixed.

> > +int
> > +[[gnu::noreturn]]
> > +[[gnu::unused]]
> > +one(void); // OK
> 
> noreturn doesn't make sense for "int".  Nor does unused, really.
> C++11 attributes that appertain to the function must either come
> before any specifiers or after the declarator.

Fixed the noreturn case.  Now that c++11 attributes in declspecs apply
to the type that precedes them, the attribute is rejected at
application time b/c it has to be applied to a function declaration.
A warning is emitted.

For unused though, I am not sure how to do that in an appropriate
manner.  An idea?

> > +template
> > +[[gnu::packed]]
> > +struct A<int>;                 // { dg-warning "attribute" }
> 
> Here the patch is giving the wrong warning; it complains about
> applying the attribute to A<int>, but actually we should be warning
> about an attribute that would appertain to all the declarators in a
> declaration with no declarators for it to appertain to.

Fixed.

> 
> > +[[gnu::deprecated]] enum E { E0 };     // { dg-warning "attribute ignored in declaration of" }
> > +// { dg-message "must follow the" "" { target *-*-* } 3 }
> 
> Same here.

Fixed.
 
> > +         if (strcmp (attr_name, IDENTIFIER_POINTER (get_attribute_name (list))) == 0)
> > +      gcc_checking_assert (TREE_CODE (get_attribute_name (list)) == IDENTIFIER_NODE);
> > +             for (a = lookup_ident_attribute (get_attribute_name (a2), attributes);
> > +                  a = lookup_ident_attribute (get_attribute_name (a2), TREE_CHAIN (a)))
> 
> Line too long.

Fixed.

> 
> > +  /* A given attribute has been parsed as a C++-11 generalized
> > +     attribute.  */
> 
> Let's drop the word "generalized" throughout the patch.  I don't see
> how these attributes are any more generalized than GNU attributes; we
> should just describe them as C++11 attributes.

Done.

> > +cxx_11_attribute_p (const_tree attr)
> 
> Let's change cxx_11 to cxx11.

Done.

>> +  struct scoped_attributes *ns = set_attributes_namespace (attrs,
>> +                                                          attrs_len,
>> +                                                          name_space);
>> +  if (ns == NULL)
>> +    return NULL;
>> +
>> +  for (i = 0; i < attrs_len; ++i)
>> +    register_scoped_attribute (&attrs[i], ns);
>
> This looks kind of funny; setting their namespace and then registering
> them sound like the same thing.  Let's rename set_attributes_namespace
> to register_scoped_attributes and call register_scoped_attribute from
> there.

Done.

>> +      if (TREE_STATIC (node))
>> +       {
>> +         /* For file scope variables and static members, the target
>> +            supports alignments that are at most
>> +            MAX_OFILE_ALIGNMENT.  */
>
> I think this should check TREE_STATIC || DECL_EXTERNAL.

Done.

Patch tested on i686-pc-linux-gnu, x86_64-unknown-linux-gnu and
powerpc64-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.

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                     |  108 +++++-
 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    |   40 ++
 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, 1927 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

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);
+}
+
 \f
 /* 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..fd135d5 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 },
@@ -6993,6 +6994,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 +7096,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 +7127,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 +11098,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..eccf31b 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;
+}
+
 \f
 /* 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..97d6037
--- /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);
+}
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..5ca1c7c
--- /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]];
+
+static void foo(U) {}
+static void foo(int) {}
+
+void bar()
+{
+  foo(0);
+}
+
+typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" }
+
+static void foo2(U1) {}		// { dg-error "previously defined" }
+static void foo2(U2) {}		// { dg-error "redefinition" }
+
+void bar2(U1 u1, U2 u2)
+{
+  foo2(u1);
+  foo2(u2);
+}
+
+// PR c++/36410
+struct A
+{
+  typedef union
+  {
+    int i;
+  } B [[gnu::transparent_union]];
+};
+
+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..7be9476
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -0,0 +1,40 @@
+// { 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(); // We should warn for this, but
+                                // this would require more work.x
+
+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" }
+{ }
+
+
+int
+five(void)
+[[gnu::unused]]
+[[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..db841ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+
+class [[gnu::unused]] C;
+struct [[gnu::unused]] S;
+union [[gnu::unused]] 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 */
-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-07-26 15:20 Dodji Seketeli
                   ` (2 preceding siblings ...)
  2012-07-27 16:09 ` Jason Merrill
@ 2012-07-27 23:22 ` Jason Merrill
  2012-08-10 20:05   ` Dodji Seketeli
  3 siblings, 1 reply; 22+ messages in thread
From: Jason Merrill @ 2012-07-27 23:22 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

On 07/26/2012 11:19 AM, Dodji Seketeli wrote:
> +// Example taken from dcl.attr.grammar:
> +
> +int p[10];
> +void f()
> +{
> +    int x = 42, y[5];
> +    /* Here, the '[[gnu::' should have introduced an attribute, ont a
> +       lambda invocation an array subscripting expression.  */
> +    int(p[[gnu::x] { return x; }()]); // { dg-error "expected|consecutive" }
> +    /* Likewise, the '[[gnu::' is invalid here.  */
> +    y[[gnu::] { return 2; }()] = 2; // { dg-error "expected|consecutive" }

The example in the standard doesn't have gnu:: in it.  Search and 
replace error?

> +      if (cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) == NULL
> +         || cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) == NULL)

Let's use ! rather than == NULL so that these lines fit in 80 chars.

> +      /* 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 : cxx_constant_value (e);

I think you want fold_non_dependent_expr_sfinae rather than 
cxx_constant_value.

> +      /*
> +        [dcl.align]/3

Extra newline.

> +int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...);

This seems wrong; you can't apply the format attribute to a pointer type.

About your earlier question on IRC, the solution to the problem you're 
having with

> struct A {int i;} [[gnu::aligned(16)]] a;

is that C++11 attributes after the closing brace should not be passed to 
finish_struct.  Instead, we should apply them to the type (without 
TYPE_IN_PLACE) after the type is complete.

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

For the same reason, this should also be rejected; the testcase should 
put the attribute before the opening brace.  We accept this with 
GNU-style attributes for backward compatibility, but there's no reason 
to propagate that lossage into the new syntax.

> +template<typename T> struct A
> +{
> +  void foo() const;
> +} [[gnu::aligned(4)]];

Likewise.

> +  typedef void ([[gnu::__stdcall__]] T::*F) (L*);

I don't think a C++11 attribute can appear in this position.  I think it 
should be

  typedef void (T::*F)(L*) [[gnu::__stdcall__]]

> +    virtual void [[gnu::__stdcall__]] A(L *listener) = 0;

Similarly, here the stdcall attribute appertains to "void", which makes 
no sense.

> +S [[gnu::__stdcall__]] getS();
> +extern int * ([[gnu::stdcall]] *fooPtr)( void);
> +int * [[gnu::stdcall]] myFn01( void) { return 0; }

Likewise.

> +  typedef [[gnu::aligned (16)]] struct {

This also seems ill-formed, as there are no type-specifiers before the 
attribute, so there's nothing for it to appertain to.

> +int
> +[[gnu::noreturn]]
> +[[gnu::unused]]
> +one(void); // OK

noreturn doesn't make sense for "int".  Nor does unused, really.  C++11 
attributes that appertain to the function must either come before any 
specifiers or after the declarator.

> +template
> +[[gnu::packed]]
> +struct A<int>;                 // { dg-warning "attribute" }

Here the patch is giving the wrong warning; it complains about applying 
the attribute to A<int>, but actually we should be warning about an 
attribute that would appertain to all the declarators in a declaration 
with no declarators for it to appertain to.

> +[[gnu::deprecated]] enum E { E0 };     // { dg-warning "attribute ignored in declaration of" }
> +// { dg-message "must follow the" "" { target *-*-* } 3 }

Same here.

> +         if (strcmp (attr_name, IDENTIFIER_POINTER (get_attribute_name (list))) == 0)
> +      gcc_checking_assert (TREE_CODE (get_attribute_name (list)) == IDENTIFIER_NODE);
> +             for (a = lookup_ident_attribute (get_attribute_name (a2), attributes);
> +                  a = lookup_ident_attribute (get_attribute_name (a2), TREE_CHAIN (a)))

Line too long.

> +  /* A given attribute has been parsed as a C++-11 generalized
> +     attribute.  */

Let's drop the word "generalized" throughout the patch.  I don't see how 
these attributes are any more generalized than GNU attributes; we should 
just describe them as C++11 attributes.

> +cxx_11_attribute_p (const_tree attr)

Let's change cxx_11 to cxx11.

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-07-26 15:20 Dodji Seketeli
  2012-07-26 16:32 ` Joseph S. Myers
  2012-07-26 21:02 ` Richard Henderson
@ 2012-07-27 16:09 ` Jason Merrill
  2012-07-27 23:22 ` Jason Merrill
  3 siblings, 0 replies; 22+ messages in thread
From: Jason Merrill @ 2012-07-27 16:09 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches

On 07/26/2012 11:19 AM, Dodji Seketeli wrote:
> +  struct scoped_attributes *ns = set_attributes_namespace (attrs,
> +                                                          attrs_len,
> +                                                          name_space);
> +  if (ns == NULL)
> +    return NULL;
> +
> +  for (i = 0; i < attrs_len; ++i)
> +    register_scoped_attribute (&attrs[i], ns);

This looks kind of funny; setting their namespace and then registering 
them sound like the same thing.  Let's rename set_attributes_namespace 
to register_scoped_attributes and call register_scoped_attribute from there.

> +      if (TREE_STATIC (node))
> +       {
> +         /* For file scope variables and static members, the target
> +            supports alignments that are at most
> +            MAX_OFILE_ALIGNMENT.  */

I think this should check TREE_STATIC || DECL_EXTERNAL.

More later.

Jason

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-07-26 15:20 Dodji Seketeli
  2012-07-26 16:32 ` Joseph S. Myers
@ 2012-07-26 21:02 ` Richard Henderson
  2012-07-27 16:09 ` Jason Merrill
  2012-07-27 23:22 ` Jason Merrill
  3 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2012-07-26 21:02 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches, Jason Merrill

On 07/26/2012 08:19 AM, Dodji Seketeli wrote:
> +      attributes_table->scoped = XRESIZEVEC (struct scoped_attributes,
> +					     attributes_table->scoped,
> +					     attributes_table->len + 1);

A good clue that you want VEC's instead, with VEC_safe_push.


r~

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
  2012-07-26 15:20 Dodji Seketeli
@ 2012-07-26 16:32 ` Joseph S. Myers
  2012-07-26 21:02 ` Richard Henderson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 22+ messages in thread
From: Joseph S. Myers @ 2012-07-26 16:32 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: GCC Patches, Jason Merrill

Do you handle how, in certain syntactic locations, a C++11 attribute binds 
differently to a GNU attribute?  (I haven't studied the patch, so feel 
free to point me to testcases it adds that verify such differences, if 
applicable.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH] PR 53528 c++/ C++11 Generalized Attribute support
@ 2012-07-26 15:20 Dodji Seketeli
  2012-07-26 16:32 ` Joseph S. Myers
                   ` (3 more replies)
  0 siblings, 4 replies; 22+ messages in thread
From: Dodji Seketeli @ 2012-07-26 15:20 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jason Merrill

Hello,

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

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

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

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

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

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

gcc/
	* plugin.h (register_scoped_attributes): Declare new function.
	* tree.h (enu attribute_flags::ATTR_FLAG_CXX_11): New flag.
	(lookup_scoped_attribute_spec, cxx_11_attribute_p)
	(get_attribute_name, get_attribute_namespace): Declare new functions.
	* 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 (attribute_hash): Remove global variable.
	(attributes_table): New global variable.
	(set_attributes_namespace, find_attribute_namespace)
	(register_scoped_attribute, attributes_array_length): New static
	functions.
	(register_scoped_attributes, lookup_scoped_attribute_spec)
	(cxx_11_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_CXX_11 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.

gcc/cp/

	* cp-tree.h (enum cpp0x_warn_str::CPP0X_GENERALIZED_ATTRIBUTES):
	New member.
	(cxx_alignas_expr): Declare new functions
	* 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, cp_parser_decl_specifier_seq): Use
	cp_nth_tokens_can_be_std_attribute_p here.
	(cp_parser_init_declarator):  Parsing attributes here is no more a
	GNU extension in c++-11.
	(cp_parser_direct_declarator, cp_parser_type_specifier_seq): Use
	cp_next_tokens_can_be_attribute_p.
	* semantics.c (potential_constant_expression_1): Likewise.
	* typeck.c (fundamental_alignment_p, cxx_alignas_expr): New public
	functions.

gcc/testsuite/

	* g++.dg/cpp0x/gen-attrs-1.C: New test.
	* g++.dg/cpp0x/gen-attrs-2.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-3.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-4.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-5.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-6.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-7.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-8.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-9.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-10.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-11.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-12.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-13.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-14.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-15.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-16.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-17.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-18.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-19.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-20.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-21.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-22.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-23.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-24.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-25.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-26.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-27.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-28.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-29.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-30.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-31.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-32.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-33.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-34.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-35.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-36.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-37.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-38.C: Likewise.
	* g++.dg/cpp0x/gen-attrs-39.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.
---
 gcc/attribs.c                               |  291 +++++++++++++++++--
 gcc/c-family/c-common.c                     |  108 +++++++-
 gcc/c-family/c-common.h                     |    1 +
 gcc/cp/cp-tree.h                            |    5 +-
 gcc/cp/decl2.c                              |    2 +-
 gcc/cp/error.c                              |    5 +
 gcc/cp/parser.c                             |  413 +++++++++++++++++++++++++--
 gcc/cp/typeck.c                             |   60 ++++
 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.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   |   18 ++
 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   |    8 +
 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.C   |   21 ++
 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.C   |   10 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C    |   32 ++
 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   |    4 +
 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-6.C    |   20 ++
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C    |    4 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C    |   11 +
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C    |   12 +
 gcc/tree.c                                  |   34 ++--
 gcc/tree.h                                  |   13 +-
 63 files changed, 1576 insertions(+), 64 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.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.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.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-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

diff --git a/gcc/attribs.c b/gcc/attribs.c
index d3af414..f75d4ee 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,30 @@ struct substring
   int length;
 };
 
+/* Scoped attribute name representation.  */
+
+struct scoped_attributes
+{
+  const char *ns;
+  unsigned len;
+  struct attribute_spec *attributes;
+  htab_t attribute_hash;
+};
+
+struct scoped_attributes_table
+{
+  unsigned len;
+  struct scoped_attributes *scoped;
+};
+
+/* The table of scope attributes.  */
+static struct scoped_attributes_table *attributes_table;
+
+static struct scoped_attributes* set_attributes_namespace (const struct attribute_spec *,
+							   unsigned, const char*);
+static struct scoped_attributes* find_attribute_namespace (const char*);
+static void register_scoped_attribute (const struct attribute_spec *,
+				       struct scoped_attributes *);
 static bool attributes_initialized = false;
 
 /* Default empty table of attributes.  */
@@ -102,6 +123,116 @@ eq_attr (const void *p, const void *q)
   return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]);
 }
 
+/* Set attributes ATTRIBUTES into the namespace NS.  */
+
+static struct scoped_attributes*
+set_attributes_namespace (const struct attribute_spec * attributes,
+			  unsigned attributes_length,
+			  const char* ns)
+{
+  unsigned i;
+  struct scoped_attributes *iter = NULL;
+  bool found_attrs = false;
+
+  /* See if we already have attributes in the namespace NS.  */
+  for (i = 0; attributes_table != NULL && i < attributes_table->len; ++i)
+    {
+      iter = &attributes_table->scoped[i];
+      if (strcmp (iter->ns, ns) == 0)
+	{
+	  found_attrs = true;
+	  break;
+	}
+    }
+
+  if (found_attrs)
+    {
+      /* We already have attributes in the namespace NS.  Add
+	 ATTRIBUTES to that namespace.  */
+
+      unsigned j;
+
+      gcc_assert (strcmp (iter->ns, ns) == 0);
+
+      iter->attributes = XRESIZEVEC (struct attribute_spec,
+				     iter->attributes,
+				     iter->len + attributes_length);
+
+      for (i = iter->len, j = 0;
+	   i < iter->len + attributes_length;
+	   ++i, ++j)
+	memcpy (&iter->attributes[i], &attributes[j],
+		sizeof (struct attribute_spec));
+      iter->len += attributes_length;
+    }
+  else
+    {
+      /* We don't have any namespace NS yet.  Create one and add
+	 ATTRIBUTES into it.  */
+
+      if (attributes_table == NULL)
+	attributes_table = XCNEW (struct scoped_attributes_table);
+
+      attributes_table->scoped = XRESIZEVEC (struct scoped_attributes,
+					     attributes_table->scoped,
+					     attributes_table->len + 1);
+      iter = &attributes_table->scoped[attributes_table->len];
+      memset (iter, 0, sizeof (struct scoped_attributes));
+      iter->ns = ns;
+      iter->len = attributes_length;
+      iter->attributes = XCNEWVEC (struct attribute_spec,
+					attributes_length);
+      memcpy (iter->attributes,
+	      attributes,
+	      attributes_length * sizeof (struct attribute_spec));
+      attributes_table->len++;
+    }
+
+  return iter;
+}
+
+/* Return the namespace which name is NS, NULL if none exist.  */
+
+static struct scoped_attributes*
+find_attribute_namespace (const char* ns)
+{
+  unsigned i;
+  struct scoped_attributes * attrs = NULL;
+
+  for (i = 0; i < attributes_table->len; ++i)
+    if (ns == attributes_table->scoped->ns
+	|| (attributes_table->scoped->ns != NULL
+	    && ns != NULL
+	    && !strcmp (attributes_table->scoped[i].ns, ns)))
+      {
+	attrs = &attributes_table->scoped[i];
+	break;
+      }
+
+  if (attrs != NULL && attrs->attribute_hash == 0)
+    attrs->attribute_hash =
+      htab_create (200, hash_attr, eq_attr, NULL);
+
+  return attrs;
+}
+
+/* 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 +240,6 @@ void
 init_attributes (void)
 {
   size_t i;
-  int k;
 
   if (attributes_initialized)
     return;
@@ -181,12 +311,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 +326,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,
+			   struct scoped_attributes *name_space)
+{
   struct substring str;
   void **slot;
 
+  gcc_assert (attr != NULL && name_space != NULL);
+
+  if (name_space->attribute_hash == NULL)
+   name_space->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL);
+
   str.str = attr->name;
   str.length = strlen (str.str);
 
@@ -206,27 +350,68 @@ 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.  */
+/* Insert an array of attributes ATTRS into a namespace.  ATTRS_LEN is
+   the length of the ATTRS array.  NAME_SPACE is the name of attribute
+   namespace.  The function returns the namespace into which the
+   attributes have been registered.  */
+
+struct scoped_attributes*
+register_scoped_attributes (const struct attribute_spec *attrs,
+			    unsigned attrs_len,
+			    const char *name_space)
+{
+  unsigned i;
+  struct scoped_attributes *ns = set_attributes_namespace (attrs,
+							   attrs_len,
+							   name_space);
+  if (ns == NULL)
+    return NULL;
+
+  for (i = 0; i < attrs_len; ++i)
+    register_scoped_attribute (&attrs[i], ns);
+
+  return ns;
+}
+
+/* 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;
+  struct scoped_attributes *attrs;
+
+  const char *ns_str = (ns != NULL_TREE) ? IDENTIFIER_POINTER (ns): NULL;
+
+  attrs = find_attribute_namespace (ns_str);
+
+  if (attrs == NULL)
+    return NULL;
 
   attr.str = IDENTIFIER_POINTER (name);
   attr.length = IDENTIFIER_LENGTH (name);
   extract_attribute_substring (&attr);
   return (const struct attribute_spec *)
-    htab_find_with_hash (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);
+}
+
 \f
 /* 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,
@@ -302,10 +487,11 @@ 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 +499,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 || !cxx_11_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 +599,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 cxx_11_flag =
+	    cxx_11_attribute_p (a) ? ATTR_FLAG_CXX_11 : 0;
+
+	  returned_attrs = chainon ((*spec->handler) (anode, name, args,
+						      flags|cxx_11_flag,
+						      &no_add_attrs),
+				    returned_attrs);
+	}
 
       /* Layout the decl in case anything changed.  */
       if (spec->type_required && DECL_P (*node)
@@ -488,6 +687,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
+   generalized attribute.
+
+   When G++ parses a C++11 generalized 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
+cxx_11_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 generalized (scoped) attributes.
+
+   Please read the comments of cxx_11_attribute_p to understand the
+   format of attributes.  */
+
+tree
+get_attribute_name (const_tree attr)
+{
+  if (cxx_11_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 generalized (scoped) attributes.  On GNU attributes,
+   it returns an identifier tree for the string "gnu".
+
+   Please read the comments of cxx_11_attribute_p to understand the
+   format of attributes.  */
+
+tree
+get_attribute_namespace (const_tree attr)
+{
+  if (cxx_11_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 b72506b..e7bbf95 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 },
@@ -6990,6 +6991,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_CXX_11)
+      || (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
+	      && (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.  */
@@ -7014,7 +7093,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)
     {
@@ -7044,6 +7124,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_CXX_11
+	   && 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)
     {
@@ -11008,4 +11095,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 3c1a7bf..7ac3844 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,
+  /* Generalized attributes */
+  CPP0X_GENERALIZED_ATTRIBUTES
 } cpp0x_warn_str;
   
 /* The various kinds of operation used by composite_pointer_type. */
@@ -5816,6 +5818,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/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..b6b1bc9 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_GENERALIZED_ATTRIBUTES:
+	pedwarn (input_location, 0,
+		 "generalized 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 70d6dac..51e3e2e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2103,9 +2103,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 +5629,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,
@@ -8859,7 +8886,7 @@ 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;
 
@@ -10299,8 +10326,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
@@ -10589,7 +10615,7 @@ 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
@@ -15498,7 +15524,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 +15590,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);
@@ -16179,7 +16203,8 @@ 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;
@@ -16921,7 +16946,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,
@@ -20104,6 +20129,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 +20212,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 +20241,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 +20262,7 @@ cp_parser_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
-/* Parse an attribute-list.
+/* Parse a GNU attribute-list.
 
    attribute-list:
      attribute
@@ -20180,7 +20280,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 +20359,275 @@ cp_parser_attribute_list (cp_parser* parser)
   return nreverse (attribute_list);
 }
 
+/*  Parse a standard C++11 generalized 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 generalized
+    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_GENERALIZED_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) == NULL
+	  || cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) == NULL)
+	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_GENERALIZED_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/typeck.c b/gcc/cp/typeck.c
index d7a719f..da5c76b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1701,6 +1701,66 @@ 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 : cxx_constant_value (e);
+      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;
+}
+
 \f
 /* 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..e43171d
--- /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 *, ...);
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..23a5b37
--- /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.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C
new file mode 100644
index 0000000..8d9027e
--- /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 (__const char *__s, int __c) throw () [[gnu::__pure__]];
+extern char *rindex (__const char *__s, int __c) throw () [[gnu::__pure__]];
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..387fcb6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C
@@ -0,0 +1,18 @@
+// 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;
+};
+
+int f[sizeof (struct S) != sizeof (struct T) ? -1 : 1];
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..079c667
--- /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-error "expected|invalid" }
+}
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..95d921b
--- /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 }
+// { dg-do run { target c++11 } }
+
+#define attrib [[gnu::mode (QI)]]
+
+attrib signed int a;		// attributes before type are broken
+static attrib unsigned int b;
+
+int foo(attrib int o)		// attribute arguments are broken
+{
+  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..169e94c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+// PR c++/35074
+template<typename T> struct A
+{
+  void foo() const;
+} [[gnu::aligned(4)]];
+
+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..5ca1c7c
--- /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]];
+
+static void foo(U) {}
+static void foo(int) {}
+
+void bar()
+{
+  foo(0);
+}
+
+typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" }
+
+static void foo2(U1) {}		// { dg-error "previously defined" }
+static void foo2(U2) {}		// { dg-error "redefinition" }
+
+void bar2(U1 u1, U2 u2)
+{
+  foo2(u1);
+  foo2(u2);
+}
+
+// PR c++/36410
+struct A
+{
+  typedef union
+  {
+    int i;
+  } B [[gnu::transparent_union]];
+};
+
+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..701cda7
--- /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 (char const * ...) [[gnu::format (printf,2,3)]];
+};
+
+template struct T<3>;
+
+template <typename T>
+struct U
+{
+  typedef T [[gnu::mode (SI)]] V;
+};
+
+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..86423ab
--- /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.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C
new file mode 100644
index 0000000..d1819bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C
@@ -0,0 +1,21 @@
+// 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 ([[gnu::__stdcall__]] T::*F) (L*);
+  void f(bool aAdd);
+};
+class T
+{
+public:
+    virtual void [[gnu::__stdcall__]] A(L *listener) = 0;
+    virtual void [[gnu::__stdcall__]] R(L *listener) = 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..3895c27
--- /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 [[gnu::__stdcall__]] getS();
+
+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..06cee02
--- /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)]];
+};
+
+int main ()
+{
+  A<4>::S s;
+}
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..451445e
--- /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 [[gnu::aligned (16)]] struct {
+    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..bbc98be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -0,0 +1,32 @@
+// { dg-do compile { target c++11 } }
+// Test for syntax support of various attribute permutations.
+
+int
+[[gnu::noreturn]]
+[[gnu::unused]]
+one(void); // OK 
+
+[[gnu::noreturn]]
+[[gnu::unused]]
+int
+two(void); // OK
+
+int
+[[gnu::unused]]
+three (void)
+[[gnu::noreturn]]; // OK
+
+[[gnu::unused]]
+int
+four (void)
+[[gnu::noreturn]]; // OK
+
+int
+five(void)
+[[gnu::noreturn]]
+[[gnu::unused]];  // OK
+
+[[gnu::noreturn]]
+int
+[[gnu::unused]] // parse error before '__attribute__' in C++
+six (void);              // OK in C
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..ceceefa
--- /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<<(int x) const [[gnu::always_inline]];
+};
+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..c05c241
--- /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]]
+struct A<int>;			// { dg-warning "attribute" }
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..699ad21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C
@@ -0,0 +1,4 @@
+// PR c++/52671
+// { dg-do compile { target c++11 } }
+[[gnu::deprecated]] enum E { E0 };	// { dg-warning "attribute ignored in declaration of" }
+// { dg-message "must follow the" "" { target *-*-* } 3 }
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..996c0b6
--- /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 '[[gnu::' should have introduced an attribute, ont a
+       lambda invocation an array subscripting expression.  */
+    int(p[[gnu::x] { return x; }()]); // { dg-error "expected|consecutive" }
+    /* Likewise, the '[[gnu::' is invalid here.  */
+    y[[gnu::] { 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..39a2263
--- /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 (sizeof (A) == sizeof (double),
+	       "size of struct A must be sizeof (double)");
+
+struct alignas (alignof (long double)) B {
+  layout_type member;
+};
+
+static_assert (sizeof (B) == sizeof (long double),
+	       "size of struct A must be sizeof (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..241a8e2
--- /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 (sizeof (A<int>) == sizeof (double),
+	       "size of struct A must be sizeof (double)");
+
+template<class> struct alignas (alignof (long double)) B {
+  layout_type member;
+};
+
+static_assert (sizeof (B<int>) == sizeof (long double),
+	       "size of struct A must be sizeof (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..91d36c2
--- /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 (sizeof (A<int>) == sizeof (double),
+	       "size of struct A must be sizeof (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 (sizeof (B<int>) == sizeof (long double),
+	       "size of struct A must be sizeof (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-6.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C
new file mode 100644
index 0000000..bb2f8f1
--- /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..3757c08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C
@@ -0,0 +1,11 @@
+// PR 8656
+// { dg-options "-std=c++11 -pedantic" }
+// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } }
+
+extern int * ([[gnu::stdcall]] *fooPtr)( void);
+int * [[gnu::stdcall]] myFn01( void) { return 0; }
+
+void snafu( void)
+{
+  fooPtr = myFn01;
+}
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..db841ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+
+class [[gnu::unused]] C;
+struct [[gnu::unused]] S;
+union [[gnu::unused]] 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 4fea005..28bf241 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4388,7 +4388,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;
 
@@ -4402,7 +4402,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;
 
@@ -5325,11 +5325,11 @@ 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))) == 0)
 	    break;
 	}
       /* TODO: If we made sure that attributes were stored in the
@@ -5337,7 +5337,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)
@@ -5367,10 +5367,10 @@ 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
@@ -5380,11 +5380,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] == '_'
@@ -5393,7 +5393,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] == '_'
@@ -5423,7 +5423,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);
@@ -5460,9 +5460,9 @@ 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)
 		{
@@ -6384,7 +6384,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;
 }
 
@@ -6421,7 +6421,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))
     ;
@@ -6436,9 +6436,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 62d6645..7625475 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4585,7 +4585,10 @@ 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 generalized
+     attribute.  */
+  ATTR_FLAG_CXX_11 = 32
 };
 
 /* Default versions of target-overridable functions.  */
@@ -5671,6 +5674,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);
 
@@ -5684,6 +5689,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 cxx_11_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 */
-- 
		Dodji

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2012-10-12 17:09 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-09 12:55 [PATCH] PR 53528 c++/ C++11 Generalized Attribute support Dominique Dhumieres
2012-10-09 13:48 ` Dodji Seketeli
2012-10-10 14:32 ` Dodji Seketeli
  -- strict thread matches above, loose matches on Subject: below --
2012-07-26 15:20 Dodji Seketeli
2012-07-26 16:32 ` Joseph S. Myers
2012-07-26 21:02 ` Richard Henderson
2012-07-27 16:09 ` Jason Merrill
2012-07-27 23:22 ` Jason Merrill
2012-08-10 20:05   ` Dodji Seketeli
2012-08-12  4:42     ` Jason Merrill
2012-08-15  7:43       ` Dodji Seketeli
2012-08-23  3:29         ` Jason Merrill
2012-09-17 15:36           ` Dodji Seketeli
2012-09-17 18:34             ` Jason Merrill
2012-09-18 13:52               ` Dodji Seketeli
2012-09-18 16:53                 ` Jason Merrill
2012-09-20  7:51                   ` Dodji Seketeli
2012-10-04 21:43                     ` Jason Merrill
2012-10-06  8:53                       ` Dodji Seketeli
2012-10-07 20:44                         ` Jason Merrill
2012-10-08 12:12                           ` Dodji Seketeli
2012-10-12 17:18                         ` Andreas Schwab

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).