From: Chris Lattner Date: Sun, 4 Jan 2009 21:25:24 +0000 (+0000) Subject: eliminate lookahead when parsing ::new / ::delete. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=59232d35f5820e334b6c8b007ae8006f4390055d;p=clang eliminate lookahead when parsing ::new / ::delete. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61638 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e23f72b5ca..cccd971073 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -643,10 +643,11 @@ private: //===--------------------------------------------------------------------===// // C++ 5.3.4 and 5.3.5: C++ new and delete - OwningExprResult ParseCXXNewExpression(); bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D); void ParseDirectNewDeclarator(Declarator &D); - OwningExprResult ParseCXXDeleteExpression(); + OwningExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start); + OwningExprResult ParseCXXDeleteExpression(bool UseGlobal, + SourceLocation Start); //===--------------------------------------------------------------------===// // C++ if/switch/while/for condition expression. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 0c25fab4f4..f719b8914f 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -626,19 +626,23 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression) { Res = ParseCXXIdExpression(); return ParsePostfixExpressionSuffix(move(Res)); - case tok::coloncolon: // [C++] new-expression or [C++] delete-expression - // If the next token is neither 'new' nor 'delete', the :: would have been - // parsed as a scope specifier already. - if (NextToken().is(tok::kw_new)) - return ParseCXXNewExpression(); - else - return ParseCXXDeleteExpression(); + case tok::coloncolon: { // [C++] new-expression or [C++] delete-expression + SourceLocation ScopeLoc = ConsumeToken(); + if (Tok.is(tok::kw_new)) + return ParseCXXNewExpression(true, ScopeLoc); + else { + // If the next token is neither 'new' nor 'delete', the :: would have been + // parsed as a scope specifier already. + assert(Tok.is(tok::kw_delete)); + return ParseCXXDeleteExpression(true, ScopeLoc); + } + } case tok::kw_new: // [C++] new-expression - return ParseCXXNewExpression(); + return ParseCXXNewExpression(false, Tok.getLocation()); case tok::kw_delete: // [C++] delete-expression - return ParseCXXDeleteExpression(); + return ParseCXXDeleteExpression(false, Tok.getLocation()); case tok::at: { SourceLocation AtLoc = ConsumeToken(); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index b0ce072a41..75e4e1fe7c 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -639,6 +639,10 @@ Parser::TypeTy *Parser::ParseConversionFunctionId() { /// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate /// memory in a typesafe manner and call constructors. +/// +/// This method is called to parse the new expression after the optional :: has +/// been already parsed. If the :: was present, "UseGlobal" is true and "Start" +/// is its location. Otherwise, "Start" is the location of the 'new' token. /// /// new-expression: /// '::'[opt] 'new' new-placement[opt] new-type-id @@ -660,21 +664,10 @@ Parser::TypeTy *Parser::ParseConversionFunctionId() { /// '(' expression-list[opt] ')' /// [C++0x] braced-init-list [TODO] /// -Parser::OwningExprResult Parser::ParseCXXNewExpression() -{ - assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_new)) && - "Expected :: or 'new' keyword"); - - SourceLocation Start = Tok.getLocation(); - bool UseGlobal = false; - if (Tok.is(tok::coloncolon)) { - UseGlobal = true; - ConsumeToken(); - } - - assert(Tok.is(tok::kw_new) && "Lookahead should have ensured 'new'"); - // Consume 'new' - ConsumeToken(); +Parser::OwningExprResult +Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { + assert(Tok.is(tok::kw_new) && "expected 'new' token"); + ConsumeToken(); // Consume 'new' // A '(' now can be a new-placement or the '(' wrapping the type-id in the // second form of new-expression. It can't be a new-type-id. @@ -768,8 +761,7 @@ Parser::OwningExprResult Parser::ParseCXXNewExpression() /// '[' expression ']' /// direct-new-declarator '[' constant-expression ']' /// -void Parser::ParseDirectNewDeclarator(Declarator &D) -{ +void Parser::ParseDirectNewDeclarator(Declarator &D) { // Parse the array dimensions. bool first = true; while (Tok.is(tok::l_square)) { @@ -802,8 +794,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) /// '(' expression-list ')' /// bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, - Declarator &D) -{ + Declarator &D) { // The '(' was already consumed. if (isTypeIdInParens()) { ParseSpecifierQualifierList(D.getMutableDeclSpec()); @@ -820,24 +811,18 @@ bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, /// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used /// to free memory allocated by new. /// +/// This method is called to parse the 'delete' expression after the optional +/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true +/// and "Start" is its location. Otherwise, "Start" is the location of the +/// 'delete' token. +/// /// delete-expression: /// '::'[opt] 'delete' cast-expression /// '::'[opt] 'delete' '[' ']' cast-expression -Parser::OwningExprResult Parser::ParseCXXDeleteExpression() -{ - assert((Tok.is(tok::coloncolon) || Tok.is(tok::kw_delete)) && - "Expected :: or 'delete' keyword"); - - SourceLocation Start = Tok.getLocation(); - bool UseGlobal = false; - if (Tok.is(tok::coloncolon)) { - UseGlobal = true; - ConsumeToken(); - } - - assert(Tok.is(tok::kw_delete) && "Lookahead should have ensured 'delete'"); - // Consume 'delete' - ConsumeToken(); +Parser::OwningExprResult +Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { + assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword"); + ConsumeToken(); // Consume 'delete' // Array delete? bool ArrayDelete = false;