diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt index 07850704..14e79484 100644 --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -33,6 +33,7 @@ add_library(cxx-parser cxx/control.cc cxx/cxx.cc cxx/decl_specs.cc + cxx/decl.cc cxx/diagnostic.cc cxx/diagnostics_client.cc cxx/external_name_encoder.cc diff --git a/src/parser/cxx/const_expression_evaluator.cc b/src/parser/cxx/const_expression_evaluator.cc index 7233bc88..a7f29cf2 100644 --- a/src/parser/cxx/const_expression_evaluator.cc +++ b/src/parser/cxx/const_expression_evaluator.cc @@ -35,16 +35,19 @@ namespace cxx { +ConstExpressionEvaluator::ConstExpressionEvaluator(TranslationUnit* unit) + : unit_(unit) {} + +auto ConstExpressionEvaluator::control() const -> Control* { + return unit_->control(); +} + auto ConstExpressionEvaluator::evaluate(ExpressionAST* ast) -> std::optional { if (!ast) return std::nullopt; return visit(*this, ast); } -auto ConstExpressionEvaluator::control() const -> Control* { - return parser.control(); -} - auto ConstExpressionEvaluator::operator()(GeneratedLiteralExpressionAST* ast) -> std::optional { return ast->value; @@ -522,8 +525,7 @@ auto ConstExpressionEvaluator::operator()(BinaryExpressionAST* ast) return right; default: - parser.translationUnit()->warning(ast->opLoc, - "invalid binary expression"); + unit_->warning(ast->opLoc, "invalid binary expression"); break; } // switch diff --git a/src/parser/cxx/const_expression_evaluator.h b/src/parser/cxx/const_expression_evaluator.h index 777bb511..0c6be8b6 100644 --- a/src/parser/cxx/const_expression_evaluator.h +++ b/src/parser/cxx/const_expression_evaluator.h @@ -27,14 +27,12 @@ namespace cxx { -class Parser; class Control; +class TranslationUnit; class ConstExpressionEvaluator { - Parser& parser; - public: - explicit ConstExpressionEvaluator(Parser& parser) : parser(parser) {} + explicit ConstExpressionEvaluator(TranslationUnit* unit); auto evaluate(ExpressionAST* ast) -> std::optional; @@ -108,6 +106,9 @@ class ConstExpressionEvaluator { auto operator()(EqualInitializerAST* ast) -> std::optional; auto operator()(BracedInitListAST* ast) -> std::optional; auto operator()(ParenInitializerAST* ast) -> std::optional; + + private: + TranslationUnit* unit_; }; } // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/decl.cc b/src/parser/cxx/decl.cc new file mode 100644 index 00000000..ace4134f --- /dev/null +++ b/src/parser/cxx/decl.cc @@ -0,0 +1,378 @@ +// Copyright (c) 2025 Roberto Raggi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include + +// cxx +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cxx { + +namespace { + +class GetFunctionPrototype { + enum class Kind { Direct, Ptr, Function, Array }; + + FunctionDeclaratorChunkAST* prototype_ = nullptr; + Kind kind_ = Kind::Direct; + + public: + GetFunctionPrototype() = default; + + FunctionDeclaratorChunkAST* operator()(DeclaratorAST* declarator) { + makeDirect(); + process(declarator); + return prototype_; + } + + private: + void makeDirect() { + prototype_ = nullptr; + kind_ = Kind::Direct; + } + + void makePtr() { + prototype_ = nullptr; + kind_ = Kind::Ptr; + } + + void makeArray() { + prototype_ = nullptr; + kind_ = Kind::Array; + } + + void makeFunction(FunctionDeclaratorChunkAST* prototype) { + prototype_ = prototype; + kind_ = Kind::Function; + } + + void process(DeclaratorAST* declarator) { + if (!declarator) return; + if (declarator->ptrOpList) makePtr(); + if (declarator->declaratorChunkList) { + auto prototype = ast_cast( + declarator->declaratorChunkList->value); + if (prototype) makeFunction(prototype); + } + auto nested = ast_cast(declarator->coreDeclarator); + if (nested) process(nested->declarator); + } +}; + +struct GetDeclaratorType { + TranslationUnit* unit = nullptr; + const Type* type_ = nullptr; + + struct { + auto operator()(float value) const -> std::optional { + return std::nullopt; + } + + auto operator()(double value) const -> std::optional { + return std::nullopt; + } + + auto operator()(const StringLiteral* value) const + -> std::optional { + return std::nullopt; + } + + template + auto operator()(T value) const -> std::optional { + return static_cast(value); + } + } get_size_value; + + explicit GetDeclaratorType(TranslationUnit* unit) : unit(unit) {} + + auto control() const -> Control* { return unit->control(); } + + auto operator()(DeclaratorAST* ast, const Type* type) -> const Type* { + if (!ast) return type; + + std::swap(type_, type); + + std::invoke(*this, ast); + + std::swap(type_, type); + + return type; + } + + void operator()(DeclaratorAST* ast) { + for (auto it = ast->ptrOpList; it; it = it->next) visit(*this, it->value); + + auto nestedNameSpecifier = getNestedNameSpecifier(ast->coreDeclarator); + + std::invoke(*this, ast->declaratorChunkList); + + if (ast->coreDeclarator) visit(*this, ast->coreDeclarator); + } + + auto getNestedNameSpecifier(CoreDeclaratorAST* ast) const + -> NestedNameSpecifierAST* { + struct { + auto operator()(DeclaratorAST* ast) const -> NestedNameSpecifierAST* { + if (ast->coreDeclarator) return visit(*this, ast->coreDeclarator); + return nullptr; + } + + auto operator()(BitfieldDeclaratorAST* ast) const + -> NestedNameSpecifierAST* { + return nullptr; + } + + auto operator()(ParameterPackAST* ast) const -> NestedNameSpecifierAST* { + return nullptr; + } + + auto operator()(IdDeclaratorAST* ast) const -> NestedNameSpecifierAST* { + return ast->nestedNameSpecifier; + } + + auto operator()(NestedDeclaratorAST* ast) const + -> NestedNameSpecifierAST* { + if (!ast->declarator) return nullptr; + return std::invoke(*this, ast->declarator); + } + } v; + + if (!ast) return nullptr; + return visit(v, ast); + } + + void operator()(List* chunks) { + if (!chunks) return; + std::invoke(*this, chunks->next); + visit(*this, chunks->value); + } + + void operator()(PointerOperatorAST* ast) { + type_ = control()->getPointerType(type_); + + for (auto it = ast->cvQualifierList; it; it = it->next) { + if (ast_cast(it->value)) { + type_ = control()->add_const(type_); + } else if (ast_cast(it->value)) { + type_ = control()->add_volatile(type_); + } + } + } + + void operator()(ReferenceOperatorAST* ast) { + if (ast->refOp == TokenKind::T_AMP_AMP) { + type_ = control()->add_rvalue_reference(type_); + } else { + type_ = control()->add_lvalue_reference(type_); + } + } + + void operator()(PtrToMemberOperatorAST* ast) { + if (!type_) return; + + auto symbol = ast->nestedNameSpecifier->symbol; + if (!symbol) return; + + auto classType = type_cast(symbol->type()); + if (!classType) return; + + if (auto functionType = type_cast(type_)) { + type_ = control()->getMemberFunctionPointerType(classType, functionType); + } else { + type_ = control()->getMemberObjectPointerType(classType, type_); + } + + for (auto it = ast->cvQualifierList; it; it = it->next) { + if (ast_cast(it->value)) { + type_ = control()->add_const(type_); + } else if (ast_cast(it->value)) { + type_ = control()->add_volatile(type_); + } + } + } + + void operator()(BitfieldDeclaratorAST* ast) {} + + void operator()(ParameterPackAST* ast) { + if (ast->coreDeclarator) visit(*this, ast->coreDeclarator); + } + + void operator()(IdDeclaratorAST* ast) {} + + void operator()(NestedDeclaratorAST* ast) { + std::invoke(*this, ast->declarator); + } + + void operator()(FunctionDeclaratorChunkAST* ast) { + auto returnType = type_; + std::vector parameterTypes; + bool isVariadic = false; + + if (auto params = ast->parameterDeclarationClause) { + for (auto it = params->parameterDeclarationList; it; it = it->next) { + auto paramType = it->value->type; + parameterTypes.push_back(paramType); + } + + isVariadic = params->isVariadic; + } + + CvQualifiers cvQualifiers = CvQualifiers::kNone; + for (auto it = ast->cvQualifierList; it; it = it->next) { + if (ast_cast(it->value)) { + if (cvQualifiers == CvQualifiers::kVolatile) + cvQualifiers = CvQualifiers::kConstVolatile; + else + cvQualifiers = CvQualifiers::kConst; + } else if (ast_cast(it->value)) { + if (cvQualifiers == CvQualifiers::kConst) + cvQualifiers = CvQualifiers::kConstVolatile; + else + cvQualifiers = CvQualifiers::kVolatile; + } + } + + RefQualifier refQualifier = RefQualifier::kNone; + + if (ast->refLoc) { + if (unit->tokenKind(ast->refLoc) == TokenKind::T_AMP_AMP) { + refQualifier = RefQualifier::kRvalue; + } else { + refQualifier = RefQualifier::kLvalue; + } + } + + bool isNoexcept = false; + + if (ast->exceptionSpecifier) + isNoexcept = visit(*this, ast->exceptionSpecifier); + + if (ast->trailingReturnType) { +#if false + if (!type_cast(returnType)) { + p->parse_warn(ast->trailingReturnType->firstSourceLocation(), + std::format("function with trailing return type must " + "be declared with 'auto', not '{}'", + to_string(returnType))); + } +#endif + + if (ast->trailingReturnType->typeId) { + returnType = ast->trailingReturnType->typeId->type; + } + } + + type_ = control()->getFunctionType(returnType, std::move(parameterTypes), + isVariadic, cvQualifiers, refQualifier, + isNoexcept); + } + + void operator()(ArrayDeclaratorChunkAST* ast) { + if (!ast->expression) { + type_ = control()->getUnboundedArrayType(type_); + return; + } + + ConstExpressionEvaluator sem{unit}; + auto constValue = sem.evaluate(ast->expression); + + if (constValue) { + if (auto size = std::visit(get_size_value, *constValue)) { + type_ = control()->getBoundedArrayType(type_, *size); + return; + } + } + + type_ = + control()->getUnresolvedBoundedArrayType(unit, type_, ast->expression); + } + + auto operator()(ThrowExceptionSpecifierAST* ast) -> bool { return false; } + + auto operator()(NoexceptSpecifierAST* ast) -> bool { + if (!ast->expression) return true; + return false; + } +}; + +} // namespace + +[[nodiscard]] auto getFunctionPrototype(DeclaratorAST* declarator) + -> FunctionDeclaratorChunkAST* { + GetFunctionPrototype prototype; + return prototype(declarator); +} + +[[nodiscard]] auto getDeclaratorType(TranslationUnit* unit, + DeclaratorAST* declarator, + const Type* type) -> const Type* { + GetDeclaratorType getDeclaratorType{unit}; + return getDeclaratorType(declarator, type); +} + +Decl::Decl(const DeclSpecs& specs) : specs{specs} {} + +auto Decl::location() const -> SourceLocation { + if (declaratorId) return declaratorId->firstSourceLocation(); + return {}; +} + +auto Decl::getName() const -> const Name* { + auto control = specs.control(); + if (!declaratorId) return nullptr; + if (!declaratorId->unqualifiedId) return nullptr; + return get_name(control, declaratorId->unqualifiedId); +} + +auto Decl::getNestedNameSpecifier() const -> NestedNameSpecifierAST* { + if (!declaratorId) return nullptr; + return declaratorId->nestedNameSpecifier; +} + +auto Decl::getScope() const -> Scope* { + auto nestedNameSpecifier = getNestedNameSpecifier(); + if (!nestedNameSpecifier) return nullptr; + + auto symbol = nestedNameSpecifier->symbol; + if (!symbol) return nullptr; + + if (auto alias = symbol_cast(symbol)) { + if (auto classType = type_cast(alias->type())) { + symbol = classType->symbol(); + } + } + + if (auto classSymbol = symbol_cast(symbol)) + return classSymbol->scope(); + + if (auto namespaceSymbol = symbol_cast(symbol)) + return namespaceSymbol->scope(); + + return nullptr; +} + +} // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/decl.h b/src/parser/cxx/decl.h new file mode 100644 index 00000000..b87e0713 --- /dev/null +++ b/src/parser/cxx/decl.h @@ -0,0 +1,51 @@ +// Copyright (c) 2025 Roberto Raggi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include +#include +#include +#include + +namespace cxx { + +class Decl { + public: + DeclSpecs specs; + IdDeclaratorAST* declaratorId = nullptr; + bool isPack = false; + + explicit Decl(const DeclSpecs& specs); + + [[nodiscard]] auto location() const -> SourceLocation; + [[nodiscard]] auto getName() const -> const Name*; + [[nodiscard]] auto getNestedNameSpecifier() const -> NestedNameSpecifierAST*; + [[nodiscard]] auto getScope() const -> Scope*; +}; + +[[nodiscard]] auto getFunctionPrototype(DeclaratorAST* declarator) + -> FunctionDeclaratorChunkAST*; + +[[nodiscard]] auto getDeclaratorType(TranslationUnit* unit, + DeclaratorAST* declarator, + const Type* type) -> const Type*; + +} // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/decl_specs.h b/src/parser/cxx/decl_specs.h index 3cc856cd..6b311f1d 100644 --- a/src/parser/cxx/decl_specs.h +++ b/src/parser/cxx/decl_specs.h @@ -18,6 +18,8 @@ // FRnewOM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +#pragma once + #include #include diff --git a/src/parser/cxx/names.cc b/src/parser/cxx/names.cc index 8a9f30bc..ccc0a38e 100644 --- a/src/parser/cxx/names.cc +++ b/src/parser/cxx/names.cc @@ -20,10 +20,77 @@ #include +// cxx +#include +#include +#include + #include namespace cxx { +namespace { + +struct ConvertToName { + Control* control_; + + explicit ConvertToName(Control* control) : control_(control) {} + + auto operator()(NameIdAST* ast) const -> const Name* { + return ast->identifier; + } + + auto operator()(DestructorIdAST* ast) const -> const Name* { + return control_->getDestructorId(visit(*this, ast->id)); + } + + auto operator()(DecltypeIdAST* ast) const -> const Name* { + cxx_runtime_error("DecltypeIdAST not implemented"); + return {}; + } + + auto operator()(OperatorFunctionIdAST* ast) const -> const Name* { + return control_->getOperatorId(ast->op); + } + + auto operator()(LiteralOperatorIdAST* ast) const -> const Name* { + if (ast->identifier) + return control_->getLiteralOperatorId(ast->identifier->name()); + + auto value = ast->literal->value(); + auto suffix = value.substr(value.find_last_of('"') + 1); + return control_->getLiteralOperatorId(suffix); + } + + auto operator()(ConversionFunctionIdAST* ast) const -> const Name* { + return control_->getConversionFunctionId(ast->typeId->type); + } + + auto operator()(SimpleTemplateIdAST* ast) const -> const Name* { + std::vector arguments; + return control_->getTemplateId(ast->identifier, std::move(arguments)); + } + + auto operator()(LiteralOperatorTemplateIdAST* ast) const -> const Name* { + std::vector arguments; + return control_->getTemplateId(operator()(ast->literalOperatorId), + std::move(arguments)); + } + + auto operator()(OperatorFunctionTemplateIdAST* ast) const -> const Name* { + std::vector arguments; + return control_->getTemplateId(operator()(ast->operatorFunctionId), + std::move(arguments)); + } +}; + +} // namespace + +[[nodiscard]] auto get_name(Control* control, UnqualifiedIdAST* id) + -> const Name* { + return visit(ConvertToName{control}, id); +} + Name::~Name() = default; auto Identifier::isBuiltinTypeTrait() const -> bool { diff --git a/src/parser/cxx/names.h b/src/parser/cxx/names.h index 95a1f142..3a719185 100644 --- a/src/parser/cxx/names.h +++ b/src/parser/cxx/names.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include @@ -176,4 +177,7 @@ auto name_cast(const Name* name) -> const T* { : nullptr; } +[[nodiscard]] auto get_name(Control* control, UnqualifiedIdAST* id) + -> const Name*; + } // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index b968e99d..a1908e32 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -53,59 +54,6 @@ inline constexpr struct { auto operator()(auto value) const -> bool { return !!value; } } to_bool; -struct ConvertToName { - Control* control_; - - explicit ConvertToName(Control* control) : control_(control) {} - - auto operator()(NameIdAST* ast) const -> const Name* { - return ast->identifier; - } - - auto operator()(DestructorIdAST* ast) const -> const Name* { - return control_->getDestructorId(visit(*this, ast->id)); - } - - auto operator()(DecltypeIdAST* ast) const -> const Name* { - cxx_runtime_error("DecltypeIdAST not implemented"); - return {}; - } - - auto operator()(OperatorFunctionIdAST* ast) const -> const Name* { - return control_->getOperatorId(ast->op); - } - - auto operator()(LiteralOperatorIdAST* ast) const -> const Name* { - if (ast->identifier) - return control_->getLiteralOperatorId(ast->identifier->name()); - - auto value = ast->literal->value(); - auto suffix = value.substr(value.find_last_of('"') + 1); - return control_->getLiteralOperatorId(suffix); - } - - auto operator()(ConversionFunctionIdAST* ast) const -> const Name* { - return control_->getConversionFunctionId(ast->typeId->type); - } - - auto operator()(SimpleTemplateIdAST* ast) const -> const Name* { - std::vector arguments; - return control_->getTemplateId(ast->identifier, std::move(arguments)); - } - - auto operator()(LiteralOperatorTemplateIdAST* ast) const -> const Name* { - std::vector arguments; - return control_->getTemplateId(operator()(ast->literalOperatorId), - std::move(arguments)); - } - - auto operator()(OperatorFunctionTemplateIdAST* ast) const -> const Name* { - std::vector arguments; - return control_->getTemplateId(operator()(ast->operatorFunctionId), - std::move(arguments)); - } -}; - class RecordingDiagnosticsClient : public DiagnosticsClient { public: void reset() { messages_.clear(); } @@ -126,298 +74,8 @@ class RecordingDiagnosticsClient : public DiagnosticsClient { std::vector messages_; }; -class FunctionPrototype { - enum class Kind { Direct, Ptr, Function, Array }; - - FunctionDeclaratorChunkAST* prototype_ = nullptr; - Kind kind_ = Kind::Direct; - - public: - FunctionPrototype() = default; - - FunctionDeclaratorChunkAST* operator()(DeclaratorAST* declarator) { - makeDirect(); - process(declarator); - return prototype_; - } - - private: - void makeDirect() { - prototype_ = nullptr; - kind_ = Kind::Direct; - } - - void makePtr() { - prototype_ = nullptr; - kind_ = Kind::Ptr; - } - - void makeArray() { - prototype_ = nullptr; - kind_ = Kind::Array; - } - - void makeFunction(FunctionDeclaratorChunkAST* prototype) { - prototype_ = prototype; - kind_ = Kind::Function; - } - - void process(DeclaratorAST* declarator) { - if (!declarator) return; - if (declarator->ptrOpList) makePtr(); - if (declarator->declaratorChunkList) { - auto prototype = ast_cast( - declarator->declaratorChunkList->value); - if (prototype) makeFunction(prototype); - } - auto nested = ast_cast(declarator->coreDeclarator); - if (nested) process(nested->declarator); - } -}; - -auto getFunctionPrototype(DeclaratorAST* declarator) - -> FunctionDeclaratorChunkAST* { - FunctionPrototype prototype; - return prototype(declarator); -} - } // namespace -struct Parser::GetDeclaratorType { - Parser* p; - const Type* type_ = nullptr; - - struct { - auto operator()(float value) const -> std::optional { - return std::nullopt; - } - - auto operator()(double value) const -> std::optional { - return std::nullopt; - } - - auto operator()(const StringLiteral* value) const - -> std::optional { - return std::nullopt; - } - - template - auto operator()(T value) const -> std::optional { - return static_cast(value); - } - } get_size_value; - - explicit GetDeclaratorType(Parser* p) : p(p) {} - - auto control() const -> Control* { return p->unit->control(); } - - auto operator()(DeclaratorAST* ast, const Type* type) -> const Type* { - if (!ast) return type; - - std::swap(type_, type); - - std::invoke(*this, ast); - - std::swap(type_, type); - - return type; - } - - void operator()(DeclaratorAST* ast) { - for (auto it = ast->ptrOpList; it; it = it->next) visit(*this, it->value); - - auto nestedNameSpecifier = getNestedNameSpecifier(ast->coreDeclarator); - - std::invoke(*this, ast->declaratorChunkList); - - if (ast->coreDeclarator) visit(*this, ast->coreDeclarator); - } - - auto getNestedNameSpecifier(CoreDeclaratorAST* ast) const - -> NestedNameSpecifierAST* { - struct { - auto operator()(DeclaratorAST* ast) const -> NestedNameSpecifierAST* { - if (ast->coreDeclarator) return visit(*this, ast->coreDeclarator); - return nullptr; - } - - auto operator()(BitfieldDeclaratorAST* ast) const - -> NestedNameSpecifierAST* { - return nullptr; - } - - auto operator()(ParameterPackAST* ast) const -> NestedNameSpecifierAST* { - return nullptr; - } - - auto operator()(IdDeclaratorAST* ast) const -> NestedNameSpecifierAST* { - return ast->nestedNameSpecifier; - } - - auto operator()(NestedDeclaratorAST* ast) const - -> NestedNameSpecifierAST* { - if (!ast->declarator) return nullptr; - return std::invoke(*this, ast->declarator); - } - } v; - - if (!ast) return nullptr; - return visit(v, ast); - } - - void operator()(List* chunks) { - if (!chunks) return; - std::invoke(*this, chunks->next); - visit(*this, chunks->value); - } - - void operator()(PointerOperatorAST* ast) { - type_ = control()->getPointerType(type_); - - for (auto it = ast->cvQualifierList; it; it = it->next) { - if (ast_cast(it->value)) { - type_ = control()->add_const(type_); - } else if (ast_cast(it->value)) { - type_ = control()->add_volatile(type_); - } - } - } - - void operator()(ReferenceOperatorAST* ast) { - if (ast->refOp == TokenKind::T_AMP_AMP) { - type_ = control()->add_rvalue_reference(type_); - } else { - type_ = control()->add_lvalue_reference(type_); - } - } - - void operator()(PtrToMemberOperatorAST* ast) { - if (!type_) return; - - auto symbol = ast->nestedNameSpecifier->symbol; - if (!symbol) return; - - auto classType = type_cast(symbol->type()); - if (!classType) return; - - if (auto functionType = type_cast(type_)) { - type_ = control()->getMemberFunctionPointerType(classType, functionType); - } else { - type_ = control()->getMemberObjectPointerType(classType, type_); - } - - for (auto it = ast->cvQualifierList; it; it = it->next) { - if (ast_cast(it->value)) { - type_ = control()->add_const(type_); - } else if (ast_cast(it->value)) { - type_ = control()->add_volatile(type_); - } - } - } - - void operator()(BitfieldDeclaratorAST* ast) {} - - void operator()(ParameterPackAST* ast) { - if (ast->coreDeclarator) visit(*this, ast->coreDeclarator); - } - - void operator()(IdDeclaratorAST* ast) {} - - void operator()(NestedDeclaratorAST* ast) { - std::invoke(*this, ast->declarator); - } - - void operator()(FunctionDeclaratorChunkAST* ast) { - auto returnType = type_; - std::vector parameterTypes; - bool isVariadic = false; - - if (auto params = ast->parameterDeclarationClause) { - for (auto it = params->parameterDeclarationList; it; it = it->next) { - auto paramType = it->value->type; - parameterTypes.push_back(paramType); - } - - isVariadic = params->isVariadic; - } - - CvQualifiers cvQualifiers = CvQualifiers::kNone; - for (auto it = ast->cvQualifierList; it; it = it->next) { - if (ast_cast(it->value)) { - if (cvQualifiers == CvQualifiers::kVolatile) - cvQualifiers = CvQualifiers::kConstVolatile; - else - cvQualifiers = CvQualifiers::kConst; - } else if (ast_cast(it->value)) { - if (cvQualifiers == CvQualifiers::kConst) - cvQualifiers = CvQualifiers::kConstVolatile; - else - cvQualifiers = CvQualifiers::kVolatile; - } - } - - RefQualifier refQualifier = RefQualifier::kNone; - - if (ast->refLoc) { - if (p->unit->tokenKind(ast->refLoc) == TokenKind::T_AMP_AMP) { - refQualifier = RefQualifier::kRvalue; - } else { - refQualifier = RefQualifier::kLvalue; - } - } - - bool isNoexcept = false; - - if (ast->exceptionSpecifier) - isNoexcept = visit(*this, ast->exceptionSpecifier); - - if (ast->trailingReturnType) { -#if false - if (!type_cast(returnType)) { - p->parse_warn(ast->trailingReturnType->firstSourceLocation(), - std::format("function with trailing return type must " - "be declared with 'auto', not '{}'", - to_string(returnType))); - } -#endif - - if (ast->trailingReturnType->typeId) { - returnType = ast->trailingReturnType->typeId->type; - } - } - - type_ = control()->getFunctionType(returnType, std::move(parameterTypes), - isVariadic, cvQualifiers, refQualifier, - isNoexcept); - } - - void operator()(ArrayDeclaratorChunkAST* ast) { - if (!ast->expression) { - type_ = control()->getUnboundedArrayType(type_); - return; - } - - auto constValue = p->evaluate_constant_expression(ast->expression); - - if (constValue) { - if (auto size = std::visit(get_size_value, *constValue)) { - type_ = control()->getBoundedArrayType(type_, *size); - return; - } - } - - type_ = control()->getUnresolvedBoundedArrayType(p->unit, type_, - ast->expression); - } - - auto operator()(ThrowExceptionSpecifierAST* ast) -> bool { return false; } - - auto operator()(NoexceptSpecifierAST* ast) -> bool { - if (!ast->expression) return true; - return false; - } -}; - struct Parser::LookaheadParser { Parser* p; SourceLocation loc; @@ -474,53 +132,6 @@ struct Parser::LoopParser { } }; -struct Parser::Decl { - DeclSpecs specs; - IdDeclaratorAST* declaratorId = nullptr; - bool isPack = false; - - explicit Decl(const DeclSpecs& specs) : specs{specs} {} - - [[nodiscard]] auto location() const -> SourceLocation { - if (declaratorId) return declaratorId->firstSourceLocation(); - return {}; - } - - [[nodiscard]] auto getName() const -> const Name* { - auto control = specs.control(); - if (!declaratorId) return nullptr; - if (!declaratorId->unqualifiedId) return nullptr; - return visit(ConvertToName{control}, declaratorId->unqualifiedId); - } - - [[nodiscard]] auto getNestedNameSpecifier() const -> NestedNameSpecifierAST* { - if (!declaratorId) return nullptr; - return declaratorId->nestedNameSpecifier; - } - - [[nodiscard]] auto getScope() const -> Scope* { - auto nestedNameSpecifier = getNestedNameSpecifier(); - if (!nestedNameSpecifier) return nullptr; - - auto symbol = nestedNameSpecifier->symbol; - if (!symbol) return nullptr; - - if (auto alias = symbol_cast(symbol)) { - if (auto classType = type_cast(alias->type())) { - symbol = classType->symbol(); - } - } - - if (auto classSymbol = symbol_cast(symbol)) - return classSymbol->scope(); - - if (auto namespaceSymbol = symbol_cast(symbol)) - return namespaceSymbol->scope(); - - return nullptr; - } -}; - struct Parser::ScopeGuard { Parser* p = nullptr; Scope* savedScope = nullptr; @@ -4669,7 +4280,7 @@ auto Parser::parse_simple_declaration( auto _ = ScopeGuard{this}; auto functionType = - GetDeclaratorType{this}(declarator, decl.specs.getType()); + getDeclaratorType(unit, declarator, decl.specs.getType()); auto q = decl.getNestedNameSpecifier(); @@ -4810,7 +4421,7 @@ auto Parser::parse_notypespec_function_definition( parse_optional_attribute_specifier_seq(functionDeclarator->attributeList); - auto functionType = GetDeclaratorType{this}(declarator, decl.specs.getType()); + auto functionType = getDeclaratorType(unit, declarator, decl.specs.getType()); SourceLocation equalLoc; SourceLocation zeroLoc; @@ -5766,7 +5377,7 @@ auto Parser::is_constructor(Symbol* symbol) const -> bool { auto Parser::evaluate_constant_expression(ExpressionAST* expr) -> std::optional { - ConstExpressionEvaluator sem{*this}; + ConstExpressionEvaluator sem{unit}; return sem.evaluate(expr); } @@ -6424,7 +6035,7 @@ auto Parser::parse_type_id(TypeIdAST*& yyast) -> bool { parse_optional_abstract_declarator(yyast->declarator, decl); yyast->type = - GetDeclaratorType{this}(yyast->declarator, decl.specs.getType()); + getDeclaratorType(unit, yyast->declarator, decl.specs.getType()); return true; } @@ -6451,7 +6062,7 @@ auto Parser::parse_defining_type_id( ast->typeSpecifierList = typeSpecifierList; ast->declarator = declarator; - ast->type = GetDeclaratorType{this}(ast->declarator, decl.specs.getType()); + ast->type = getDeclaratorType(unit, ast->declarator, decl.specs.getType()); return true; } @@ -6586,7 +6197,7 @@ auto Parser::parse_parameter_declaration(ParameterDeclarationAST*& yyast, Decl decl{specs}; parse_optional_declarator_or_abstract_declarator(ast->declarator, decl); - ast->type = GetDeclaratorType{this}(ast->declarator, decl.specs.getType()); + ast->type = getDeclaratorType(unit, ast->declarator, decl.specs.getType()); ast->isPack = decl.isPack; if (auto declId = decl.declaratorId; declId && declId->unqualifiedId) { @@ -8752,7 +8363,7 @@ auto Parser::declareTypeAlias(SourceLocation identifierLoc, TypeIdAST* typeId) auto Parser::declareTypedef(DeclaratorAST* declarator, const Decl& decl) -> TypeAliasSymbol* { auto name = decl.getName(); - auto type = GetDeclaratorType{this}(declarator, decl.specs.getType()); + auto type = getDeclaratorType(unit, declarator, decl.specs.getType()); auto symbol = control_->newTypeAliasSymbol(scope_, decl.location()); symbol->setName(name); symbol->setType(type); @@ -8763,7 +8374,7 @@ auto Parser::declareTypedef(DeclaratorAST* declarator, const Decl& decl) auto Parser::declareFunction(DeclaratorAST* declarator, const Decl& decl) -> FunctionSymbol* { auto name = decl.getName(); - auto type = GetDeclaratorType{this}(declarator, decl.specs.getType()); + auto type = getDeclaratorType(unit, declarator, decl.specs.getType()); auto parentScope = scope_; @@ -8816,7 +8427,7 @@ auto Parser::declareFunction(DeclaratorAST* declarator, const Decl& decl) auto Parser::declareField(DeclaratorAST* declarator, const Decl& decl) -> FieldSymbol* { auto name = decl.getName(); - auto type = GetDeclaratorType{this}(declarator, decl.specs.getType()); + auto type = getDeclaratorType(unit, declarator, decl.specs.getType()); auto fieldSymbol = control_->newFieldSymbol(scope_, decl.location()); applySpecifiers(fieldSymbol, decl.specs); fieldSymbol->setName(name); @@ -8833,7 +8444,7 @@ auto Parser::declareVariable(DeclaratorAST* declarator, const Decl& decl) -> VariableSymbol* { auto name = decl.getName(); auto symbol = control_->newVariableSymbol(scope_, decl.location()); - auto type = GetDeclaratorType{this}(declarator, decl.specs.getType()); + auto type = getDeclaratorType(unit, declarator, decl.specs.getType()); applySpecifiers(symbol, decl.specs); symbol->setName(name); symbol->setType(type); @@ -8951,7 +8562,7 @@ auto Parser::parse_conversion_function_id(ConversionFunctionIdAST*& yyast) auto typeId = make_node(pool_); typeId->typeSpecifierList = typeSpecifierList; typeId->declarator = declarator; - typeId->type = GetDeclaratorType{this}(declarator, specs.getType()); + typeId->type = getDeclaratorType(unit, declarator, specs.getType()); auto ast = make_node(pool_); yyast = ast; @@ -10548,7 +10159,7 @@ void Parser::check(ExpressionAST* ast) { auto Parser::convertName(UnqualifiedIdAST* id) -> const Name* { if (!id) return nullptr; - return visit(ConvertToName{control_}, id); + return get_name(control_, id); } auto Parser::getFunction(Scope* scope, const Name* name, const Type* type) diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index bea4e150..258290ec 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -20,7 +20,6 @@ #pragma once -#include #include #include #include @@ -36,6 +35,7 @@ namespace cxx { +class Decl; class DeclSpecs; class Parser final { @@ -71,14 +71,12 @@ class Parser final { void setConfig(ParserConfiguration config); private: - struct Decl; struct TemplateHeadContext; struct ClassSpecifierContext; struct ScopeGuard; struct ExprContext; struct LookaheadParser; struct LoopParser; - struct GetDeclaratorType; enum class BindingContext { kNamespace,