diff --git a/src/parser/cxx/binder.cc b/src/parser/cxx/binder.cc index 67ccadc8..94e0a463 100644 --- a/src/parser/cxx/binder.cc +++ b/src/parser/cxx/binder.cc @@ -272,10 +272,11 @@ void Binder::bind(ClassSpecifierAST* ast, DeclSpecs& declSpecs) { unit_, primaryTemplateSymbol->templateDeclaration(), templateId->templateArgumentList); - specialization = - primaryTemplateSymbol - ? primaryTemplateSymbol->findSpecialization(templateArguments) - : nullptr; + specialization = primaryTemplateSymbol + ? symbol_cast( + primaryTemplateSymbol->findSpecialization( + templateArguments)) + : nullptr; if (specialization) { error(location, std::format("redefinition of specialization '{}'", @@ -518,6 +519,8 @@ void Binder::bind(UsingDeclaratorAST* ast, Symbol* target) { } void Binder::bind(BaseSpecifierAST* ast) { + const auto checkTemplates = unit_->config().checkTypes; + Symbol* symbol = nullptr; if (auto decltypeId = ast_cast(ast->unqualifiedId)) { @@ -525,12 +528,12 @@ void Binder::bind(BaseSpecifierAST* ast) { control()->remove_cv(decltypeId->decltypeSpecifier->type))) { symbol = classType->symbol(); } + } else { + symbol = + resolve(ast->nestedNameSpecifier, ast->unqualifiedId, checkTemplates); } - if (auto nameId = ast_cast(ast->unqualifiedId)) { - symbol = Lookup{scope_}(ast->nestedNameSpecifier, nameId->identifier); - } - + // dealias if (auto typeAlias = symbol_cast(symbol)) { if (auto classType = type_cast(control()->remove_cv(typeAlias->type()))) { @@ -538,32 +541,34 @@ void Binder::bind(BaseSpecifierAST* ast) { } } - if (symbol) { - auto location = ast->unqualifiedId->firstSourceLocation(); - auto baseClassSymbol = control()->newBaseClassSymbol(scope(), location); - ast->symbol = baseClassSymbol; + if (!symbol || !symbol->isClass()) { + error(ast->unqualifiedId->firstSourceLocation(), + "base class specifier must be a class"); + return; + } + + auto location = ast->unqualifiedId->firstSourceLocation(); + auto baseClassSymbol = control()->newBaseClassSymbol(scope(), location); + ast->symbol = baseClassSymbol; - baseClassSymbol->setVirtual(ast->isVirtual); - baseClassSymbol->setSymbol(symbol); + baseClassSymbol->setVirtual(ast->isVirtual); + baseClassSymbol->setSymbol(symbol); - if (symbol) { - baseClassSymbol->setName(symbol->name()); - } + 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 - } + 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) { diff --git a/src/parser/cxx/symbol_printer.cc b/src/parser/cxx/symbol_printer.cc index b9461d4c..17055289 100644 --- a/src/parser/cxx/symbol_printer.cc +++ b/src/parser/cxx/symbol_printer.cc @@ -63,9 +63,8 @@ struct DumpSymbols { --depth; } - template void dumpSpecializations( - std::span> specializations) { + std::span specializations) { if (specializations.empty()) return; ++depth; indent(); diff --git a/src/parser/cxx/symbols.cc b/src/parser/cxx/symbols.cc index 3fedef1c..bb49ef21 100644 --- a/src/parser/cxx/symbols.cc +++ b/src/parser/cxx/symbols.cc @@ -407,43 +407,6 @@ void ClassSymbol::addConversionFunction(FunctionSymbol* conversionFunction) { conversionFunctions_.push_back(conversionFunction); } -auto ClassSymbol::declaration() const -> SpecifierAST* { return specifier_; } - -void ClassSymbol::setDeclaration(SpecifierAST* specifier) { - specifier_ = specifier; -} - -auto ClassSymbol::templateDeclaration() const -> TemplateDeclarationAST* { - return templateDeclaration_; -} - -void ClassSymbol::setTemplateDeclaration( - TemplateDeclarationAST* templateDeclaration) { - templateDeclaration_ = templateDeclaration; -} - -auto ClassSymbol::specializations() const - -> std::span> { - if (!templateInfo_) return {}; - return templateInfo_->specializations(); -} - -auto ClassSymbol::findSpecialization( - const std::vector& arguments) const -> ClassSymbol* { - if (!templateInfo_) return {}; - return templateInfo_->findSpecialization(arguments); -} - -void ClassSymbol::addSpecialization(std::vector arguments, - ClassSymbol* specialization) { - if (!templateInfo_) { - templateInfo_ = std::make_unique>(this); - } - auto index = templateInfo_->specializations().size(); - specialization->setSpecializationInfo(this, index); - templateInfo_->addSpecialization(std::move(arguments), specialization); -} - auto ClassSymbol::buildClassLayout(Control* control) -> std::expected { int offset = 0; @@ -726,7 +689,7 @@ void TypeAliasSymbol::setTemplateDeclaration( } auto TypeAliasSymbol::specializations() const - -> std::span> { + -> std::span { if (!templateInfo_) return {}; return templateInfo_->specializations(); } @@ -734,13 +697,14 @@ auto TypeAliasSymbol::specializations() const auto TypeAliasSymbol::findSpecialization( const std::vector& arguments) const -> TypeAliasSymbol* { if (!templateInfo_) return {}; - return templateInfo_->findSpecialization(arguments); + return symbol_cast( + templateInfo_->findSpecialization(arguments)); } void TypeAliasSymbol::addSpecialization(std::vector arguments, TypeAliasSymbol* specialization) { if (!templateInfo_) { - templateInfo_ = std::make_unique>(this); + templateInfo_ = std::make_unique(this); } auto index = templateInfo_->specializations().size(); specialization->setSpecializationInfo(this, index); @@ -792,7 +756,7 @@ void VariableSymbol::setTemplateDeclaration( } auto VariableSymbol::specializations() const - -> std::span> { + -> std::span { if (!templateInfo_) return {}; return templateInfo_->specializations(); } @@ -800,13 +764,14 @@ auto VariableSymbol::specializations() const auto VariableSymbol::findSpecialization( const std::vector& arguments) const -> VariableSymbol* { if (!templateInfo_) return {}; - return templateInfo_->findSpecialization(arguments); + return symbol_cast( + templateInfo_->findSpecialization(arguments)); } void VariableSymbol::addSpecialization(std::vector arguments, VariableSymbol* specialization) { if (!templateInfo_) { - templateInfo_ = std::make_unique>(this); + templateInfo_ = std::make_unique(this); } auto index = templateInfo_->specializations().size(); specialization->setSpecializationInfo(this, index); diff --git a/src/parser/cxx/symbols.h b/src/parser/cxx/symbols.h index ec732b5b..bea935be 100644 --- a/src/parser/cxx/symbols.h +++ b/src/parser/cxx/symbols.h @@ -41,29 +41,29 @@ namespace cxx { class SymbolChainView; -template -struct TemplateSpecialization { - S* templateSymbol = nullptr; +class TemplateSpecialization { + public: + Symbol* templateSymbol = nullptr; std::vector arguments; - S* symbol = nullptr; + Symbol* symbol = nullptr; }; [[nodiscard]] auto compare_args(const std::vector& args1, const std::vector& args2) -> bool; -template class TemplateInfo { public: - explicit TemplateInfo(S* templateSymbol) : templateSymbol_(templateSymbol) {} + explicit TemplateInfo(Symbol* templateSymbol) + : templateSymbol_(templateSymbol) {} [[nodiscard]] auto specializations() const - -> std::span> { + -> std::span { return specializations_; } [[nodiscard]] auto findSpecialization( - const std::vector& arguments) const -> S* { + const std::vector& arguments) const -> Symbol* { for (const auto& specialization : specializations_) { const std::vector& args = specialization.arguments; if (args == arguments) return specialization.symbol; @@ -77,14 +77,14 @@ class TemplateInfo { } void addSpecialization(std::vector arguments, - S* specialization) { + Symbol* specialization) { specializations_.push_back( {templateSymbol_, std::move(arguments), specialization}); } private: - S* templateSymbol_ = nullptr; - std::vector> specializations_; + Symbol* templateSymbol_ = nullptr; + std::vector specializations_; }; class Symbol { @@ -263,6 +263,15 @@ class BaseClassSymbol final : public Symbol { bool isVirtual_ = false; }; +class Template { + public: + std::unique_ptr templateInfo_; + SpecifierAST* declaration_ = nullptr; + TemplateDeclarationAST* templateDeclaration_ = nullptr; + ClassSymbol* templateClass_ = nullptr; + int templateSepcializationIndex_ = 0; +}; + class ClassSymbol final : public ScopeSymbol { public: constexpr static auto Kind = SymbolKind::kClass; @@ -305,48 +314,95 @@ class ClassSymbol final : public ScopeSymbol { [[nodiscard]] auto flags() const -> std::uint32_t; void setFlags(std::uint32_t flags); - [[nodiscard]] auto declaration() const -> SpecifierAST*; - void setDeclaration(SpecifierAST* ast); + [[nodiscard]] auto declaration() const -> SpecifierAST* { + if (!template_) return nullptr; + return template_->declaration_; + } + + void setDeclaration(SpecifierAST* ast) { + ensure_template(); + template_->declaration_ = ast; + } - [[nodiscard]] auto templateDeclaration() const -> TemplateDeclarationAST*; - void setTemplateDeclaration(TemplateDeclarationAST* templateDeclaration); + [[nodiscard]] auto templateDeclaration() const -> TemplateDeclarationAST* { + if (!template_) return nullptr; + return template_->templateDeclaration_; + } + + void setTemplateDeclaration(TemplateDeclarationAST* templateDeclaration) { + ensure_template(); + template_->templateDeclaration_ = templateDeclaration; + } [[nodiscard]] auto specializations() const - -> std::span>; + -> std::span { + if (!template_) return {}; + if (!template_->templateInfo_) return {}; + return template_->templateInfo_->specializations(); + } [[nodiscard]] auto findSpecialization( - const std::vector& arguments) const -> ClassSymbol*; + const std::vector& arguments) const -> Symbol* { + if (!template_) return {}; + if (!template_->templateInfo_) return {}; + return template_->templateInfo_->findSpecialization(arguments); + } void addSpecialization(std::vector arguments, - ClassSymbol* specialization); + ClassSymbol* specialization) { + ensure_template(); + + if (!template_->templateInfo_) { + template_->templateInfo_ = std::make_unique(this); + } + + auto index = int(template_->templateInfo_->specializations().size()); + + specialization->setSpecializationInfo(this, index); + + template_->templateInfo_->addSpecialization(std::move(arguments), + specialization); + } [[nodiscard]] auto isSpecialization() const -> bool { - return templateClass_ != nullptr; + if (!template_) return false; + return template_->templateClass_ != nullptr; } [[nodiscard]] auto templateArguments() const -> std::span { - if (!templateClass_) return {}; - return templateClass_->specializations()[templateSepcializationIndex_] + if (!template_) return {}; + if (!template_->templateClass_) return {}; + + return template_->templateClass_ + ->specializations()[template_->templateSepcializationIndex_] .arguments; } void setSpecializationInfo(ClassSymbol* templateClass, std::size_t index) { - templateClass_ = templateClass; - templateSepcializationIndex_ = index; + ensure_template(); + template_->templateClass_ = templateClass; + template_->templateSepcializationIndex_ = index; } [[nodiscard]] auto templateClass() const -> ClassSymbol* { - return templateClass_; + if (!template_) return nullptr; + return template_->templateClass_; } [[nodiscard]] auto templateSepcializationIndex() const -> std::size_t { - return templateSepcializationIndex_; + if (!template_) return 0; + return template_->templateSepcializationIndex_; } [[nodiscard]] auto buildClassLayout(Control* control) -> std::expected; + void ensure_template() { + if (template_) return; + template_ = std::make_unique