implement a fixme: __extension__ marker on decls in compound stmts.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41473 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp
index 01cdbbc..cae056a 100644
--- a/Parse/ParseStmt.cpp
+++ b/Parse/ParseStmt.cpp
@@ -354,7 +354,7 @@
 ///
 ///       block-item:
 ///         declaration
-/// [GNU]   '__extension__' declaration [TODO]
+/// [GNU]   '__extension__' declaration
 ///         statement
 /// [OMP]   openmp-directive            [TODO]
 ///
@@ -392,11 +392,47 @@
   SourceLocation LBraceLoc = ConsumeBrace();  // eat the '{'.
 
   // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
-  // only allowed at the start of a compound stmt.
+  // only allowed at the start of a compound stmt regardless of the language.
   
   llvm::SmallVector<StmtTy*, 32> Stmts;
   while (Tok.getKind() != tok::r_brace && Tok.getKind() != tok::eof) {
-    StmtResult R = ParseStatementOrDeclaration(false);
+    StmtResult R;
+    if (Tok.getKind() != tok::kw___extension__) {
+      R = ParseStatementOrDeclaration(false);
+    } else {
+      // __extension__ can start declarations and it can also be a unary
+      // operator for expressions.  Consume multiple __extension__ markers here
+      // until we can determine which is which.
+      SourceLocation ExtLoc = ConsumeToken();
+      while (Tok.getKind() == tok::kw___extension__)
+        ConsumeToken();
+      
+      // If this is the start of a declaration, parse it as such.
+      if (isDeclarationSpecifier()) {
+        // FIXME: Save the __extension__ on the decl as a node somehow.
+        // FIXME: disable extwarns.
+        R = Actions.ParseDeclStmt(ParseDeclaration(Declarator::BlockContext));
+      } else {
+        // Otherwise this was a unary __extension__ marker.  Parse the
+        // subexpression and add the __extension__ unary op. 
+        // FIXME: disable extwarns.
+        ExprResult Res = ParseCastExpression(false);
+        if (Res.isInvalid) {
+          SkipUntil(tok::semi);
+          continue;
+        }
+        
+        // Add the __extension__ node to the AST.
+        Res = Actions.ParseUnaryOp(ExtLoc, tok::kw___extension__, Res.Val);
+        if (Res.isInvalid)
+          continue;
+        
+        // Eat the semicolon at the end of stmt and convert the expr into a stmt.
+        ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
+        R = Actions.ParseExprStmt(Res.Val);
+      }
+    }
+    
     if (!R.isInvalid && R.Val)
       Stmts.push_back(R.Val);
   }