This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PR 53528 c++/ C++11 Generalized Attribute support


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]