Added rudimentary C++0x attribute support.
The following attributes are currently supported in C++0x attribute
lists (and in GNU ones as well):
 - align() - semantics believed to be conformant to n3000, except for
   redeclarations and what entities it may apply to
 - final - semantics believed to be conformant to CWG issue 817's proposed
   wording, except for redeclarations
 - noreturn - semantics believed to be conformant to n3000, except for
   redeclarations
 - carries_dependency - currently ignored (this is an optimization hint)

llvm-svn: 89543
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index ff08ebb..66e61dd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -78,6 +78,10 @@
   const char *SemiError = 0;
   OwningStmtResult Res(Actions);
 
+  CXX0XAttributeList Attr;
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+    Attr = ParseCXX0XAttributes();
+
   // Cases in this switch statement should fall through if the parser expects
   // the token to end in a semicolon (in which case SemiError should be set),
   // or they directly 'return;' if not.
@@ -98,14 +102,15 @@
   case tok::identifier:
     if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
       // identifier ':' statement
-      return ParseLabeledStatement();
+      return ParseLabeledStatement(Attr.AttrList);
     }
     // PASS THROUGH.
 
   default: {
     if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd);
+      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+                                             Attr);
       return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
     }
 
@@ -114,6 +119,7 @@
       return StmtError();
     }
 
+    // FIXME: Use the attributes
     // expression[opt] ';'
     OwningExprResult Expr(ParseExpression());
     if (Expr.isInvalid()) {
@@ -129,47 +135,50 @@
   }
 
   case tok::kw_case:                // C99 6.8.1: labeled-statement
-    return ParseCaseStatement();
+    return ParseCaseStatement(Attr.AttrList);
   case tok::kw_default:             // C99 6.8.1: labeled-statement
-    return ParseDefaultStatement();
+    return ParseDefaultStatement(Attr.AttrList);
 
   case tok::l_brace:                // C99 6.8.2: compound-statement
-    return ParseCompoundStatement();
+    return ParseCompoundStatement(Attr.AttrList);
   case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
     return Actions.ActOnNullStmt(ConsumeToken());
 
   case tok::kw_if:                  // C99 6.8.4.1: if-statement
-    return ParseIfStatement();
+    return ParseIfStatement(Attr.AttrList);
   case tok::kw_switch:              // C99 6.8.4.2: switch-statement
-    return ParseSwitchStatement();
+    return ParseSwitchStatement(Attr.AttrList);
 
   case tok::kw_while:               // C99 6.8.5.1: while-statement
-    return ParseWhileStatement();
+    return ParseWhileStatement(Attr.AttrList);
   case tok::kw_do:                  // C99 6.8.5.2: do-statement
-    Res = ParseDoStatement();
+    Res = ParseDoStatement(Attr.AttrList);
     SemiError = "do/while";
     break;
   case tok::kw_for:                 // C99 6.8.5.3: for-statement
-    return ParseForStatement();
+    return ParseForStatement(Attr.AttrList);
 
   case tok::kw_goto:                // C99 6.8.6.1: goto-statement
-    Res = ParseGotoStatement();
+    Res = ParseGotoStatement(Attr.AttrList);
     SemiError = "goto";
     break;
   case tok::kw_continue:            // C99 6.8.6.2: continue-statement
-    Res = ParseContinueStatement();
+    Res = ParseContinueStatement(Attr.AttrList);
     SemiError = "continue";
     break;
   case tok::kw_break:               // C99 6.8.6.3: break-statement
-    Res = ParseBreakStatement();
+    Res = ParseBreakStatement(Attr.AttrList);
     SemiError = "break";
     break;
   case tok::kw_return:              // C99 6.8.6.4: return-statement
-    Res = ParseReturnStatement();
+    Res = ParseReturnStatement(Attr.AttrList);
     SemiError = "return";
     break;
 
   case tok::kw_asm: {
+    if (Attr.HasAttr)
+      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+        << Attr.Range;
     bool msAsm = false;
     Res = ParseAsmStatement(msAsm);
     if (msAsm) return move(Res);
@@ -178,7 +187,7 @@
   }
 
   case tok::kw_try:                 // C++ 15: try-block
-    return ParseCXXTryBlock();
+    return ParseCXXTryBlock(Attr.AttrList);
   }
 
   // If we reached this code, the statement must end in a semicolon.
@@ -202,7 +211,7 @@
 ///         identifier ':' statement
 /// [GNU]   identifier ':' attributes[opt] statement
 ///
-Parser::OwningStmtResult Parser::ParseLabeledStatement() {
+Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
          "Not an identifier!");
 
@@ -215,10 +224,8 @@
   SourceLocation ColonLoc = ConsumeToken();
 
   // Read label attributes, if present.
-  Action::AttrTy *AttrList = 0;
   if (Tok.is(tok::kw___attribute))
-    // TODO: save these somewhere.
-    AttrList = ParseAttributes();
+    Attr = addAttributeLists(Attr, ParseGNUAttributes());
 
   OwningStmtResult SubStmt(ParseStatement());
 
@@ -236,8 +243,9 @@
 ///         'case' constant-expression ':' statement
 /// [GNU]   'case' constant-expression '...' constant-expression ':' statement
 ///
-Parser::OwningStmtResult Parser::ParseCaseStatement() {
+Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
   assert(Tok.is(tok::kw_case) && "Not a case stmt!");
+  // FIXME: Use attributes?
 
   // It is very very common for code to contain many case statements recursively
   // nested, as in (but usually without indentation):
@@ -354,7 +362,8 @@
 ///         'default' ':' statement
 /// Note that this does not parse the 'statement' at the end.
 ///
-Parser::OwningStmtResult Parser::ParseDefaultStatement() {
+Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
+  //FIXME: Use attributes?
   assert(Tok.is(tok::kw_default) && "Not a default stmt!");
   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
 
@@ -408,7 +417,9 @@
 /// [OMP]   barrier-directive
 /// [OMP]   flush-directive
 ///
-Parser::OwningStmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
+Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
+                                                        bool isStmtExpr) {
+  //FIXME: Use attributes?
   assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
 
   // Enter a scope to hold everything within the compound stmt.  Compound
@@ -449,6 +460,10 @@
       while (Tok.is(tok::kw___extension__))
         ConsumeToken();
 
+      CXX0XAttributeList Attr;
+      if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+        Attr = ParseCXX0XAttributes();
+
       // If this is the start of a declaration, parse it as such.
       if (isDeclarationStatement()) {
         // __extension__ silences extension warnings in the subdeclaration.
@@ -456,7 +471,8 @@
         ExtensionRAIIObject O(Diags);
 
         SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext,DeclEnd);
+        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+                                              Attr);
         R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
       } else {
         // Otherwise this was a unary __extension__ marker.
@@ -467,6 +483,7 @@
           continue;
         }
 
+        // FIXME: Use attributes?
         // Eat the semicolon at the end of stmt and convert the expr into a
         // statement.
         ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
@@ -537,7 +554,8 @@
 /// [C++]   'if' '(' condition ')' statement
 /// [C++]   'if' '(' condition ')' statement 'else' statement
 ///
-Parser::OwningStmtResult Parser::ParseIfStatement() {
+Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_if) && "Not an if stmt!");
   SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
 
@@ -659,7 +677,8 @@
 ///       switch-statement:
 ///         'switch' '(' expression ')' statement
 /// [C++]   'switch' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseSwitchStatement() {
+Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
   SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
 
@@ -734,7 +753,8 @@
 ///       while-statement: [C99 6.8.5.1]
 ///         'while' '(' expression ')' statement
 /// [C++]   'while' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseWhileStatement() {
+Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_while) && "Not a while stmt!");
   SourceLocation WhileLoc = Tok.getLocation();
   ConsumeToken();  // eat the 'while'.
@@ -805,7 +825,8 @@
 ///       do-statement: [C99 6.8.5.2]
 ///         'do' statement 'while' '(' expression ')' ';'
 /// Note: this lets the caller parse the end ';'.
-Parser::OwningStmtResult Parser::ParseDoStatement() {
+Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_do) && "Not a do stmt!");
   SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
 
@@ -880,7 +901,8 @@
 /// [C++]   expression-statement
 /// [C++]   simple-declaration
 ///
-Parser::OwningStmtResult Parser::ParseForStatement() {
+Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_for) && "Not a for stmt!");
   SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
 
@@ -937,8 +959,13 @@
     if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
 
+    AttributeList *AttrList = 0;
+    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
+      AttrList = ParseCXX0XAttributes().AttrList;
+
     SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd);
+    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
+                                               AttrList);
     FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
 
     if (Tok.is(tok::semi)) {  // for (int x = 4;
@@ -1036,7 +1063,8 @@
 ///
 /// Note: this lets the caller parse the end ';'.
 ///
-Parser::OwningStmtResult Parser::ParseGotoStatement() {
+Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
   SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
 
@@ -1069,7 +1097,8 @@
 ///
 /// Note: this lets the caller parse the end ';'.
 ///
-Parser::OwningStmtResult Parser::ParseContinueStatement() {
+Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
   return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
 }
@@ -1080,7 +1109,8 @@
 ///
 /// Note: this lets the caller parse the end ';'.
 ///
-Parser::OwningStmtResult Parser::ParseBreakStatement() {
+Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
   return Actions.ActOnBreakStmt(BreakLoc, CurScope);
 }
@@ -1088,7 +1118,8 @@
 /// ParseReturnStatement
 ///       jump-statement:
 ///         'return' expression[opt] ';'
-Parser::OwningStmtResult Parser::ParseReturnStatement() {
+Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
+  // FIXME: Use attributes?
   assert(Tok.is(tok::kw_return) && "Not a return stmt!");
   SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
 
@@ -1164,7 +1195,7 @@
   }
   DeclSpec DS;
   SourceLocation Loc = Tok.getLocation();
-  ParseTypeQualifierListOpt(DS);
+  ParseTypeQualifierListOpt(DS, true, false);
 
   // GNU asms accept, but warn, about type-qualifiers other than volatile.
   if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
@@ -1372,7 +1403,8 @@
 ///       try-block:
 ///         'try' compound-statement handler-seq
 ///
-Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
+Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
+  // FIXME: Add attributes?
   assert(Tok.is(tok::kw_try) && "Expected 'try'");
 
   SourceLocation TryLoc = ConsumeToken();
@@ -1394,11 +1426,17 @@
 Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
   if (Tok.isNot(tok::l_brace))
     return StmtError(Diag(Tok, diag::err_expected_lbrace));
-  OwningStmtResult TryBlock(ParseCompoundStatement());
+  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+  OwningStmtResult TryBlock(ParseCompoundStatement(0));
   if (TryBlock.isInvalid())
     return move(TryBlock);
 
   StmtVector Handlers(Actions);
+  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
+    CXX0XAttributeList Attr = ParseCXX0XAttributes();
+    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+      << Attr.Range;
+  }
   if (Tok.isNot(tok::kw_catch))
     return StmtError(Diag(Tok, diag::err_expected_catch));
   while (Tok.is(tok::kw_catch)) {
@@ -1458,7 +1496,8 @@
   if (Tok.isNot(tok::l_brace))
     return StmtError(Diag(Tok, diag::err_expected_lbrace));
 
-  OwningStmtResult Block(ParseCompoundStatement());
+  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
+  OwningStmtResult Block(ParseCompoundStatement(0));
   if (Block.isInvalid())
     return move(Block);