From: Chris Lattner Date: Mon, 27 Aug 2007 01:01:57 +0000 (+0000) Subject: implement a fixme: __extension__ marker on decls in compound stmts. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45a566cfcbec0efd50bc737991bdfcc70e986811;p=clang 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 01cdbbcb46..cae056aa8e 100644 --- a/Parse/ParseStmt.cpp +++ b/Parse/ParseStmt.cpp @@ -354,7 +354,7 @@ Parser::StmtResult Parser::ParseDefaultStatement() { /// /// block-item: /// declaration -/// [GNU] '__extension__' declaration [TODO] +/// [GNU] '__extension__' declaration /// statement /// [OMP] openmp-directive [TODO] /// @@ -392,11 +392,47 @@ Parser::StmtResult Parser::ParseCompoundStatementBody() { 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 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); } diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp index da2d12bfaf..0bd05d86ae 100644 --- a/Sema/SemaStmt.cpp +++ b/Sema/SemaStmt.cpp @@ -48,6 +48,10 @@ Sema::StmtResult Sema::ParseDeclStmt(DeclTy *decl) { Action::StmtResult Sema::ParseCompoundStmt(SourceLocation L, SourceLocation R, StmtTy **Elts, unsigned NumElts) { + // FIXME: ISO C90 forbids mixed declarations and code + // Note that __extension__ can be around a decl. + + return new CompoundStmt((Stmt**)Elts, NumElts); } diff --git a/test/Parser/extension.c b/test/Parser/extension.c index 77a2f17583..9bd18de63f 100644 --- a/test/Parser/extension.c +++ b/test/Parser/extension.c @@ -7,3 +7,11 @@ __extension__ typedef struct long long int quot; long long int rem; }lldiv_t; + + +// Compound expr __extension__ marker. +void bar() { + __extension__ int i; + int j; +} +