diff --git a/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts b/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts index 69420d99..1c8677b8 100644 --- a/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts +++ b/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts @@ -62,6 +62,9 @@ export function new_ast_rewriter_cc({ emit(); emit(` struct ASTRewriter::${className}Visitor {`); emit(` ${opName}& rewrite;`); + emit( + ` [[nodiscard]] auto translationUnit() const -> TranslationUnit* { return rewrite.unit_; }` + ); emit(); emit( ` [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); }` @@ -88,8 +91,20 @@ export function new_ast_rewriter_cc({ } case "node-list": { emit(); + + // check the base type has a context that must be passed + switch (m.type) { + case "SpecifierAST": + emit(` DeclSpecs ${m.name}Ctx{translationUnit()};`); + break; + + default: + break; + } // switch + emit(` if (auto it = ast->${m.name}) {`); emit(` auto out = ©->${m.name};`); + emit(` for (auto node : ListView{ast->${m.name}}) {`); emit(` auto value = ${visitor}(node);`); if (isBase(m.type)) { @@ -98,6 +113,17 @@ export function new_ast_rewriter_cc({ emit(`*out = new (arena()) List(ast_cast<${m.type}>(value));`); } emit(` out = &(*out)->next;`); + + // update the context if needed + switch (m.type) { + case "SpecifierAST": + emit(`${m.name}Ctx.accept(value);`); + break; + + default: + break; + } // switch + emit(` }`); emit(` }`); emit(); @@ -118,21 +144,34 @@ export function new_ast_rewriter_cc({ by_base.forEach((nodes, base) => { if (base === "AST") return; emit(); - if (base == "ExpressionAST") { - emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); - emit(` if (!ast) return {};`); - emit(` auto expr = visit(${chopAST(base)}Visitor{*this}, ast);`); - emit(` if (expr) typeChecker_->check(expr);`); - emit(` return expr;`); - emit(`}`); - } else { - emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); - emit(` if (ast)`); - emit(` return visit(${chopAST(base)}Visitor{*this}, ast);`); - emit(` return {};`); - emit(`}`); - } + + switch (base) { + case "ExpressionAST": + emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); + emit(` if (!ast) return {};`); + emit(` auto expr = visit(${chopAST(base)}Visitor{*this}, ast);`); + emit(` if (expr) typeChecker_->check(expr);`); + emit(` return expr;`); + emit(`}`); + break; + + case "SpecifierAST": + emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); + emit(` if (!ast) return {};`); + emit(` auto specifier = visit(${chopAST(base)}Visitor{*this}, ast);`); + emit(` return specifier;`); + emit(`}`); + break; + + default: + emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); + emit(` if (!ast) return {};`); + emit(` return visit(${chopAST(base)}Visitor{*this}, ast);`); + emit(`}`); + break; + } // switch }); + by_base.get("AST")?.forEach(({ name, members }) => { emit(); emit(`auto ${opName}::operator()(${name}* ast) -> ${name}* {`); @@ -176,6 +215,7 @@ export function new_ast_rewriter_cc({ #include #include #include +#include namespace cxx { diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt index d59c9962..07850704 100644 --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -21,17 +21,18 @@ file(GLOB CXX_INCLUDE_HEADER_FILES cxx/*.h) file(GLOB CXX_VIEWS_INCLUDE_HEADER_FILES cxx/views/*.h) add_library(cxx-parser - cxx/ast.cc cxx/ast_cursor.cc cxx/ast_interpreter.cc cxx/ast_rewriter.cc cxx/ast_slot.cc + cxx/ast.cc cxx/base_classes.cc cxx/cli.cc cxx/const_expression_evaluator.cc cxx/const_value.cc cxx/control.cc cxx/cxx.cc + cxx/decl_specs.cc cxx/diagnostic.cc cxx/diagnostics_client.cc cxx/external_name_encoder.cc diff --git a/src/parser/cxx/ast.h b/src/parser/cxx/ast.h index c0240e1f..abce3d5e 100644 --- a/src/parser/cxx/ast.h +++ b/src/parser/cxx/ast.h @@ -2998,6 +2998,7 @@ class NamedTypeSpecifierAST final : public SpecifierAST { SourceLocation templateLoc; UnqualifiedIdAST* unqualifiedId = nullptr; bool isTemplateIntroduced = false; + Symbol* 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 37361458..428d06fe 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -23,6 +23,7 @@ // cxx #include #include +#include #include #include @@ -42,6 +43,9 @@ auto ASTRewriter::arena() const -> Arena* { return unit_->arena(); } struct ASTRewriter::UnitVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -52,6 +56,9 @@ struct ASTRewriter::UnitVisitor { struct ASTRewriter::DeclarationVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -127,6 +134,9 @@ struct ASTRewriter::DeclarationVisitor { struct ASTRewriter::StatementVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -172,6 +182,9 @@ struct ASTRewriter::StatementVisitor { struct ASTRewriter::ExpressionVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -317,6 +330,9 @@ struct ASTRewriter::ExpressionVisitor { struct ASTRewriter::TemplateParameterVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -335,6 +351,9 @@ struct ASTRewriter::TemplateParameterVisitor { struct ASTRewriter::SpecifierVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -418,6 +437,9 @@ struct ASTRewriter::SpecifierVisitor { struct ASTRewriter::PtrOperatorVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -430,6 +452,9 @@ struct ASTRewriter::PtrOperatorVisitor { struct ASTRewriter::CoreDeclaratorVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -445,6 +470,9 @@ struct ASTRewriter::CoreDeclaratorVisitor { struct ASTRewriter::DeclaratorChunkVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -457,6 +485,9 @@ struct ASTRewriter::DeclaratorChunkVisitor { struct ASTRewriter::UnqualifiedIdVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -485,6 +516,9 @@ struct ASTRewriter::UnqualifiedIdVisitor { struct ASTRewriter::NestedNameSpecifierVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -503,6 +537,9 @@ struct ASTRewriter::NestedNameSpecifierVisitor { struct ASTRewriter::FunctionBodyVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -520,6 +557,9 @@ struct ASTRewriter::FunctionBodyVisitor { struct ASTRewriter::TemplateArgumentVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -532,6 +572,9 @@ struct ASTRewriter::TemplateArgumentVisitor { struct ASTRewriter::ExceptionSpecifierVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -544,6 +587,9 @@ struct ASTRewriter::ExceptionSpecifierVisitor { struct ASTRewriter::RequirementVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -558,6 +604,9 @@ struct ASTRewriter::RequirementVisitor { struct ASTRewriter::NewInitializerVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -570,6 +619,9 @@ struct ASTRewriter::NewInitializerVisitor { struct ASTRewriter::MemInitializerVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -582,6 +634,9 @@ struct ASTRewriter::MemInitializerVisitor { struct ASTRewriter::LambdaCaptureVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -603,6 +658,9 @@ struct ASTRewriter::LambdaCaptureVisitor { struct ASTRewriter::ExceptionDeclarationVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -615,6 +673,9 @@ struct ASTRewriter::ExceptionDeclarationVisitor { struct ASTRewriter::AttributeSpecifierVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -633,6 +694,9 @@ struct ASTRewriter::AttributeSpecifierVisitor { struct ASTRewriter::AttributeTokenVisitor { ASTRewriter& rewrite; + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { + return rewrite.unit_; + } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } @@ -644,18 +708,18 @@ struct ASTRewriter::AttributeTokenVisitor { }; auto ASTRewriter::operator()(UnitAST* ast) -> UnitAST* { - if (ast) return visit(UnitVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(UnitVisitor{*this}, ast); } auto ASTRewriter::operator()(DeclarationAST* ast) -> DeclarationAST* { - if (ast) return visit(DeclarationVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(DeclarationVisitor{*this}, ast); } auto ASTRewriter::operator()(StatementAST* ast) -> StatementAST* { - if (ast) return visit(StatementVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(StatementVisitor{*this}, ast); } auto ASTRewriter::operator()(ExpressionAST* ast) -> ExpressionAST* { @@ -667,92 +731,93 @@ auto ASTRewriter::operator()(ExpressionAST* ast) -> ExpressionAST* { auto ASTRewriter::operator()(TemplateParameterAST* ast) -> TemplateParameterAST* { - if (ast) return visit(TemplateParameterVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(TemplateParameterVisitor{*this}, ast); } auto ASTRewriter::operator()(SpecifierAST* ast) -> SpecifierAST* { - if (ast) return visit(SpecifierVisitor{*this}, ast); - return {}; + if (!ast) return {}; + auto specifier = visit(SpecifierVisitor{*this}, ast); + return specifier; } auto ASTRewriter::operator()(PtrOperatorAST* ast) -> PtrOperatorAST* { - if (ast) return visit(PtrOperatorVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(PtrOperatorVisitor{*this}, ast); } auto ASTRewriter::operator()(CoreDeclaratorAST* ast) -> CoreDeclaratorAST* { - if (ast) return visit(CoreDeclaratorVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(CoreDeclaratorVisitor{*this}, ast); } auto ASTRewriter::operator()(DeclaratorChunkAST* ast) -> DeclaratorChunkAST* { - if (ast) return visit(DeclaratorChunkVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(DeclaratorChunkVisitor{*this}, ast); } auto ASTRewriter::operator()(UnqualifiedIdAST* ast) -> UnqualifiedIdAST* { - if (ast) return visit(UnqualifiedIdVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(UnqualifiedIdVisitor{*this}, ast); } auto ASTRewriter::operator()(NestedNameSpecifierAST* ast) -> NestedNameSpecifierAST* { - if (ast) return visit(NestedNameSpecifierVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(NestedNameSpecifierVisitor{*this}, ast); } auto ASTRewriter::operator()(FunctionBodyAST* ast) -> FunctionBodyAST* { - if (ast) return visit(FunctionBodyVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(FunctionBodyVisitor{*this}, ast); } auto ASTRewriter::operator()(TemplateArgumentAST* ast) -> TemplateArgumentAST* { - if (ast) return visit(TemplateArgumentVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(TemplateArgumentVisitor{*this}, ast); } auto ASTRewriter::operator()(ExceptionSpecifierAST* ast) -> ExceptionSpecifierAST* { - if (ast) return visit(ExceptionSpecifierVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(ExceptionSpecifierVisitor{*this}, ast); } auto ASTRewriter::operator()(RequirementAST* ast) -> RequirementAST* { - if (ast) return visit(RequirementVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(RequirementVisitor{*this}, ast); } auto ASTRewriter::operator()(NewInitializerAST* ast) -> NewInitializerAST* { - if (ast) return visit(NewInitializerVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(NewInitializerVisitor{*this}, ast); } auto ASTRewriter::operator()(MemInitializerAST* ast) -> MemInitializerAST* { - if (ast) return visit(MemInitializerVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(MemInitializerVisitor{*this}, ast); } auto ASTRewriter::operator()(LambdaCaptureAST* ast) -> LambdaCaptureAST* { - if (ast) return visit(LambdaCaptureVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(LambdaCaptureVisitor{*this}, ast); } auto ASTRewriter::operator()(ExceptionDeclarationAST* ast) -> ExceptionDeclarationAST* { - if (ast) return visit(ExceptionDeclarationVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(ExceptionDeclarationVisitor{*this}, ast); } auto ASTRewriter::operator()(AttributeSpecifierAST* ast) -> AttributeSpecifierAST* { - if (ast) return visit(AttributeSpecifierVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(AttributeSpecifierVisitor{*this}, ast); } auto ASTRewriter::operator()(AttributeTokenAST* ast) -> AttributeTokenAST* { - if (ast) return visit(AttributeTokenVisitor{*this}, ast); - return {}; + if (!ast) return {}; + return visit(AttributeTokenVisitor{*this}, ast); } auto ASTRewriter::operator()(SplicerAST* ast) -> SplicerAST* { @@ -971,12 +1036,14 @@ auto ASTRewriter::operator()(TypeIdAST* ast) -> TypeIdAST* { auto copy = new (arena()) TypeIdAST{}; + DeclSpecs typeSpecifierListCtx{translationUnit()}; if (auto it = ast->typeSpecifierList) { auto out = ©->typeSpecifierList; for (auto node : ListView{ast->typeSpecifierList}) { auto value = operator()(node); *out = new (arena()) List(value); out = &(*out)->next; + typeSpecifierListCtx.accept(value); } } @@ -1227,12 +1294,14 @@ auto ASTRewriter::DeclarationVisitor::operator()(SimpleDeclarationAST* ast) } } + DeclSpecs declSpecifierListCtx{translationUnit()}; if (auto it = ast->declSpecifierList) { auto out = ©->declSpecifierList; for (auto node : ListView{ast->declSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + declSpecifierListCtx.accept(value); } } @@ -1460,12 +1529,14 @@ auto ASTRewriter::DeclarationVisitor::operator()(OpaqueEnumDeclarationAST* ast) copy->unqualifiedId = ast_cast(rewrite(ast->unqualifiedId)); copy->colonLoc = ast->colonLoc; + DeclSpecs typeSpecifierListCtx{translationUnit()}; if (auto it = ast->typeSpecifierList) { auto out = ©->typeSpecifierList; for (auto node : ListView{ast->typeSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + typeSpecifierListCtx.accept(value); } } @@ -1487,12 +1558,14 @@ auto ASTRewriter::DeclarationVisitor::operator()(FunctionDefinitionAST* ast) } } + DeclSpecs declSpecifierListCtx{translationUnit()}; if (auto it = ast->declSpecifierList) { auto out = ©->declSpecifierList; for (auto node : ListView{ast->declSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + declSpecifierListCtx.accept(value); } } @@ -1742,12 +1815,14 @@ auto ASTRewriter::DeclarationVisitor::operator()(ParameterDeclarationAST* ast) copy->thisLoc = ast->thisLoc; + DeclSpecs typeSpecifierListCtx{translationUnit()}; if (auto it = ast->typeSpecifierList) { auto out = ©->typeSpecifierList; for (auto node : ListView{ast->typeSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + typeSpecifierListCtx.accept(value); } } @@ -1793,12 +1868,14 @@ auto ASTRewriter::DeclarationVisitor::operator()( } } + DeclSpecs declSpecifierListCtx{translationUnit()}; if (auto it = ast->declSpecifierList) { auto out = ©->declSpecifierList; for (auto node : ListView{ast->declSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + declSpecifierListCtx.accept(value); } } @@ -2811,12 +2888,14 @@ auto ASTRewriter::ExpressionVisitor::operator()(NewExpressionAST* ast) copy->newPlacement = rewrite(ast->newPlacement); copy->lparenLoc = ast->lparenLoc; + DeclSpecs typeSpecifierListCtx{translationUnit()}; if (auto it = ast->typeSpecifierList) { auto out = ©->typeSpecifierList; for (auto node : ListView{ast->typeSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + typeSpecifierListCtx.accept(value); } } @@ -3001,12 +3080,14 @@ auto ASTRewriter::ExpressionVisitor::operator()(ConditionExpressionAST* ast) } } + DeclSpecs declSpecifierListCtx{translationUnit()}; if (auto it = ast->declSpecifierList) { auto out = ©->declSpecifierList; for (auto node : ListView{ast->declSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + declSpecifierListCtx.accept(value); } } @@ -3368,6 +3449,7 @@ auto ASTRewriter::SpecifierVisitor::operator()(NamedTypeSpecifierAST* ast) copy->templateLoc = ast->templateLoc; copy->unqualifiedId = rewrite(ast->unqualifiedId); copy->isTemplateIntroduced = ast->isTemplateIntroduced; + copy->symbol = ast->symbol; return copy; } @@ -3503,12 +3585,14 @@ auto ASTRewriter::SpecifierVisitor::operator()(EnumSpecifierAST* ast) copy->unqualifiedId = ast_cast(rewrite(ast->unqualifiedId)); copy->colonLoc = ast->colonLoc; + DeclSpecs typeSpecifierListCtx{translationUnit()}; if (auto it = ast->typeSpecifierList) { auto out = ©->typeSpecifierList; for (auto node : ListView{ast->typeSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + typeSpecifierListCtx.accept(value); } } @@ -3614,12 +3698,14 @@ auto ASTRewriter::PtrOperatorVisitor::operator()(PointerOperatorAST* ast) } } + DeclSpecs cvQualifierListCtx{translationUnit()}; if (auto it = ast->cvQualifierList) { auto out = ©->cvQualifierList; for (auto node : ListView{ast->cvQualifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + cvQualifierListCtx.accept(value); } } @@ -3662,12 +3748,14 @@ auto ASTRewriter::PtrOperatorVisitor::operator()(PtrToMemberOperatorAST* ast) } } + DeclSpecs cvQualifierListCtx{translationUnit()}; if (auto it = ast->cvQualifierList) { auto out = ©->cvQualifierList; for (auto node : ListView{ast->cvQualifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + cvQualifierListCtx.accept(value); } } @@ -3736,12 +3824,14 @@ auto ASTRewriter::DeclaratorChunkVisitor::operator()( copy->parameterDeclarationClause = rewrite(ast->parameterDeclarationClause); copy->rparenLoc = ast->rparenLoc; + DeclSpecs cvQualifierListCtx{translationUnit()}; if (auto it = ast->cvQualifierList) { auto out = ©->cvQualifierList; for (auto node : ListView{ast->cvQualifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + cvQualifierListCtx.accept(value); } } @@ -4283,12 +4373,14 @@ auto ASTRewriter::ExceptionDeclarationVisitor::operator()( } } + DeclSpecs typeSpecifierListCtx{translationUnit()}; if (auto it = ast->typeSpecifierList) { auto out = ©->typeSpecifierList; for (auto node : ListView{ast->typeSpecifierList}) { auto value = rewrite(node); *out = new (arena()) List(value); out = &(*out)->next; + typeSpecifierListCtx.accept(value); } } diff --git a/src/parser/cxx/control.cc b/src/parser/cxx/control.cc index a028f276..950a3b1f 100644 --- a/src/parser/cxx/control.cc +++ b/src/parser/cxx/control.cc @@ -346,6 +346,14 @@ auto Control::getLongDoubleType() -> const LongDoubleType* { auto Control::getQualType(const Type* elementType, CvQualifiers cvQualifiers) -> const QualType* { + if (auto qualType = type_cast(elementType)) { + cvQualifiers = cvQualifiers | qualType->cvQualifiers(); + return &*d->qualTypes + .emplace(qualType->elementType(), + cvQualifiers | qualType->cvQualifiers()) + .first; + } + return &*d->qualTypes.emplace(elementType, cvQualifiers).first; } diff --git a/src/parser/cxx/decl_specs.cc b/src/parser/cxx/decl_specs.cc new file mode 100644 index 00000000..4d7dd4f8 --- /dev/null +++ b/src/parser/cxx/decl_specs.cc @@ -0,0 +1,260 @@ +// 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 +// FRnewOM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include + +// cxx +#include +#include +#include +#include + +namespace cxx { + +struct DeclSpecs::Visitor { + DeclSpecs& specs; + + void operator()(GeneratedTypeSpecifierAST* ast); + void operator()(TypedefSpecifierAST* ast); + void operator()(FriendSpecifierAST* ast); + void operator()(ConstevalSpecifierAST* ast); + void operator()(ConstinitSpecifierAST* ast); + void operator()(ConstexprSpecifierAST* ast); + void operator()(InlineSpecifierAST* ast); + void operator()(StaticSpecifierAST* ast); + void operator()(ExternSpecifierAST* ast); + void operator()(ThreadLocalSpecifierAST* ast); + void operator()(ThreadSpecifierAST* ast); + void operator()(MutableSpecifierAST* ast); + void operator()(VirtualSpecifierAST* ast); + void operator()(ExplicitSpecifierAST* ast); + void operator()(AutoTypeSpecifierAST* ast); + void operator()(VoidTypeSpecifierAST* ast); + void operator()(SizeTypeSpecifierAST* ast); + void operator()(SignTypeSpecifierAST* ast); + void operator()(VaListTypeSpecifierAST* ast); + void operator()(IntegralTypeSpecifierAST* ast); + void operator()(FloatingPointTypeSpecifierAST* ast); + void operator()(ComplexTypeSpecifierAST* ast); + void operator()(NamedTypeSpecifierAST* ast); + void operator()(AtomicTypeSpecifierAST* ast); + void operator()(UnderlyingTypeSpecifierAST* ast); + void operator()(ElaboratedTypeSpecifierAST* ast); + void operator()(DecltypeAutoSpecifierAST* ast); + void operator()(DecltypeSpecifierAST* ast); + void operator()(PlaceholderTypeSpecifierAST* ast); + void operator()(ConstQualifierAST* ast); + void operator()(VolatileQualifierAST* ast); + void operator()(RestrictQualifierAST* ast); + void operator()(EnumSpecifierAST* ast); + void operator()(ClassSpecifierAST* ast); + void operator()(TypenameSpecifierAST* ast); + void operator()(SplicerTypeSpecifierAST* ast); +}; + +void DeclSpecs::Visitor::operator()(GeneratedTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(TypedefSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(FriendSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ConstevalSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ConstinitSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ConstexprSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(InlineSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(StaticSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ExternSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ThreadLocalSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ThreadSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(MutableSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(VirtualSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ExplicitSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(AutoTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(VoidTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(SizeTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(SignTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(VaListTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(IntegralTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(FloatingPointTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ComplexTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(NamedTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(AtomicTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(UnderlyingTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ElaboratedTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(DecltypeAutoSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(DecltypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(PlaceholderTypeSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ConstQualifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(VolatileQualifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(RestrictQualifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(EnumSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(ClassSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(TypenameSpecifierAST* ast) {} + +void DeclSpecs::Visitor::operator()(SplicerTypeSpecifierAST* ast) {} + +DeclSpecs::DeclSpecs(TranslationUnit* unit) : unit(unit) {} + +auto DeclSpecs::control() const -> Control* { return unit->control(); } + +void DeclSpecs::accept(SpecifierAST* specifier) { + if (!specifier) return; + visit(Visitor{*this}, specifier); +} + +auto DeclSpecs::getType() const -> const Type* { + auto type = this->type; + + if (!type || type == control()->getIntType()) { + if (isLongLong && isUnsigned) + type = control()->getUnsignedLongLongIntType(); + else if (isLongLong) + type = control()->getLongLongIntType(); + else if (isLong && isUnsigned) + type = control()->getUnsignedLongIntType(); + else if (isLong) + type = control()->getLongIntType(); + else if (isShort && isUnsigned) + type = control()->getUnsignedShortIntType(); + else if (isShort) + type = control()->getShortIntType(); + else if (isUnsigned) + type = control()->getUnsignedIntType(); + else if (isSigned) + type = control()->getIntType(); + } + + if (!type) return nullptr; + + if (type == control()->getDoubleType() && isLong) + type = control()->getLongDoubleType(); + + if (isSigned && type == control()->getCharType()) + type = control()->getSignedCharType(); + + if (isUnsigned) { + switch (type->kind()) { + case TypeKind::kChar: + type = control()->getUnsignedCharType(); + break; + case TypeKind::kShortInt: + type = control()->getUnsignedShortIntType(); + break; + case TypeKind::kInt: + type = control()->getUnsignedIntType(); + break; + case TypeKind::kLongInt: + type = control()->getUnsignedLongIntType(); + break; + case TypeKind::kLongLongInt: + type = control()->getUnsignedLongLongIntType(); + break; + case TypeKind::kChar8: + type = control()->getUnsignedCharType(); + break; + case TypeKind::kChar16: + type = control()->getUnsignedShortIntType(); + break; + case TypeKind::kChar32: + type = control()->getUnsignedIntType(); + break; + case TypeKind::kWideChar: + type = control()->getUnsignedIntType(); + break; + default: + break; + } // switch + } + + if (isConst) type = control()->add_const(type); + if (isVolatile) type = control()->add_volatile(type); + + return type; +} + +auto DeclSpecs::hasTypeSpecifier() const -> bool { + if (typeSpecifier) return true; + if (isShort || isLong) return true; + if (isSigned || isUnsigned) return true; + return false; +} + +void DeclSpecs::setTypeSpecifier(SpecifierAST* specifier) { + typeSpecifier = specifier; +} + +auto DeclSpecs::hasClassOrEnumSpecifier() const -> bool { + if (!typeSpecifier) return false; + switch (typeSpecifier->kind()) { + case ASTKind::ClassSpecifier: + case ASTKind::EnumSpecifier: + case ASTKind::ElaboratedTypeSpecifier: + case ASTKind::TypenameSpecifier: + return true; + default: + return false; + } // switch +} + +auto DeclSpecs::hasPlaceholderTypeSpecifier() const -> bool { + if (!typeSpecifier) return false; + switch (typeSpecifier->kind()) { + case ASTKind::AutoTypeSpecifier: + case ASTKind::DecltypeAutoSpecifier: + case ASTKind::PlaceholderTypeSpecifier: + case ASTKind::DecltypeSpecifier: + return true; + default: + return false; + } // switch +} + +} // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/decl_specs.h b/src/parser/cxx/decl_specs.h new file mode 100644 index 00000000..3cc856cd --- /dev/null +++ b/src/parser/cxx/decl_specs.h @@ -0,0 +1,94 @@ +// 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 +// FRnewOM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include +#include + +namespace cxx { + +class Control; +class TranslationUnit; + +class DeclSpecs { + struct Visitor; + + public: + explicit DeclSpecs(TranslationUnit* unit = nullptr); + + [[nodiscard]] auto control() const -> Control*; + [[nodiscard]] auto getType() const -> const Type*; + + [[nodiscard]] auto hasTypeSpecifier() const -> bool; + void setTypeSpecifier(SpecifierAST* specifier); + + [[nodiscard]] auto hasClassOrEnumSpecifier() const -> bool; + [[nodiscard]] auto hasPlaceholderTypeSpecifier() const -> bool; + + void accept(SpecifierAST* specifier); + + const Type* type = nullptr; + SpecifierAST* typeSpecifier = nullptr; + + TranslationUnit* unit; + + bool isTypedef = false; + bool isFriend = false; + bool isConstexpr = false; + bool isConsteval = false; + bool isConstinit = false; + bool isInline = false; + + // cv qualifiers + bool isConst = false; + bool isVolatile = false; + bool isRestrict = false; + + // storage class specifiers + bool isStatic = false; + bool isThreadLocal = false; + bool isExtern = false; + bool isMutable = false; + bool isThread = false; + + // function specifiers + bool isVirtual = false; + bool isExplicit = false; + + // sign specifiers + bool isSigned = false; + bool isUnsigned = false; + + // sized specifiers + bool isShort = false; + bool isLong = false; + bool isLongLong = false; + + bool isComplex = false; + + // placeholder type specifiers + bool isAuto = false; + bool isDecltypeAuto = false; + + // internal state, used during parsing + bool no_typespecs = false; + bool no_class_or_enum_specs = false; +}; + +} // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index e6e19eeb..97f91cfb 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -275,18 +276,18 @@ struct Parser::GetDeclaratorType { for (auto it = ast->cvQualifierList; it; it = it->next) { if (ast_cast(it->value)) { - type_ = control()->getConstType(type_); + type_ = control()->add_const(type_); } else if (ast_cast(it->value)) { - type_ = control()->getVolatileType(type_); + type_ = control()->add_volatile(type_); } } } void operator()(ReferenceOperatorAST* ast) { if (ast->refOp == TokenKind::T_AMP_AMP) { - type_ = control()->getRvalueReferenceType(type_); + type_ = control()->add_rvalue_reference(type_); } else { - type_ = control()->getLvalueReferenceType(type_); + type_ = control()->add_lvalue_reference(type_); } } @@ -307,9 +308,9 @@ struct Parser::GetDeclaratorType { for (auto it = ast->cvQualifierList; it; it = it->next) { if (ast_cast(it->value)) { - type_ = control()->getConstType(type_); + type_ = control()->add_const(type_); } else if (ast_cast(it->value)) { - type_ = control()->getVolatileType(type_); + type_ = control()->add_volatile(type_); } } } @@ -473,168 +474,6 @@ struct Parser::LoopParser { } }; -struct Parser::DeclSpecs { - Parser* parser = nullptr; - - explicit DeclSpecs(Parser* parser) : parser(parser) {} - - auto control() const -> Control* { return parser->control_; } - - auto getType() const -> const Type* { - auto type = this->type; - - if (!type || type == control()->getIntType()) { - if (isLongLong && isUnsigned) - type = control()->getUnsignedLongLongIntType(); - else if (isLongLong) - type = control()->getLongLongIntType(); - else if (isLong && isUnsigned) - type = control()->getUnsignedLongIntType(); - else if (isLong) - type = control()->getLongIntType(); - else if (isShort && isUnsigned) - type = control()->getUnsignedShortIntType(); - else if (isShort) - type = control()->getShortIntType(); - else if (isUnsigned) - type = control()->getUnsignedIntType(); - else if (isSigned) - type = control()->getIntType(); - } - - if (!type) return nullptr; - - if (type == control()->getDoubleType() && isLong) - type = control()->getLongDoubleType(); - - if (isSigned && type == control()->getCharType()) - type = control()->getSignedCharType(); - - if (isUnsigned) { - switch (type->kind()) { - case TypeKind::kChar: - type = control()->getUnsignedCharType(); - break; - case TypeKind::kShortInt: - type = control()->getUnsignedShortIntType(); - break; - case TypeKind::kInt: - type = control()->getUnsignedIntType(); - break; - case TypeKind::kLongInt: - type = control()->getUnsignedLongIntType(); - break; - case TypeKind::kLongLongInt: - type = control()->getUnsignedLongLongIntType(); - break; - case TypeKind::kChar8: - type = control()->getUnsignedCharType(); - break; - case TypeKind::kChar16: - type = control()->getUnsignedShortIntType(); - break; - case TypeKind::kChar32: - type = control()->getUnsignedIntType(); - break; - case TypeKind::kWideChar: - type = control()->getUnsignedIntType(); - break; - default: - break; - } // switch - } - - if (isConst && isVolatile) { - type = control()->getConstVolatileType(type); - } else if (isConst) { - type = control()->getConstType(type); - } else if (isVolatile) { - type = control()->getVolatileType(type); - } - - return type; - } - - [[nodiscard]] auto hasTypeSpecifier() const -> bool { - if (typeSpecifier) return true; - if (isShort || isLong) return true; - if (isSigned || isUnsigned) return true; - return false; - } - - void setTypeSpecifier(SpecifierAST* specifier) { typeSpecifier = specifier; } - - [[nodiscard]] auto hasClassOrEnumSpecifier() const -> bool { - if (!typeSpecifier) return false; - switch (typeSpecifier->kind()) { - case ASTKind::ClassSpecifier: - case ASTKind::EnumSpecifier: - case ASTKind::ElaboratedTypeSpecifier: - case ASTKind::TypenameSpecifier: - return true; - default: - return false; - } // switch - } - - [[nodiscard]] auto hasPlaceholderTypeSpecifier() const -> bool { - if (!typeSpecifier) return false; - switch (typeSpecifier->kind()) { - case ASTKind::AutoTypeSpecifier: - case ASTKind::DecltypeAutoSpecifier: - case ASTKind::PlaceholderTypeSpecifier: - case ASTKind::DecltypeSpecifier: - return true; - default: - return false; - } // switch - } - - const Type* type = nullptr; - SpecifierAST* typeSpecifier = nullptr; - - bool isTypedef = false; - bool isFriend = false; - bool isConstexpr = false; - bool isConsteval = false; - bool isConstinit = false; - bool isInline = false; - - // cv qualifiers - bool isConst = false; - bool isVolatile = false; - bool isRestrict = false; - - // storage class specifiers - bool isStatic = false; - bool isThreadLocal = false; - bool isExtern = false; - bool isMutable = false; - bool isThread = false; - - // function specifiers - bool isVirtual = false; - bool isExplicit = false; - - // sign specifiers - bool isSigned = false; - bool isUnsigned = false; - - // sized specifiers - bool isShort = false; - bool isLong = false; - bool isLongLong = false; - - bool isComplex = false; - - // placeholder type specifiers - bool isAuto = false; - bool isDecltypeAuto = false; - - bool no_typespecs = false; - bool no_class_or_enum_specs = false; -}; - struct Parser::Decl { DeclSpecs specs; IdDeclaratorAST* declaratorId = nullptr; @@ -1113,7 +952,7 @@ auto Parser::parse_literal(ExpressionAST*& yyast) -> bool { if (unit->tokenKind(literalLoc) == TokenKind::T_STRING_LITERAL) { ast->type = control_->getBoundedArrayType( - control_->getConstType(control_->getCharType()), + control_->add_const(control_->getCharType()), ast->literal->stringValue().size() + 1); ast->valueCategory = ValueCategory::kLValue; @@ -2724,7 +2563,7 @@ auto Parser::parse_cpp_type_cast_expression(ExpressionAST*& yyast, LookaheadParser lookahead{this}; SpecifierAST* typeSpecifier = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_simple_type_specifier(typeSpecifier, specs)) return false; @@ -2740,7 +2579,7 @@ auto Parser::parse_cpp_type_cast_expression(ExpressionAST*& yyast, LookaheadParser lookahead{this}; SpecifierAST* typeSpecifier = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_simple_type_specifier(typeSpecifier, specs)) return false; @@ -2765,7 +2604,7 @@ auto Parser::parse_cpp_type_cast_expression(ExpressionAST*& yyast, LookaheadParser lookahead{this}; SpecifierAST* typeSpecifier = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_simple_type_specifier(typeSpecifier, specs)) return false; @@ -2847,7 +2686,7 @@ auto Parser::parse_typename_expression(ExpressionAST*& yyast, LookaheadParser lookahead{this}; SpecifierAST* typenameSpecifier = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_typename_specifier(typenameSpecifier, specs)) return false; if (BracedInitListAST* bracedInitList = nullptr; @@ -3219,7 +3058,7 @@ auto Parser::parse_new_expression(ExpressionAST*& yyast, const ExprContext& ctx) if (!match(TokenKind::T_LPAREN, lparenLoc)) return false; List* typeSpecifierList = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_type_specifier_seq(typeSpecifierList, specs)) return false; DeclaratorAST* declarator = nullptr; @@ -3244,7 +3083,7 @@ auto Parser::parse_new_expression(ExpressionAST*& yyast, const ExprContext& ctx) if (lookat_nested_type_id()) return true; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_type_specifier_seq(ast->typeSpecifierList, specs)) parse_error("expected a type specifier"); @@ -3816,7 +3655,7 @@ void Parser::parse_condition(ExpressionAST*& yyast, const ExprContext& ctx) { List* declSpecifierList = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_decl_specifier_seq(declSpecifierList, specs, {})) return false; @@ -4241,7 +4080,7 @@ auto Parser::parse_for_range_declaration(DeclarationAST*& yyast) -> bool { List* declSpecifierList = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_decl_specifier_seq(declSpecifierList, specs, {})) return false; @@ -4631,13 +4470,13 @@ auto Parser::parse_notypespec_function_definition( LookaheadParser lookahead{this}; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; List* declSpecifierList = nullptr; auto parse_optional_decl_specifier_seq_no_typespecs = [&] { LookaheadParser lookahead{this}; if (!parse_decl_specifier_seq_no_typespecs(declSpecifierList, specs)) { - specs = DeclSpecs{this}; + specs = DeclSpecs{unit}; return; } lookahead.commit(); @@ -4776,7 +4615,7 @@ auto Parser::parse_simple_declaration( templateDeclarations, ctx)) return true; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; List* declSpecifierList = nullptr; auto lookat_decl_specifiers = [&] { @@ -5657,6 +5496,8 @@ auto Parser::parse_named_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) return false; } + Symbol* typeSymbol = nullptr; + if (auto templateId = ast_cast(unqualifiedId)) { if (auto conceptSymbol = symbol_cast(templateId->primaryTemplateSymbol)) { @@ -5672,6 +5513,7 @@ auto Parser::parse_named_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) Lookup{scope_}.lookupType(nestedNameSpecifier, name->identifier); if (is_type(symbol)) { + typeSymbol = symbol; specs.type = symbol->type(); } else { if (config_.checkTypes) return false; @@ -5692,6 +5534,7 @@ auto Parser::parse_named_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) ast->templateLoc = templateLoc; ast->unqualifiedId = unqualifiedId; ast->isTemplateIntroduced = isTemplateIntroduced; + ast->symbol = typeSymbol; return true; } @@ -6090,7 +5933,7 @@ auto Parser::parse_elaborated_type_specifier( auto Parser::parse_decl_specifier_seq_no_typespecs(List*& yyast) -> bool { - DeclSpecs specs{this}; + DeclSpecs specs{unit}; return parse_decl_specifier_seq_no_typespecs(yyast, specs); } @@ -6414,7 +6257,7 @@ auto Parser::parse_function_declarator(FunctionDeclaratorChunkAST*& yyast, ast->parameterDeclarationClause = parameterDeclarationClause; ast->rparenLoc = rparenLoc; - DeclSpecs cvQualifiers{this}; + DeclSpecs cvQualifiers{unit}; (void)parse_cv_qualifier_seq(ast->cvQualifierList, cvQualifiers); @@ -6479,7 +6322,7 @@ auto Parser::parse_ptr_operator(PtrOperatorAST*& yyast) -> bool { parse_optional_attribute_specifier_seq(ast->attributeList); - DeclSpecs cvQualifiers{this}; + DeclSpecs cvQualifiers{unit}; (void)parse_cv_qualifier_seq(ast->cvQualifierList, cvQualifiers); return true; @@ -6515,7 +6358,7 @@ auto Parser::parse_ptr_operator(PtrOperatorAST*& yyast) -> bool { parse_optional_attribute_specifier_seq(ast->attributeList); - DeclSpecs cvQualifiers{this}; + DeclSpecs cvQualifiers{unit}; (void)parse_cv_qualifier_seq(ast->cvQualifierList, cvQualifiers); return true; @@ -6621,7 +6464,7 @@ auto Parser::parse_declarator_id(CoreDeclaratorAST*& yyast, Decl& decl, auto Parser::parse_type_id(TypeIdAST*& yyast) -> bool { List* specifierList = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_type_specifier_seq(specifierList, specs)) return false; yyast = make_node(pool_); @@ -6639,7 +6482,7 @@ auto Parser::parse_type_id(TypeIdAST*& yyast) -> bool { auto Parser::parse_defining_type_id( TypeIdAST*& yyast, const std::vector& templateDeclarations) -> bool { - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!templateDeclarations.empty()) specs.no_class_or_enum_specs = true; @@ -6781,7 +6624,7 @@ auto Parser::parse_parameter_declaration(ParameterDeclarationAST*& yyast, parse_optional_attribute_specifier_seq(ast->attributeList); - DeclSpecs specs{this}; + DeclSpecs specs{unit}; specs.no_class_or_enum_specs = true; @@ -7144,7 +6987,7 @@ auto Parser::parse_enum_specifier(SpecifierAST*& yyast, DeclSpecs& specs) SourceLocation colonLoc; List* typeSpecifierList = nullptr; - DeclSpecs underlyingTypeSpecs{this}; + DeclSpecs underlyingTypeSpecs{unit}; (void)parse_enum_base(colonLoc, typeSpecifierList, underlyingTypeSpecs); SourceLocation lbraceLoc; @@ -7231,7 +7074,7 @@ auto Parser::parse_opaque_enum_declaration(DeclarationAST*& yyast) -> bool { NestedNameSpecifierAST* nestedNameSpecifier = nullptr; NameIdAST* name = nullptr; SourceLocation colonLoc; - DeclSpecs underlyingTypeSpecs{this}; + DeclSpecs underlyingTypeSpecs{unit}; List* typeSpecifierList = nullptr; SourceLocation semicolonLoc; @@ -7360,7 +7203,7 @@ auto Parser::parse_using_enum_declaration(DeclarationAST*& yyast) -> bool { expect(TokenKind::T_USING, ast->usingLoc); - DeclSpecs specs{this}; + DeclSpecs specs{unit}; SpecifierAST* typeSpecifier = nullptr; if (!parse_elaborated_type_specifier(typeSpecifier, specs, {})) { @@ -8750,7 +8593,7 @@ auto Parser::parse_member_declaration_helper(DeclarationAST*& yyast) -> bool { parse_optional_attribute_specifier_seq(attributes); List* declSpecifierList = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; (void)parse_decl_specifier_seq_no_typespecs(declSpecifierList, specs); auto lookat_notypespec_function_definition = [&] { @@ -9146,7 +8989,7 @@ auto Parser::parse_conversion_function_id(ConversionFunctionIdAST*& yyast) if (!match(TokenKind::T_OPERATOR, operatorLoc)) return false; List* typeSpecifierList = nullptr; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_type_specifier_seq(typeSpecifierList, specs)) return false; lookahead.commit(); @@ -10281,7 +10124,7 @@ auto Parser::parse_deduction_guide(DeclarationAST*& yyast) -> bool { auto lookat_deduction_guide = [&] { LookaheadParser lookahead{this}; - DeclSpecs specs{this}; + DeclSpecs specs{unit}; (void)parse_explicit_specifier(explicitSpecifier, specs); if (!match(TokenKind::T_IDENTIFIER, identifierLoc)) return false; @@ -10579,7 +10422,7 @@ auto Parser::parse_exception_declaration(ExceptionDeclarationAST*& yyast) parse_optional_attribute_specifier_seq(ast->attributeList); - DeclSpecs specs{this}; + DeclSpecs specs{unit}; if (!parse_type_specifier_seq(ast->typeSpecifierList, specs)) { parse_error("expected a type specifier"); } diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index 490f0f39..bea4e150 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -36,6 +36,8 @@ namespace cxx { +class DeclSpecs; + class Parser final { public: Parser(const Parser&) = delete; @@ -69,7 +71,6 @@ class Parser final { void setConfig(ParserConfiguration config); private: - struct DeclSpecs; struct Decl; struct TemplateHeadContext; struct ClassSpecifierContext; diff --git a/src/parser/cxx/symbol_instantiation.cc b/src/parser/cxx/symbol_instantiation.cc index 6639ecdf..16419b41 100644 --- a/src/parser/cxx/symbol_instantiation.cc +++ b/src/parser/cxx/symbol_instantiation.cc @@ -550,13 +550,13 @@ auto SymbolInstantiation::VisitType::operator()(const PointerType* type) auto SymbolInstantiation::VisitType::operator()(const LvalueReferenceType* type) -> const Type* { auto elementType = substitute(type->elementType()); - return self.control()->getLvalueReferenceType(elementType); + return self.control()->add_lvalue_reference(elementType); } auto SymbolInstantiation::VisitType::operator()(const RvalueReferenceType* type) -> const Type* { auto elementType = substitute(type->elementType()); - return self.control()->getRvalueReferenceType(elementType); + return self.control()->add_rvalue_reference(elementType); } auto SymbolInstantiation::VisitType::operator()(const FunctionType* type) diff --git a/src/parser/cxx/type_checker.cc b/src/parser/cxx/type_checker.cc index 6d587bfb..7d818329 100644 --- a/src/parser/cxx/type_checker.cc +++ b/src/parser/cxx/type_checker.cc @@ -575,7 +575,7 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) { if (!is_glvalue(ast->expression)) { error(ast->opLoc, std::format("cannot decrement an rvalue of type '{}'", to_string(ast->expression->type))); - break; + break; } auto ty = ast->expression->type; diff --git a/src/parser/cxx/types_fwd.h b/src/parser/cxx/types_fwd.h index 80743d9a..7edd5f13 100644 --- a/src/parser/cxx/types_fwd.h +++ b/src/parser/cxx/types_fwd.h @@ -23,6 +23,7 @@ #include #include +#include namespace cxx { @@ -84,12 +85,30 @@ enum class TypeKind { CXX_FOR_EACH_TYPE_KIND(PROCESS_TYPE) }; #undef PROCESS_TYPE enum class CvQualifiers { - kNone, - kConst, - kVolatile, - kConstVolatile, + kNone = 0, + kConst = 1, + kVolatile = 2, + kConstVolatile = kConst | kVolatile, }; +[[nodiscard]] inline auto operator|(CvQualifiers a, CvQualifiers b) + -> CvQualifiers { + return CvQualifiers(std::to_underlying(a) | std::to_underlying(b)); +} + +[[nodiscard]] inline auto operator&(CvQualifiers a, CvQualifiers b) + -> CvQualifiers { + return CvQualifiers(std::to_underlying(a) & std::to_underlying(b)); +} + +[[nodiscard]] inline auto is_const(CvQualifiers cv) -> bool { + return (cv & CvQualifiers::kConst) != CvQualifiers::kNone; +} + +[[nodiscard]] inline auto is_volatile(CvQualifiers cv) -> bool { + return (cv & CvQualifiers::kVolatile) != CvQualifiers::kNone; +} + enum class RefQualifier { kNone, kLvalue,