From e0c896f67847275d36d707d441950bb3b332b57e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 15 Nov 2024 19:29:50 +0000 Subject: [PATCH 1/2] chore: Make the binding context available in parse_init_declarator --- src/parser/cxx/parser.cc | 25 +++++++++++++++---------- src/parser/cxx/parser.h | 9 ++++++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 31fa7ea9..8b30b84b 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -4567,7 +4567,8 @@ auto Parser::parse_template_class_declaration( } auto Parser::parse_empty_or_attribute_declaration( - DeclarationAST*& yyast, List* attributes) -> auto { + DeclarationAST*& yyast, List* attributes, + BindingContext ctx) -> auto { LookaheadParser lookahead{this}; SourceLocation semicolonLoc; @@ -4594,10 +4595,10 @@ auto Parser::parse_notypespec_function_definition( DeclarationAST*& yyast, List* atributes, const std::vector& templateDeclarations, BindingContext ctx) -> bool { - LookaheadParser lookahead{this}; - if (!context_allows_function_definition(ctx)) return false; + LookaheadParser lookahead{this}; + DeclSpecs specs{this}; List* declSpecifierList = nullptr; @@ -4625,6 +4626,8 @@ auto Parser::parse_type_or_forward_declaration( List* declSpecifierList, const DeclSpecs& specs, const std::vector& templateDeclarations, BindingContext ctx) -> bool { + if (ctx == BindingContext::kInitStatement) return false; + LookaheadParser lookahead{this}; List* trailingAttributes = nullptr; @@ -4738,7 +4741,7 @@ auto Parser::parse_simple_declaration( if (parse_template_class_declaration(yyast, attributes, templateDeclarations, ctx)) return true; - else if (parse_empty_or_attribute_declaration(yyast, attributes)) + else if (parse_empty_or_attribute_declaration(yyast, attributes, ctx)) return true; else if (parse_notypespec_function_definition(yyast, attributes, templateDeclarations, ctx)) @@ -4864,7 +4867,8 @@ auto Parser::parse_simple_declaration( auto declIt = &initDeclaratorList; InitDeclaratorAST* initDeclarator = nullptr; - if (!parse_init_declarator(initDeclarator, declarator, decl)) return false; + if (!parse_init_declarator(initDeclarator, declarator, decl, ctx)) + return false; if (ctx == BindingContext::kTemplate) { auto declarator = initDeclarator->declarator; @@ -4879,7 +4883,7 @@ auto Parser::parse_simple_declaration( while (match(TokenKind::T_COMMA, commaLoc)) { InitDeclaratorAST* initDeclarator = nullptr; - if (!parse_init_declarator(initDeclarator, specs)) return false; + if (!parse_init_declarator(initDeclarator, specs, ctx)) return false; *declIt = make_list_node(pool_, initDeclarator); declIt = &(*declIt)->next; @@ -6742,17 +6746,18 @@ auto Parser::parse_placeholder_type_specifier(SpecifierAST*& yyast, } auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, - const DeclSpecs& specs) -> bool { + const DeclSpecs& specs, BindingContext ctx) + -> bool { DeclaratorAST* declarator = nullptr; Decl decl{specs}; if (!parse_declarator(declarator, decl)) return false; - return parse_init_declarator(yyast, declarator, decl); + return parse_init_declarator(yyast, declarator, decl, ctx); } auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, - DeclaratorAST* declarator, Decl& decl) - -> bool { + DeclaratorAST* declarator, Decl& decl, + BindingContext ctx) -> bool { Symbol* declaredSynbol = nullptr; if (auto declId = decl.declaratorId; declId) { auto symbolType = GetDeclaratorType{this}(declarator, decl.specs.getType()); diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index b9b6559b..ed965bc2 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -383,7 +383,8 @@ class Parser final { const std::vector& templateDeclarations, BindingContext ctx) -> bool; [[nodiscard]] auto parse_empty_or_attribute_declaration( - DeclarationAST*& yyast, List* attributes) -> auto; + DeclarationAST*& yyast, List* attributes, + BindingContext ctx) -> auto; [[nodiscard]] auto parse_notypespec_function_definition( DeclarationAST*& yyast, List* atributes, @@ -472,10 +473,12 @@ class Parser final { [[nodiscard]] auto parse_placeholder_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) -> bool; [[nodiscard]] auto parse_init_declarator(InitDeclaratorAST*& yyast, - const DeclSpecs& specs) -> bool; + const DeclSpecs& specs, + BindingContext ctx) -> bool; [[nodiscard]] auto parse_init_declarator(InitDeclaratorAST*& yyast, DeclaratorAST* declarator, - Decl& decl) -> bool; + Decl& decl, BindingContext ctx) + -> bool; [[nodiscard]] auto parse_declarator_initializer( RequiresClauseAST*& requiresClause, ExpressionAST*& yyast) -> bool; void parse_optional_declarator_or_abstract_declarator(DeclaratorAST*& yyast, From 4abd26fad86796d7c9c31773e3f1fda8c26c450d Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 15 Nov 2024 19:56:14 +0000 Subject: [PATCH 2/2] fix: Improve parsing of init statements --- src/parser/cxx/parser.cc | 44 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 8b30b84b..51d19580 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -3734,8 +3734,18 @@ void Parser::parse_init_statement(StatementAST*& yyast) { DeclarationAST* declaration = nullptr; if (!parse_simple_declaration(declaration, BindingContext::kInitStatement)) return false; + lookahead.commit(); + if (auto simpleDeclaration = ast_cast(declaration)) { + // recover the declared symbols and add them to the scope + for (auto initDeclaraotr : + ListView(simpleDeclaration->initDeclaratorList)) { + auto symbol = initDeclaraotr->symbol; + std::invoke(DeclareSymbol{this, scope_}, symbol); + } + } + auto ast = make_node(pool_); yyast = ast; ast->declaration = declaration; @@ -3778,6 +3788,15 @@ void Parser::parse_condition(ExpressionAST*& yyast, const ExprContext& ctx) { Decl decl{specs}; if (!parse_declarator(declarator, decl)) return false; + auto symbolType = GetDeclaratorType{this}(declarator, decl.specs.getType()); + + auto symbol = control_->newVariableSymbol(scope_, decl.location()); + applySpecifiers(symbol, decl.specs); + symbol->setName(decl.getName()); + symbol->setType(symbolType); + + std::invoke(DeclareSymbol{this, scope_}, symbol); + ExpressionAST* initializer = nullptr; if (!parse_brace_or_equal_initializer(initializer)) return false; @@ -3978,6 +3997,10 @@ auto Parser::parse_if_statement(StatementAST*& yyast) -> bool { ScopeGuard scopeGuard{this}; + auto blockSymbol = control_->newBlockSymbol(scope_, ifLoc); + std::invoke(DeclareSymbol{this, scope_}, blockSymbol); + scope_ = blockSymbol->scope(); + if (LA().isOneOf(TokenKind::T_EXCLAIM, TokenKind::T_CONSTEVAL)) { auto ast = make_node(pool_); yyast = ast; @@ -4057,6 +4080,10 @@ auto Parser::parse_while_statement(StatementAST*& yyast) -> bool { ScopeGuard scopeGuard{this}; + auto blockSymbol = control_->newBlockSymbol(scope_, whileLoc); + std::invoke(DeclareSymbol{this, scope_}, blockSymbol); + scope_ = blockSymbol->scope(); + auto ast = make_node(pool_); yyast = ast; @@ -4106,6 +4133,11 @@ auto Parser::parse_for_range_statement(StatementAST*& yyast) -> bool { SourceLocation forLoc; if (!match(TokenKind::T_FOR, forLoc)) return false; + ScopeGuard scopeGuard{this}; + + auto blockSymbol = control_->newBlockSymbol(scope_, forLoc); + scope_ = blockSymbol->scope(); + SourceLocation lparenLoc; if (!match(TokenKind::T_LPAREN, lparenLoc)) return false; @@ -4120,6 +4152,8 @@ auto Parser::parse_for_range_statement(StatementAST*& yyast) -> bool { lookahead.commit(); + std::invoke(DeclareSymbol{this, scope_}, blockSymbol); + auto ast = make_node(pool_); yyast = ast; @@ -4145,6 +4179,12 @@ auto Parser::parse_for_statement(StatementAST*& yyast) -> bool { if (!match(TokenKind::T_FOR, forLoc)) return false; + ScopeGuard scopeGuard{this}; + + auto blockSymbol = control_->newBlockSymbol(scope_, forLoc); + std::invoke(DeclareSymbol{this, scope_}, blockSymbol); + scope_ = blockSymbol->scope(); + auto ast = make_node(pool_); yyast = ast; @@ -6782,7 +6822,9 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, applySpecifiers(symbol, decl.specs); symbol->setName(name); symbol->setType(symbolType); - std::invoke(DeclareSymbol{this, scope_}, symbol); + if (ctx != BindingContext::kInitStatement) { + std::invoke(DeclareSymbol{this, scope_}, symbol); + } declaredSynbol = symbol; } }