Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 168292)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -1923,12 +1923,13 @@
             << TokenName << TagName;
       }
 
+      ParsedAttributesWithRange attrs(AttrFactory);
       // Parse this as a tag as if the missing tag were present.
       if (TagKind == tok::kw_enum)
         ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSC_normal);
       else
         ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,
-                            /*EnteringContext*/ false, DSC_normal);
+                            /*EnteringContext*/ false, DSC_normal, attrs);
       return true;
     }
   }
@@ -2749,8 +2750,20 @@
     case tok::kw_union: {
       tok::TokenKind Kind = Tok.getKind();
       ConsumeToken();
+
+      // These are attributes following class specifiers.
+      // To produce better diagnostic, we parse them when
+      // parsing class specifier.
+      ParsedAttributesWithRange attributes(AttrFactory);
       ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS,
-                          EnteringContext, DSContext);
+                          EnteringContext, DSContext, attributes);
+
+      // If there are attributes following class specifier,
+      // take them over and handle them here.
+      if (!attributes.empty()) {
+        AttrsLastTime = true;
+        attrs.takeAllFrom(attributes);
+      }
       continue;
     }
 
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp	(revision 168292)
+++ lib/Parse/ParseDeclCXX.cpp	(working copy)
@@ -1052,7 +1052,8 @@
                                  SourceLocation StartLoc, DeclSpec &DS,
                                  const ParsedTemplateInfo &TemplateInfo,
                                  AccessSpecifier AS, 
-                                 bool EnteringContext, DeclSpecContext DSC) {
+                                 bool EnteringContext, DeclSpecContext DSC, 
+                                 ParsedAttributesWithRange &attributes) {
   DeclSpec::TST TagType;
   if (TagTokKind == tok::kw_struct)
     TagType = DeclSpec::TST_struct;
@@ -1234,12 +1235,24 @@
   //  - If we have 'struct foo;', then this is either a forward declaration
   //    or a friend declaration, which have to be treated differently.
   //  - Otherwise we have something like 'struct foo xyz', a reference.
+  //  When start parsing from here, we also take misplaced C++11 attributes
+  //  specifiers into consideration by detecting the following cases:
+  //  - attributes follow class-name:
+  //    struct foo [[]] {};
+  //  - attributes appear before or after 'final':
+  //    struct foo [[]] final [[]] {};
+  //  This allow we produce better diagnostics.
+  //
   // However, in type-specifier-seq's, things look like declarations but are
   // just references, e.g.
   //   new struct s;
   // or
   //   &T::operator struct s;
   // For these, DSC is DSC_type_specifier.
+
+  // If there are attributes after class name, parse them.
+  MaybeParseCXX0XAttributes(attributes);
+
   Sema::TagUseKind TUK;
   if (DSC == DSC_trailing)
     TUK = Sema::TUK_Reference;
@@ -1261,6 +1274,30 @@
       // Okay, this is a class definition.
       TUK = Sema::TUK_Definition;
     }
+  } else if (isCXX0XFinalKeyword() && (NextToken().is(tok::l_square))) {
+    // We can't tell if this is a declaration or definition or reference
+    // until we skipped the 'final' and attributes sequences.
+    TentativeParsingAction PA(*this);
+
+    // Skip the 'final' keyword
+    ConsumeToken();
+    assert(Tok.is(tok::l_square) && "expected left square");
+    do {
+      // Skip the attributes without parsing them
+      if (NextToken().is(tok::l_square)) {
+        ConsumeBracket();
+        ConsumeBracket();
+        SkipUntil(tok::r_square, false);
+	SkipUntil(tok::r_square, false);
+      }
+    } while (Tok.is(tok::l_square));
+
+    if (Tok.is(tok::l_brace) || Tok.is(tok::colon))
+      TUK = Sema::TUK_Definition;
+    else
+      TUK = Sema::TUK_Reference;
+
+    PA.Revert();
   } else if (DSC != DSC_type_specifier &&
              (Tok.is(tok::semi) ||
               (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
@@ -1275,6 +1312,12 @@
   } else
     TUK = Sema::TUK_Reference;
 
+  // Forbid misplaced attributes. In cases of the reference, we pass attributes
+  // to caller to handle.
+  // FIXME: provide fix-it hints if we can.
+  if (TUK != Sema::TUK_Reference)
+    ProhibitAttributes(attributes);
+
   // If this is an elaborated type specifier, and we delayed
   // diagnostics before, just merge them into the current pool.
   if (shouldDelayDiagsInTag) {
@@ -2326,6 +2369,11 @@
            diag::warn_cxx98_compat_override_control_keyword :
            diag::ext_override_control_keyword) << "final";
     }
+
+    // Forbid C++11 attributes that appear here.
+    ParsedAttributesWithRange attrs(AttrFactory);
+    MaybeParseCXX0XAttributes(attrs);
+    ProhibitAttributes(attrs);
   }
 
   if (Tok.is(tok::colon)) {
Index: test/Parser/cxx0x-attributes.cpp
===================================================================
--- test/Parser/cxx0x-attributes.cpp	(revision 168292)
+++ test/Parser/cxx0x-attributes.cpp	(working copy)
@@ -62,6 +62,28 @@
 struct [[]] struct_attr;
 class [[]] class_attr {};
 union [[]] union_attr;
+
+// Checks attributes placed at wrong syntactic locations of class specifiers.
+// FIXME: provide fix-it hint.
+class [[]] [[]]
+  attr_after_class_name_decl [[]] [[]]; // expected-error {{an attribute list cannot appear here}}
+
+class [[]] [[]]
+ attr_after_class_name_definition [[]] [[]] [[]]{}; // expected-error {{an attribute list cannot appear here}}
+
+class [[]] c {};
+class c [[]] [[]] x;
+class c [[]] [[]] y [[]] [[]];
+
+class base {};
+class [[]] [[]] final_class 
+  [[]] [[]] final // expected-error {{an attribute list cannot appear here}}
+  [[]] [[]] [[]] : base{}; // expected-error {{an attribute list cannot appear here}}
+
+class [[]] [[]] final_class_another 
+  [[]] [[]] final // expected-error {{an attribute list cannot appear here}}
+  [[]] [[]] [[]] {}; // expected-error {{an attribute list cannot appear here}}
+
 [[]] struct with_init_declarators {} init_declarator;
 [[]] struct no_init_declarators; // expected-error {{an attribute list cannot appear here}}
 [[]];
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 168292)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -2098,7 +2098,8 @@
   void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
                            DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,
                            AccessSpecifier AS, bool EnteringContext,
-                           DeclSpecContext DSC);
+                           DeclSpecContext DSC, 
+                           ParsedAttributesWithRange &attributes);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
                                    Decl *TagDecl);
   ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction,
