From adf077f46ba5cddcd801a647a5e9a3eb97060df4 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 27 Jan 2009 08:43:38 +0000 Subject: [PATCH] Fix for PR3418: make sure to handle the RHS of expressions starting with __extension__. This sort of construct shows up in the gcc source code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63100 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/Parser.h | 2 ++ lib/Parse/ParseExpr.cpp | 19 +++++++++++++++++++ lib/Parse/ParseStmt.cpp | 12 +++--------- test/Parser/expressions.c | 4 ++++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index df8646df79..cf479f000e 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -567,6 +567,8 @@ private: OwningExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); + OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); + OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec); OwningExprResult ParseCastExpression(bool isUnaryExpression); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 38518557a3..1bec279890 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -192,6 +192,25 @@ Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) { return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); } +/// This routine is called when a leading '__extension__' is seen and +/// consumed. This is necessary because the token gets consumed in the +/// process of disambiguating between an expression and a declaration. +Parser::OwningExprResult +Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { + // FIXME: The handling for throw is almost certainly wrong. + if (Tok.is(tok::kw_throw)) + return ParseThrowExpression(); + + OwningExprResult LHS(ParseCastExpression(false)); + if (LHS.isInvalid()) return move(LHS); + + LHS = Actions.ActOnUnaryOp(CurScope, ExtLoc, tok::kw___extension__, + move_arg(LHS)); + if (LHS.isInvalid()) return move(LHS); + + return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); +} + /// ParseAssignmentExpression - Parse an expr that doesn't include commas. /// Parser::OwningExprResult Parser::ParseAssignmentExpression() { diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index f7014991bf..5ff09052f5 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -366,6 +366,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // __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. + // FIXME: This loses extension expressions in the AST! SourceLocation ExtLoc = ConsumeToken(); while (Tok.is(tok::kw___extension__)) ConsumeToken(); @@ -381,21 +382,14 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // FIXME: Pass in the right location for the end of the declstmt. R = Actions.ActOnDeclStmt(Res, DeclStart, DeclStart); } else { - // Otherwise this was a unary __extension__ marker. Parse the - // subexpression and add the __extension__ unary op. - OwningExprResult Res(ParseCastExpression(false)); + // Otherwise this was a unary __extension__ marker. + OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc)); if (Res.isInvalid()) { SkipUntil(tok::semi); continue; } - // Add the __extension__ node to the AST. - Res = Actions.ActOnUnaryOp(CurScope, ExtLoc, tok::kw___extension__, - move_arg(Res)); - if (Res.isInvalid()) - continue; - // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr); diff --git a/test/Parser/expressions.c b/test/Parser/expressions.c index 3b47260c32..29621f1975 100644 --- a/test/Parser/expressions.c +++ b/test/Parser/expressions.c @@ -36,4 +36,8 @@ void test_sizeof(){ sizeof(arr)[0]; } +// PR3418 +int test_leading_extension() { + __extension__ (*(char*)0) = 1; +} -- 2.50.1