diff --git a/src/parser/cxx/ast.h b/src/parser/cxx/ast.h index b603e1f1..4f323749 100644 --- a/src/parser/cxx/ast.h +++ b/src/parser/cxx/ast.h @@ -1372,6 +1372,7 @@ class LambdaExpressionAST final : public ExpressionAST { RequiresClauseAST* requiresClause = nullptr; CompoundStatementAST* statement = nullptr; TokenKind captureDefault = TokenKind::T_EOF_SYMBOL; + LambdaSymbol* symbol = nullptr; void accept(ASTVisitor* visitor) override { visitor->visit(this); } diff --git a/src/parser/cxx/ast_rewriter.cc b/src/parser/cxx/ast_rewriter.cc index 428d06fe..858038b5 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -2413,6 +2413,7 @@ auto ASTRewriter::ExpressionVisitor::operator()(LambdaExpressionAST* ast) copy->requiresClause = rewrite(ast->requiresClause); copy->statement = ast_cast(rewrite(ast->statement)); copy->captureDefault = ast->captureDefault; + copy->symbol = ast->symbol; return copy; } diff --git a/src/parser/cxx/binder.cc b/src/parser/cxx/binder.cc index cd221324..01599df6 100644 --- a/src/parser/cxx/binder.cc +++ b/src/parser/cxx/binder.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -186,6 +187,153 @@ auto Binder::declareTypeAlias(SourceLocation identifierLoc, TypeIdAST* typeId) return symbol; } +void Binder::bind(UsingDeclaratorAST* ast, Symbol* target) { + if (auto u = symbol_cast(target)) { + target = u->target(); + } + + const auto name = get_name(control(), ast->unqualifiedId); + + auto symbol = control()->newUsingDeclarationSymbol( + scope(), ast->unqualifiedId->firstSourceLocation()); + + ast->symbol = symbol; + + symbol->setName(name); + symbol->setDeclarator(ast); + symbol->setTarget(target); + + scope()->addSymbol(symbol); +} + +void Binder::bind(BaseSpecifierAST* ast) { + Symbol* symbol = nullptr; + + if (auto decltypeId = ast_cast(ast->unqualifiedId)) { + if (auto classType = type_cast( + control()->remove_cv(decltypeId->decltypeSpecifier->type))) { + symbol = classType->symbol(); + } + } + + if (auto nameId = ast_cast(ast->unqualifiedId)) { + symbol = Lookup{scope_}(ast->nestedNameSpecifier, nameId->identifier); + } + + if (auto typeAlias = symbol_cast(symbol)) { + if (auto classType = + type_cast(control()->remove_cv(typeAlias->type()))) { + symbol = classType->symbol(); + } + } + + if (symbol) { + auto location = ast->unqualifiedId->firstSourceLocation(); + auto baseClassSymbol = control()->newBaseClassSymbol(scope(), location); + ast->symbol = baseClassSymbol; + + baseClassSymbol->setVirtual(ast->isVirtual); + baseClassSymbol->setSymbol(symbol); + + if (symbol) { + baseClassSymbol->setName(symbol->name()); + } + + switch (ast->accessSpecifier) { + case TokenKind::T_PRIVATE: + baseClassSymbol->setAccessSpecifier(AccessSpecifier::kPrivate); + break; + case TokenKind::T_PROTECTED: + baseClassSymbol->setAccessSpecifier(AccessSpecifier::kProtected); + break; + case TokenKind::T_PUBLIC: + baseClassSymbol->setAccessSpecifier(AccessSpecifier::kPublic); + break; + default: + break; + } // switch + } +} + +void Binder::bind(NonTypeTemplateParameterAST* ast, int index, int depth) { + auto symbol = control()->newNonTypeParameterSymbol( + scope(), ast->declaration->firstSourceLocation()); + ast->symbol = symbol; + + symbol->setIndex(index); + symbol->setDepth(depth); + symbol->setName(ast->declaration->identifier); + symbol->setParameterPack(ast->declaration->isPack); + symbol->setObjectType(ast->declaration->type); + scope()->addSymbol(symbol); +} + +void Binder::bind(TypenameTypeParameterAST* ast, int index, int depth) { + auto location = ast->identifier ? ast->identifierLoc : ast->classKeyLoc; + + auto symbol = control()->newTypeParameterSymbol(scope(), location); + ast->symbol = symbol; + + symbol->setIndex(index); + symbol->setDepth(depth); + symbol->setParameterPack(ast->isPack); + symbol->setName(ast->identifier); + scope()->addSymbol(symbol); +} + +void Binder::bind(ConstraintTypeParameterAST* ast, int index, int depth) { + auto symbol = + control()->newConstraintTypeParameterSymbol(scope(), ast->identifierLoc); + symbol->setIndex(index); + symbol->setDepth(depth); + symbol->setName(ast->identifier); + scope()->addSymbol(symbol); +} + +void Binder::bind(TemplateTypeParameterAST* ast, int index, int depth) { + auto symbol = + control()->newTemplateTypeParameterSymbol(scope(), ast->templateLoc); + + ast->symbol = symbol; + + symbol->setIndex(index); + symbol->setDepth(depth); + symbol->setName(ast->identifier); + symbol->setParameterPack(ast->isPack); + scope()->addSymbol(symbol); +} + +void Binder::bind(ConceptDefinitionAST* ast) { + auto templateParameters = currentTemplateParameters(); + + auto symbol = control()->newConceptSymbol(scope(), ast->identifierLoc); + symbol->setName(ast->identifier); + symbol->setTemplateParameters(templateParameters); + + declaringScope()->addSymbol(symbol); +} + +void Binder::bind(LambdaExpressionAST* ast) { + auto parentScope = declaringScope(); + auto symbol = control()->newLambdaSymbol(parentScope, ast->lbracketLoc); + ast->symbol = symbol; + + setScope(symbol); +} + +void Binder::complete(LambdaExpressionAST* ast) { + if (auto params = ast->parameterDeclarationClause) { + auto lambdaScope = ast->symbol->scope(); + lambdaScope->addSymbol(params->functionParametersSymbol); + setScope(params->functionParametersSymbol); + } else { + setScope(ast->symbol); + } + + auto parentScope = ast->symbol->enclosingScope(); + parentScope->addSymbol(ast->symbol); +} + auto Binder::declareTypedef(DeclaratorAST* declarator, const Decl& decl) -> TypeAliasSymbol* { auto name = decl.getName(); diff --git a/src/parser/cxx/binder.h b/src/parser/cxx/binder.h index 9a0bc2d2..bc86e0e8 100644 --- a/src/parser/cxx/binder.h +++ b/src/parser/cxx/binder.h @@ -93,6 +93,24 @@ class Binder { void bind(ParameterDeclarationAST* ast, const Decl& decl, bool inTemplateParameters); + void bind(UsingDeclaratorAST* ast, Symbol* target); + + void bind(BaseSpecifierAST* ast); + + void bind(NonTypeTemplateParameterAST* ast, int index, int depth); + + void bind(TypenameTypeParameterAST* ast, int index, int depth); + + void bind(ConstraintTypeParameterAST* ast, int index, int depth); + + void bind(TemplateTypeParameterAST* ast, int index, int depth); + + void bind(ConceptDefinitionAST* ast); + + void bind(LambdaExpressionAST* ast); + + void complete(LambdaExpressionAST* ast); + class ScopeGuard { public: Binder* p = nullptr; diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 278adb3f..b2becbf9 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -1131,11 +1131,6 @@ auto Parser::parse_lambda_expression(ExpressionAST*& yyast) -> bool { auto _ = Binder::ScopeGuard{&binder_}; - auto parentScope = binder_.declaringScope(); - auto symbol = control_->newLambdaSymbol(scope(), currentLocation()); - - setScope(symbol); - TemplateHeadContext templateHeadContext{this}; auto ast = make_node(pool_); @@ -1143,6 +1138,8 @@ auto Parser::parse_lambda_expression(ExpressionAST*& yyast) -> bool { expect(TokenKind::T_LBRACKET, ast->lbracketLoc); + binder_.bind(ast); + if (!match(TokenKind::T_RBRACKET, ast->rbracketLoc)) { if (!parse_lambda_capture(ast->captureDefaultLoc, ast->captureList)) { parse_error("expected a lambda capture"); @@ -1177,7 +1174,7 @@ auto Parser::parse_lambda_expression(ExpressionAST*& yyast) -> bool { parse_optional_attribute_specifier_seq(ast->gnuAtributeList, AllowedAttributes::kGnuAttribute); - (void)parse_lambda_specifier_seq(ast->lambdaSpecifierList, symbol); + (void)parse_lambda_specifier_seq(ast->lambdaSpecifierList, ast->symbol); (void)parse_noexcept_specifier(ast->exceptionSpecifier); @@ -1189,17 +1186,9 @@ auto Parser::parse_lambda_expression(ExpressionAST*& yyast) -> bool { (void)parse_requires_clause(ast->requiresClause); } - if (auto params = ast->parameterDeclarationClause) { - auto lambdaScope = symbol->scope(); - lambdaScope->addSymbol(params->functionParametersSymbol); - setScope(params->functionParametersSymbol); - } else { - setScope(symbol); - } - if (!lookat(TokenKind::T_LBRACE)) return false; - parentScope->addSymbol(symbol); + binder_.complete(ast); if (!parse_compound_statement(ast->statement)) { parse_error("expected a compound statement"); @@ -6928,6 +6917,7 @@ auto Parser::parse_using_declarator(UsingDeclaratorAST*& yyast) -> bool { return false; auto name = convertName(unqualifiedId); + auto target = Lookup{scope()}.lookup(nestedNameSpecifier, name); SourceLocation ellipsisLoc; auto isPack = match(TokenKind::T_DOT_DOT_DOT, ellipsisLoc); @@ -6939,22 +6929,7 @@ auto Parser::parse_using_declarator(UsingDeclaratorAST*& yyast) -> bool { yyast->ellipsisLoc = ellipsisLoc; yyast->isPack = isPack; - auto target = Lookup{scope()}.lookup(nestedNameSpecifier, name); - - if (auto u = symbol_cast(target)) { - target = u->target(); - } - - auto symbol = control_->newUsingDeclarationSymbol( - scope(), unqualifiedId->firstSourceLocation()); - - yyast->symbol = symbol; - - symbol->setName(name); - symbol->setDeclarator(yyast); - symbol->setTarget(target); - - scope()->addSymbol(symbol); + binder_.bind(yyast, target); return true; } @@ -7757,12 +7732,9 @@ auto Parser::parse_class_specifier( const Identifier* className = nullptr; ClassSymbol* symbol = nullptr; SourceLocation finalLoc; - SourceLocation colonLoc; - List* baseSpecifierList = nullptr; bool isUnion = false; bool isTemplateSpecialization = false; SourceLocation location = classLoc; - ClassSymbol* classSymbol = nullptr; auto lookat_class_head = [&] { LookaheadParser lookahead{this}; @@ -7807,6 +7779,21 @@ auto Parser::parse_class_specifier( if (!lookat_class_head()) return false; + auto ast = make_node(pool_); + yyast = ast; + + ast->classLoc = classLoc; + ast->attributeList = attributeList; + ast->nestedNameSpecifier = nestedNameSpecifier; + ast->unqualifiedId = unqualifiedId; + ast->finalLoc = finalLoc; + + ast->classKey = unit->tokenKind(ast->classLoc); + + if (finalLoc) { + ast->isFinal = true; + } + auto _ = Binder::ScopeGuard{&binder_}; if (scope()->isTemplateParametersScope()) { @@ -7839,6 +7826,8 @@ auto Parser::parse_class_specifier( } } + ClassSymbol* classSymbol = nullptr; + if (className) { for (auto candidate : binder_.declaringScope()->find(className) | views::classes) { @@ -7870,33 +7859,15 @@ auto Parser::parse_class_specifier( classSymbol->setFinal(true); } - setScope(classSymbol); - - (void)parse_base_clause(classSymbol, colonLoc, baseSpecifierList); - - SourceLocation lbraceLoc; - expect(TokenKind::T_LBRACE, lbraceLoc); - - ClassSpecifierContext classContext(this); + ast->symbol = classSymbol; - auto ast = make_node(pool_); - yyast = ast; + setScope(ast->symbol); - ast->symbol = classSymbol; - ast->classLoc = classLoc; - ast->attributeList = attributeList; - ast->nestedNameSpecifier = nestedNameSpecifier; - ast->unqualifiedId = unqualifiedId; - ast->finalLoc = finalLoc; - ast->colonLoc = colonLoc; - ast->baseSpecifierList = baseSpecifierList; - ast->lbraceLoc = lbraceLoc; + (void)parse_base_clause(ast); - ast->classKey = unit->tokenKind(ast->classLoc); + expect(TokenKind::T_LBRACE, ast->lbraceLoc); - if (finalLoc) { - ast->isFinal = true; - } + ClassSpecifierContext classContext(this); if (!match(TokenKind::T_RBRACE, ast->rbraceLoc)) { parse_class_body(ast->declarationList); @@ -8319,23 +8290,18 @@ auto Parser::parse_conversion_function_id(ConversionFunctionIdAST*& yyast) return true; } -auto Parser::parse_base_clause(ClassSymbol* classSymbol, - SourceLocation& colonLoc, - List*& baseSpecifierList) - -> bool { - if (!match(TokenKind::T_COLON, colonLoc)) return false; +auto Parser::parse_base_clause(ClassSpecifierAST* ast) -> bool { + if (!match(TokenKind::T_COLON, ast->colonLoc)) return false; - if (!parse_base_specifier_list(classSymbol, baseSpecifierList)) { + if (!parse_base_specifier_list(ast)) { parse_error("expected a base class specifier"); } return true; } -auto Parser::parse_base_specifier_list(ClassSymbol* classSymbol, - List*& yyast) - -> bool { - auto it = &yyast; +auto Parser::parse_base_specifier_list(ClassSpecifierAST* ast) -> bool { + auto it = &ast->baseSpecifierList; BaseSpecifierAST* baseSpecifier = nullptr; @@ -8346,7 +8312,7 @@ auto Parser::parse_base_specifier_list(ClassSymbol* classSymbol, match(TokenKind::T_DOT_DOT_DOT, ellipsisLoc); if (baseSpecifier && baseSpecifier->symbol) { - classSymbol->addBaseClass(baseSpecifier->symbol); + ast->symbol->addBaseClass(baseSpecifier->symbol); } *it = make_list_node(pool_, baseSpecifier); @@ -8364,7 +8330,7 @@ auto Parser::parse_base_specifier_list(ClassSymbol* classSymbol, match(TokenKind::T_DOT_DOT_DOT, ellipsisLoc); if (baseSpecifier && baseSpecifier->symbol) { - classSymbol->addBaseClass(baseSpecifier->symbol); + ast->symbol->addBaseClass(baseSpecifier->symbol); } *it = make_list_node(pool_, baseSpecifier); @@ -8397,58 +8363,14 @@ void Parser::parse_base_specifier(BaseSpecifierAST*& yyast) { if (!parse_class_or_decltype(ast->nestedNameSpecifier, ast->templateLoc, ast->unqualifiedId)) { parse_error("expected a class name"); - } else { - Symbol* symbol = nullptr; - - if (auto decltypeId = ast_cast(ast->unqualifiedId)) { - if (auto classType = type_cast( - control_->remove_cv(decltypeId->decltypeSpecifier->type))) { - symbol = classType->symbol(); - } - } - - if (auto nameId = ast_cast(ast->unqualifiedId)) { - symbol = Lookup{scope()}(ast->nestedNameSpecifier, nameId->identifier); - } - - if (auto typeAlias = symbol_cast(symbol)) { - if (auto classType = - type_cast(control_->remove_cv(typeAlias->type()))) { - symbol = classType->symbol(); - } - } - - if (symbol) { - auto location = ast->unqualifiedId->firstSourceLocation(); - auto baseClassSymbol = control_->newBaseClassSymbol(scope(), location); - ast->symbol = baseClassSymbol; - - baseClassSymbol->setVirtual(ast->isVirtual); - baseClassSymbol->setSymbol(symbol); - - if (symbol) { - baseClassSymbol->setName(symbol->name()); - } - - switch (ast->accessSpecifier) { - case TokenKind::T_PRIVATE: - baseClassSymbol->setAccessSpecifier(AccessSpecifier::kPrivate); - break; - case TokenKind::T_PROTECTED: - baseClassSymbol->setAccessSpecifier(AccessSpecifier::kProtected); - break; - case TokenKind::T_PUBLIC: - baseClassSymbol->setAccessSpecifier(AccessSpecifier::kPublic); - break; - default: - break; - } // switch - } + return; } if (ast->templateLoc) { ast->isTemplateIntroduced = true; } + + binder_.bind(ast); } auto Parser::parse_class_or_decltype( @@ -8949,22 +8871,14 @@ void Parser::parse_template_parameter(TemplateParameterAST*& yyast) { if (!parse_parameter_declaration(parameter, /*templParam*/ true)) return; - auto symbol = control_->newNonTypeParameterSymbol( - scope(), parameter->firstSourceLocation()); - symbol->setIndex(templateParameterCount_); - symbol->setDepth(templateParameterDepth_); - symbol->setName(parameter->identifier); - symbol->setParameterPack(parameter->isPack); - symbol->setObjectType(parameter->type); - scope()->addSymbol(symbol); + lookahead.commit(); auto ast = make_node(pool_); yyast = ast; ast->declaration = parameter; - ast->symbol = symbol; - lookahead.commit(); + binder_.bind(ast, templateParameterCount_, templateParameterDepth_); } auto Parser::parse_type_parameter(TemplateParameterAST*& yyast) -> bool { @@ -9002,26 +8916,17 @@ auto Parser::parse_typename_type_parameter(TemplateParameterAST*& yyast) const auto isPack = match(TokenKind::T_DOT_DOT_DOT, ast->ellipsisLoc); + ast->isPack = isPack; + match(TokenKind::T_IDENTIFIER, ast->identifierLoc); ast->identifier = unit->identifier(ast->identifierLoc); - auto location = ast->identifier ? ast->identifierLoc : classKeyLoc; - - auto symbol = control_->newTypeParameterSymbol(scope(), location); - symbol->setIndex(templateParameterCount_); - symbol->setDepth(templateParameterDepth_); - symbol->setParameterPack(isPack); - symbol->setName(ast->identifier); - scope()->addSymbol(symbol); - - ast->symbol = symbol; - - if (!match(TokenKind::T_EQUAL, ast->equalLoc)) return true; - - if (!parse_type_id(ast->typeId)) parse_error("expected a type id"); + binder_.bind(ast, templateParameterCount_, templateParameterDepth_); - ast->isPack = isPack; + if (match(TokenKind::T_EQUAL, ast->equalLoc)) { + if (!parse_type_id(ast->typeId)) parse_error("expected a type id"); + } return true; } @@ -9032,13 +8937,6 @@ void Parser::parse_template_type_parameter(TemplateParameterAST*& yyast) { auto ast = make_node(pool_); yyast = ast; - auto symbol = - control_->newTemplateTypeParameterSymbol(scope(), currentLocation()); - ast->symbol = symbol; - - symbol->setIndex(templateParameterCount_); - symbol->setDepth(templateParameterDepth_); - expect(TokenKind::T_TEMPLATE, ast->templateLoc); expect(TokenKind::T_LESS, ast->lessLoc); @@ -9065,16 +8963,13 @@ void Parser::parse_template_type_parameter(TemplateParameterAST*& yyast) { ast->isPack = match(TokenKind::T_DOT_DOT_DOT, ast->ellipsisLoc); - symbol->setParameterPack(ast->isPack); - if (match(TokenKind::T_IDENTIFIER, ast->identifierLoc)) { ast->identifier = unit->identifier(ast->identifierLoc); - symbol->setName(ast->identifier); mark_maybe_template_name(ast->identifier); } - scope()->addSymbol(symbol); + binder_.bind(ast, templateParameterCount_, templateParameterDepth_); if (match(TokenKind::T_EQUAL, ast->equalLoc)) { if (!parse_id_expression(ast->idExpression, @@ -9118,12 +9013,7 @@ auto Parser::parse_constraint_type_parameter(TemplateParameterAST*& yyast) ast->equalLoc = equalLoc; ast->typeId = typeId; - auto symbol = - control_->newConstraintTypeParameterSymbol(scope(), identifierLoc); - symbol->setIndex(templateParameterCount_); - symbol->setDepth(templateParameterDepth_); - symbol->setName(ast->identifier); - scope()->addSymbol(symbol); + binder_.bind(ast, templateParameterCount_, templateParameterDepth_); return true; } @@ -9504,13 +9394,7 @@ auto Parser::parse_concept_definition(DeclarationAST*& yyast) -> bool { expect(TokenKind::T_IDENTIFIER, ast->identifierLoc); ast->identifier = unit->identifier(ast->identifierLoc); - auto templateParameters = binder_.currentTemplateParameters(); - - auto symbol = control_->newConceptSymbol(scope(), ast->identifierLoc); - symbol->setName(ast->identifier); - symbol->setTemplateParameters(templateParameters); - - binder_.declaringScope()->addSymbol(symbol); + binder_.bind(ast); if (ast->identifierLoc) { concept_names_.insert(ast->identifier); diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index 8533f803..2dbecd9f 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -670,12 +670,8 @@ class Parser final { SourceLocation& zeroLoc) -> bool; [[nodiscard]] auto parse_conversion_function_id( ConversionFunctionIdAST*& yyast) -> bool; - [[nodiscard]] auto parse_base_clause( - ClassSymbol* classSymbol, SourceLocation& colonLoc, - List*& baseSpecifierList) -> bool; - [[nodiscard]] auto parse_base_specifier_list(ClassSymbol* classSymbol, - List*& yyast) - -> bool; + [[nodiscard]] auto parse_base_clause(ClassSpecifierAST* ast) -> bool; + [[nodiscard]] auto parse_base_specifier_list(ClassSpecifierAST* ast) -> bool; void parse_base_specifier(BaseSpecifierAST*& yyast); [[nodiscard]] auto parse_class_or_decltype( NestedNameSpecifierAST*& nestedNameSpecifier, SourceLocation& templateLoc,