From eb3a9b03ab3379185c8af2574272149a7f9a56c6 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. llvm-svn: 63100 --- clang/include/clang/Parse/Parser.h | 2 ++ clang/lib/Parse/ParseExpr.cpp | 19 +++++++++++++++++++ clang/lib/Parse/ParseStmt.cpp | 12 +++--------- clang/test/Parser/expressions.c | 4 ++++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index df8646df796e..cf479f000e4c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/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/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 38518557a3f8..1bec279890d4 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/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/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f7014991bf8c..5ff09052f58d 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/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/clang/test/Parser/expressions.c b/clang/test/Parser/expressions.c index 3b47260c32f2..29621f1975e6 100644 --- a/clang/test/Parser/expressions.c +++ b/clang/test/Parser/expressions.c @@ -36,4 +36,8 @@ void test_sizeof(){ sizeof(arr)[0]; } +// PR3418 +int test_leading_extension() { + __extension__ (*(char*)0) = 1; +}