diff --git a/packages/cxx-frontend/src/AST.ts b/packages/cxx-frontend/src/AST.ts index f87f688e..6df0e600 100644 --- a/packages/cxx-frontend/src/AST.ts +++ b/packages/cxx-frontend/src/AST.ts @@ -7667,25 +7667,39 @@ export class BaseSpecifierAST extends AST { ); } + /** + * Returns the location of the ellipsis token in this node + */ + getEllipsisToken(): Token | undefined { + return Token.from(cxx.getASTSlot(this.getHandle(), 6), this.parser); + } + /** * Returns the isTemplateIntroduced attribute of this node */ getIsTemplateIntroduced(): boolean { - return cxx.getASTSlot(this.getHandle(), 6) !== 0; + return cxx.getASTSlot(this.getHandle(), 7) !== 0; } /** * Returns the isVirtual attribute of this node */ getIsVirtual(): boolean { - return cxx.getASTSlot(this.getHandle(), 7) !== 0; + return cxx.getASTSlot(this.getHandle(), 8) !== 0; + } + + /** + * Returns the isVariadic attribute of this node + */ + getIsVariadic(): boolean { + return cxx.getASTSlot(this.getHandle(), 9) !== 0; } /** * Returns the accessSpecifier attribute of this node */ getAccessSpecifier(): TokenKind { - return cxx.getASTSlot(this.getHandle(), 8); + return cxx.getASTSlot(this.getHandle(), 10); } } diff --git a/packages/cxx-gen-ast/src/gen.ts b/packages/cxx-gen-ast/src/gen.ts index 10e52619..5884e168 100644 --- a/packages/cxx-gen-ast/src/gen.ts +++ b/packages/cxx-gen-ast/src/gen.ts @@ -31,6 +31,7 @@ import { gen_ast_slot_cc } from "./gen_ast_slot_cc.js"; import { gen_ast_slot_h } from "./get_ast_slot_h.js"; import { gen_ast_ts } from "./gen_ast_ts.js"; import { gen_ast_visitor_h } from "./gen_ast_visitor_h.js"; +import { gen_ast_visitor_cc } from "./gen_ast_visitor_cc.js"; import { gen_ast_visitor_ts } from "./gen_ast_visitor_ts.js"; import { parseAST } from "./parseAST.js"; import { gen_ast_kind_ts } from "./gen_ast_kind_ts.js"; @@ -67,6 +68,10 @@ gen_ast_visitor_h({ ast, output: path.join(outdir, "src/parser/cxx/ast_visitor.h"), }); +gen_ast_visitor_cc({ + ast, + output: path.join(outdir, "src/parser/cxx/ast_visitor.cc"), +}); gen_ast_printer_h({ ast, output: path.join(outdir, "src/parser/cxx/ast_printer.h"), diff --git a/packages/cxx-gen-ast/src/gen_ast_visitor_cc.ts b/packages/cxx-gen-ast/src/gen_ast_visitor_cc.ts new file mode 100644 index 00000000..28949dd8 --- /dev/null +++ b/packages/cxx-gen-ast/src/gen_ast_visitor_cc.ts @@ -0,0 +1,91 @@ +// Copyright (c) 2024 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. + +import { groupNodesByBaseType } from "./groupNodesByBaseType.js"; +import { AST, getASTNodes } from "./parseAST.js"; +import { cpy_header } from "./cpy_header.js"; +import * as fs from "fs"; + +export function gen_ast_visitor_cc({ + ast, + output, +}: { + ast: AST; + output: string; +}) { + const code: string[] = []; + const emit = (line = "") => code.push(line); + + const by_base = groupNodesByBaseType(ast); + + const types = new Set(); + + ast.nodes.forEach((node) => { + node.members.forEach((m) => { + if (m.kind === "node" || m.kind === "node-list") types.add(m.type); + }); + }); + + by_base.forEach((nodes) => { + nodes.forEach(({ name, members }) => { + members = getASTNodes(members); + + emit(); + emit(`void ASTVisitor::visit(${name}* ast) {`); + members.forEach((m) => { + if (m.kind === "node") { + emit(`accept(ast->${m.name});`); + } else if (m.kind === "node-list") { + emit(`for (auto node : ListView{ast->${m.name}}) {`); + emit(`accept(node);`); + emit(`}`); + } + }); + emit(`}`); + }); + }); + + const out = `${cpy_header} +#include + +// cxx +#include + +namespace cxx { + +auto ASTVisitor::preVisit(AST*) -> bool { + return true; +} + +void ASTVisitor::postVisit(AST*) {} + +void ASTVisitor::accept(AST* ast) { + if (!ast) return; + if (preVisit(ast)) ast->accept(this); + postVisit(ast); +} + +${code.join("\n")} + +} // namespace cxx +`; + + fs.writeFileSync(output, out); +} diff --git a/packages/cxx-gen-ast/src/gen_ast_visitor_h.ts b/packages/cxx-gen-ast/src/gen_ast_visitor_h.ts index 0d5512dc..d31450e1 100644 --- a/packages/cxx-gen-ast/src/gen_ast_visitor_h.ts +++ b/packages/cxx-gen-ast/src/gen_ast_visitor_h.ts @@ -40,7 +40,7 @@ export function gen_ast_visitor_h({ emit(); emit(` // ${base}`); nodes.forEach(({ name }) => { - emit(` virtual void visit(${name}* ast) = 0;`); + emit(` virtual void visit(${name}* ast);`); }); }); @@ -55,6 +55,12 @@ namespace cxx { class ASTVisitor { public: virtual ~ASTVisitor() = default; + + void accept(AST* ast); + + [[nodiscard]] virtual bool preVisit(AST* ast); + virtual void postVisit(AST* ast); + ${code.join("\n")} }; 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 a34a76a8..27fad0ca 100644 --- a/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts +++ b/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts @@ -62,17 +62,20 @@ export function new_ast_rewriter_cc({ emit(` struct ASTRewriter::${className}Visitor {`); emit(` ASTRewriter& rewrite;`); emit( - `[[nodiscard]] auto translationUnit() const -> TranslationUnit* { return rewrite.unit_; }`, + `[[nodiscard]] auto translationUnit() const -> TranslationUnit* { return rewrite.unit_; }` ); emit(); emit( - `[[nodiscard]] auto control() const -> Control* { return rewrite.control(); }`, + `[[nodiscard]] auto control() const -> Control* { return rewrite.control(); }` ); emit( - `[[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); }`, + `[[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); }` ); emit( - `[[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; }`, + `[[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; }` + ); + emit( + `[[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; }` ); nodes.forEach(({ name }) => { emit(); @@ -81,16 +84,24 @@ export function new_ast_rewriter_cc({ emit(` };`); }); - const emitRewriterBody = (members: Member[], visitor: string = "rewrite") => { + const emitRewriterBody = ({ + name, + members, + visitor = "rewrite", + }: { + name: string; + members: Member[]; + visitor?: string; + }) => { const blockSymbol = members.find( - (m) => m.kind === "attribute" && m.type === "BlockSymbol", + (m) => m.kind === "attribute" && m.type === "BlockSymbol" ); if (blockSymbol) { - emit(`auto _ = Binder::ScopeGuard(&rewrite.binder_); + emit(`auto _ = Binder::ScopeGuard(binder()); if (ast->${blockSymbol.name}) { - copy->${blockSymbol.name} = rewrite.binder_.enterBlock(ast->${blockSymbol.name}->location()); + copy->${blockSymbol.name} = binder()->enterBlock(ast->${blockSymbol.name}->location()); } `); } @@ -114,11 +125,14 @@ export function new_ast_rewriter_cc({ if (specsAttr) { emit(); emit( - `auto ${m.name}Type = getDeclaratorType(translationUnit(), copy->${m.name}, ${specsAttr}Ctx.getType());`, + `auto ${m.name}Decl = Decl{${specsAttr}Ctx, copy->${m.name}};` + ); + emit( + `auto ${m.name}Type = getDeclaratorType(translationUnit(), copy->${m.name}, ${specsAttr}Ctx.getType());` ); typeAttr = members.find( - (m) => m.kind === "attribute" && m.name === "type", + (m) => m.kind === "attribute" && m.name === "type" ); if (typeAttr) { @@ -131,7 +145,7 @@ export function new_ast_rewriter_cc({ } // switch } else { emit( - `copy->${m.name} = ast_cast<${m.type}>(${visitor}(ast->${m.name}));`, + `copy->${m.name} = ast_cast<${m.type}>(${visitor}(ast->${m.name}));` ); } break; @@ -150,7 +164,7 @@ export function new_ast_rewriter_cc({ } // switch emit( - `for (auto ${m.name} = ©->${m.name}; auto node : ListView{ast->${m.name}}) {`, + `for (auto ${m.name} = ©->${m.name}; auto node : ListView{ast->${m.name}}) {` ); switch (m.type) { @@ -167,7 +181,7 @@ export function new_ast_rewriter_cc({ emit(`*${m.name} = make_list_node(arena(), value);`); } else { emit( - `*${m.name} = make_list_node(arena(), ast_cast<${m.type}>(value));`, + `*${m.name} = make_list_node(arena(), ast_cast<${m.type}>(value));` ); } emit(`${m.name} = &(*${m.name})->next;`); @@ -188,6 +202,39 @@ export function new_ast_rewriter_cc({ } case "attribute": { emit(` copy->${m.name} = ast->${m.name};`); + + if (m.name == "symbol" && name == "NamedTypeSpecifierAST") { + emit(` + if (auto typeParameter = symbol_cast(copy->symbol)) { + const auto& args = rewrite.templateArguments_; + if (typeParameter && typeParameter->depth() == 0 && + typeParameter->index() < args.size()) { + auto index = typeParameter->index(); + + if (auto sym = std::get_if(&args[index])) { + copy->symbol = *sym; + } + } + } +`); + } + + if (m.name == "symbol" && name == "IdExpressionAST") { + emit(` + if (auto param = symbol_cast(copy->symbol); + param && param->depth() == 0 && + param->index() < rewrite.templateArguments_.size()) { + auto symbolPtr = + std::get_if(&rewrite.templateArguments_[param->index()]); + + if (!symbolPtr) { + cxx_runtime_error("expected initializer for non-type template parameter"); + } + + copy->symbol = *symbolPtr; + copy->type = copy->symbol->type(); + }`); + } break; } case "token": { @@ -234,7 +281,7 @@ export function new_ast_rewriter_cc({ switch (name) { case "InitDeclaratorAST": emit( - `auto ASTRewriter::operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}* {`, + `auto ASTRewriter::operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}* {` ); break; default: @@ -246,7 +293,7 @@ export function new_ast_rewriter_cc({ emit(); emit(` auto copy = make_node<${name}>(arena());`); emit(); - emitRewriterBody(members, "operator()"); + emitRewriterBody({ name, members, visitor: "operator()" }); emit(); emit(` return copy;`); emit(`}`); @@ -259,38 +306,79 @@ export function new_ast_rewriter_cc({ nodes.forEach(({ name, members }) => { emit(); emit( - `auto ASTRewriter::${className}Visitor::operator()(${name}* ast) -> ${base}* {`, + `auto ASTRewriter::${className}Visitor::operator()(${name}* ast) -> ${base}* {` ); + if (name === "IdExpressionAST") { emit(` -if (auto x = symbol_cast(ast->symbol); - x && x->depth() == 0 && x->index() < rewrite.templateArguments_.size()) { - auto initializerPtr = - std::get_if(&rewrite.templateArguments_[x->index()]); - if (!initializerPtr) { +if (auto param = symbol_cast(ast->symbol); + param && param->depth() == 0 && + param->index() < rewrite.templateArguments_.size()) { + auto symbolPtr = + std::get_if(&rewrite.templateArguments_[param->index()]); + + if (!symbolPtr) { cxx_runtime_error("expected initializer for non-type template parameter"); } - auto initializer = rewrite(*initializerPtr); + auto parameterPack = symbol_cast(*symbolPtr); - if (auto eq = ast_cast(initializer)) { - return eq->expression; + if (parameterPack && parameterPack == rewrite.parameterPack_ && + rewrite.elementIndex_.has_value()) { + auto idx = rewrite.elementIndex_.value(); + auto element = parameterPack->elements()[idx]; + if (auto var = symbol_cast(element)) { + return rewrite(var->initializer()); + } } +} +`); + } + if (name === "LeftFoldExpressionAST") { + emit(` + if (auto parameterPack = rewrite.getParameterPack(ast->expression)) { + auto savedParameterPack = rewrite.parameterPack_; + std::swap(rewrite.parameterPack_, parameterPack); + + std::vector instantiations; + ExpressionAST* current = nullptr; + + int n = 0; + for (auto element : rewrite.parameterPack_->elements()) { + std::optional index{n}; + std::swap(rewrite.elementIndex_, index); + + auto expression = rewrite(ast->expression); + if (!current) { + current = expression; + } else { + auto binop = make_node(arena()); + binop->valueCategory = current->valueCategory; + binop->type = current->type; + binop->leftExpression = current; + binop->op = ast->op; + binop->opLoc = ast->opLoc; + binop->rightExpression = expression; + current = binop; + } - if (auto bracedInit = ast_cast(initializer)) { - if (bracedInit->expressionList && !bracedInit->expressionList->next) { - return bracedInit->expressionList->value; + std::swap(rewrite.elementIndex_, index); + ++n; } + + std::swap(rewrite.parameterPack_, parameterPack); + + return current; } -} `); } + emit(` auto copy = make_node<${name}>(arena());`); emit(); ast.baseMembers.get(base)?.forEach((m) => { emit(` copy->${m.name} = ast->${m.name};`); }); - emitRewriterBody(members, "rewrite"); + emitRewriterBody({ name, members, visitor: "rewrite" }); emit(); emit(` return copy;`); emit(`}`); @@ -311,6 +399,9 @@ if (auto x = symbol_cast(ast->symbol); #include #include #include +#include + +#include namespace cxx { @@ -339,6 +430,29 @@ void ASTRewriter::setRestrictedToDeclarations(bool restrictedToDeclarations) { restrictedToDeclarations_ = restrictedToDeclarations; } +auto ASTRewriter::getParameterPack(ExpressionAST* ast) -> ParameterPackSymbol* { + for (auto cursor = ASTCursor{ast, {}}; cursor; ++cursor) { + const auto& current = *cursor; + if (!std::holds_alternative(current.node)) continue; + + auto id = ast_cast(std::get(current.node)); + if (!id) continue; + + auto param = symbol_cast(id->symbol); + if (!param) continue; + + if (param->depth() != 0) continue; + + auto arg = templateArguments_[param->index()]; + auto argSymbol = std::get(arg); + + auto parameterPack = symbol_cast(argSymbol); + if (parameterPack) return parameterPack; + } + + return nullptr; +} + ${code.join("\n")} } // namespace cxx diff --git a/packages/cxx-gen-ast/src/new_ast_rewriter_h.ts b/packages/cxx-gen-ast/src/new_ast_rewriter_h.ts index 73ad22e0..78accee9 100644 --- a/packages/cxx-gen-ast/src/new_ast_rewriter_h.ts +++ b/packages/cxx-gen-ast/src/new_ast_rewriter_h.ts @@ -54,7 +54,7 @@ export function new_ast_rewriter_h({ switch (name) { case "InitDeclaratorAST": emit( - ` [[nodiscard]] auto operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}*;`, + ` [[nodiscard]] auto operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}*;` ); break; default: @@ -117,8 +117,12 @@ ${code.join("\n")} private: [[nodiscard]] auto rewriter() -> ASTRewriter* { return this; } + [[nodiscard]] auto getParameterPack(ExpressionAST* ast) -> ParameterPackSymbol*; + TypeChecker* typeChecker_ = nullptr; const std::vector& templateArguments_; + ParameterPackSymbol* parameterPack_ = nullptr; + std::optional elementIndex_; TranslationUnit* unit_ = nullptr; Binder binder_; bool restrictedToDeclarations_ = false; diff --git a/src/frontend/cxx/frontend.cc b/src/frontend/cxx/frontend.cc index e2e941b6..3565f261 100644 --- a/src/frontend/cxx/frontend.cc +++ b/src/frontend/cxx/frontend.cc @@ -19,7 +19,6 @@ // SOFTWARE. #include -#include #include #include #include @@ -56,43 +55,48 @@ namespace { using namespace cxx; -struct CheckExpressionTypes { +class CheckExpressionTypes final : private ASTVisitor { + public: [[nodiscard]] auto operator()(TranslationUnit* unit) { std::size_t missingTypes = 0; + std::swap(unit_, unit); + std::swap(missingTypes_, missingTypes); - // iterate over all expressions and check if they have a type - for (auto cursor = ASTCursor{unit->ast(), "unit"}; cursor; - cursor = ++cursor) { - const auto& current = *cursor; + accept(unit_->ast()); - if (!std::holds_alternative(current.node)) { - // skip non-AST nodes - continue; - } + std::swap(unit_, unit); + std::swap(missingTypes_, missingTypes); - auto ast = std::get(current.node); - auto expression = ast_cast(ast); - if (!expression) { - // skip non-expression nodes - continue; - } + return missingTypes == 0; + } - auto type = expression->type; - if (type) { - // the expression has a type - continue; - } + private: + using ASTVisitor::visit; - const auto loc = expression->firstSourceLocation(); + auto preVisit(AST* ast) -> bool override { + if (ast_cast(ast)) { + // skip template declarations, as they are not instantiated yet + return false; + } + + if (auto expression = ast_cast(ast)) { + if (!expression->type) { + const auto loc = expression->firstSourceLocation(); - unit->warning(loc, std::format("untyped expression of kind '{}'", - to_string(expression->kind()))); + unit_->warning(loc, std::format("untyped expression of kind '{}'", + to_string(expression->kind()))); - ++missingTypes; + ++missingTypes_; + return false; + } } - return missingTypes == 0; + return true; // visit children } + + private: + TranslationUnit* unit_ = nullptr; + std::size_t missingTypes_ = 0; }; auto readAll(const std::string& fileName, std::istream& in) diff --git a/src/parser/CMakeLists.txt b/src/parser/CMakeLists.txt index 9ea5d243..01b7e6d5 100644 --- a/src/parser/CMakeLists.txt +++ b/src/parser/CMakeLists.txt @@ -27,6 +27,7 @@ add_library(cxx-parser cxx/ast_printer.cc cxx/ast_rewriter.cc cxx/ast_slot.cc + cxx/ast_visitor.cc cxx/ast.cc cxx/base_classes.cc cxx/binder.cc diff --git a/src/parser/cxx/ast.cc b/src/parser/cxx/ast.cc index 18baca0e..c631a7b6 100644 --- a/src/parser/cxx/ast.cc +++ b/src/parser/cxx/ast.cc @@ -1979,10 +1979,12 @@ auto BaseSpecifierAST::firstSourceLocation() -> SourceLocation { if (auto loc = cxx::firstSourceLocation(nestedNameSpecifier)) return loc; if (auto loc = cxx::firstSourceLocation(templateLoc)) return loc; if (auto loc = cxx::firstSourceLocation(unqualifiedId)) return loc; + if (auto loc = cxx::firstSourceLocation(ellipsisLoc)) return loc; return {}; } auto BaseSpecifierAST::lastSourceLocation() -> SourceLocation { + if (auto loc = cxx::lastSourceLocation(ellipsisLoc)) return loc; if (auto loc = cxx::lastSourceLocation(unqualifiedId)) return loc; if (auto loc = cxx::lastSourceLocation(templateLoc)) return loc; if (auto loc = cxx::lastSourceLocation(nestedNameSpecifier)) return loc; diff --git a/src/parser/cxx/ast.fbs b/src/parser/cxx/ast.fbs index 314a4525..ab21724e 100644 --- a/src/parser/cxx/ast.fbs +++ b/src/parser/cxx/ast.fbs @@ -422,6 +422,7 @@ table BaseSpecifier /* AST */ { virtual_or_access_loc: uint32; other_virtual_or_access_loc: uint32; template_loc: uint32; + ellipsis_loc: uint32; } table RequiresClause /* AST */ { diff --git a/src/parser/cxx/ast.h b/src/parser/cxx/ast.h index f6481364..de2e048e 100644 --- a/src/parser/cxx/ast.h +++ b/src/parser/cxx/ast.h @@ -2429,8 +2429,10 @@ class BaseSpecifierAST final : public AST { NestedNameSpecifierAST* nestedNameSpecifier = nullptr; SourceLocation templateLoc; UnqualifiedIdAST* unqualifiedId = nullptr; + SourceLocation ellipsisLoc; bool isTemplateIntroduced = false; bool isVirtual = false; + bool isVariadic = false; TokenKind accessSpecifier = TokenKind::T_EOF_SYMBOL; BaseClassSymbol* symbol = nullptr; diff --git a/src/parser/cxx/ast_pretty_printer.cc b/src/parser/cxx/ast_pretty_printer.cc index bf916152..513bf806 100644 --- a/src/parser/cxx/ast_pretty_printer.cc +++ b/src/parser/cxx/ast_pretty_printer.cc @@ -1044,6 +1044,9 @@ void ASTPrettyPrinter::operator()(BaseSpecifierAST* ast) { writeToken(ast->templateLoc); } operator()(ast->unqualifiedId); + if (ast->ellipsisLoc) { + writeToken(ast->ellipsisLoc); + } } void ASTPrettyPrinter::operator()(RequiresClauseAST* ast) { diff --git a/src/parser/cxx/ast_printer.cc b/src/parser/cxx/ast_printer.cc index 5d4eccd0..897bb5de 100644 --- a/src/parser/cxx/ast_printer.cc +++ b/src/parser/cxx/ast_printer.cc @@ -1729,6 +1729,12 @@ void ASTPrinter::visit(BaseSpecifierAST* ast) { out_ << std::format("is-virtual: {}\n", ast->isVirtual); --indent_; } + if (ast->isVariadic) { + ++indent_; + out_ << std::format("{:{}}", "", indent_ * 2); + out_ << std::format("is-variadic: {}\n", ast->isVariadic); + --indent_; + } if (ast->accessSpecifier != TokenKind::T_EOF_SYMBOL) { ++indent_; out_ << std::format("{:{}}", "", indent_ * 2); diff --git a/src/parser/cxx/ast_rewriter.cc b/src/parser/cxx/ast_rewriter.cc index 4af2a5ad..3c84cd03 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -22,15 +22,19 @@ // cxx #include +#include #include #include #include #include +#include #include #include #include #include +#include + namespace cxx { ASTRewriter::ASTRewriter(TypeChecker* typeChcker, @@ -54,6 +58,29 @@ void ASTRewriter::setRestrictedToDeclarations(bool restrictedToDeclarations) { restrictedToDeclarations_ = restrictedToDeclarations; } +auto ASTRewriter::getParameterPack(ExpressionAST* ast) -> ParameterPackSymbol* { + for (auto cursor = ASTCursor{ast, {}}; cursor; ++cursor) { + const auto& current = *cursor; + if (!std::holds_alternative(current.node)) continue; + + auto id = ast_cast(std::get(current.node)); + if (!id) continue; + + auto param = symbol_cast(id->symbol); + if (!param) continue; + + if (param->depth() != 0) continue; + + auto arg = templateArguments_[param->index()]; + auto argSymbol = std::get(arg); + + auto parameterPack = symbol_cast(argSymbol); + if (parameterPack) return parameterPack; + } + + return nullptr; +} + struct ASTRewriter::UnitVisitor { ASTRewriter& rewrite; [[nodiscard]] auto translationUnit() const -> TranslationUnit* { @@ -63,6 +90,7 @@ struct ASTRewriter::UnitVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(TranslationUnitAST* ast) -> UnitAST*; @@ -78,6 +106,7 @@ struct ASTRewriter::DeclarationVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(SimpleDeclarationAST* ast) -> DeclarationAST*; @@ -158,6 +187,7 @@ struct ASTRewriter::StatementVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(LabeledStatementAST* ast) -> StatementAST*; @@ -208,6 +238,7 @@ struct ASTRewriter::ExpressionVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(GeneratedLiteralExpressionAST* ast) -> ExpressionAST*; @@ -358,6 +389,7 @@ struct ASTRewriter::TemplateParameterVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(TemplateTypeParameterAST* ast) -> TemplateParameterAST*; @@ -381,6 +413,7 @@ struct ASTRewriter::SpecifierVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(GeneratedTypeSpecifierAST* ast) -> SpecifierAST*; @@ -469,6 +502,7 @@ struct ASTRewriter::PtrOperatorVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(PointerOperatorAST* ast) -> PtrOperatorAST*; @@ -486,6 +520,7 @@ struct ASTRewriter::CoreDeclaratorVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(BitfieldDeclaratorAST* ast) -> CoreDeclaratorAST*; @@ -506,6 +541,7 @@ struct ASTRewriter::DeclaratorChunkVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(FunctionDeclaratorChunkAST* ast) -> DeclaratorChunkAST*; @@ -523,6 +559,7 @@ struct ASTRewriter::UnqualifiedIdVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(NameIdAST* ast) -> UnqualifiedIdAST*; @@ -556,6 +593,7 @@ struct ASTRewriter::NestedNameSpecifierVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(GlobalNestedNameSpecifierAST* ast) -> NestedNameSpecifierAST*; @@ -579,6 +617,7 @@ struct ASTRewriter::FunctionBodyVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(DefaultFunctionBodyAST* ast) -> FunctionBodyAST*; @@ -601,6 +640,7 @@ struct ASTRewriter::TemplateArgumentVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(TypeTemplateArgumentAST* ast) -> TemplateArgumentAST*; @@ -618,6 +658,7 @@ struct ASTRewriter::ExceptionSpecifierVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(ThrowExceptionSpecifierAST* ast) -> ExceptionSpecifierAST*; @@ -635,6 +676,7 @@ struct ASTRewriter::RequirementVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(SimpleRequirementAST* ast) -> RequirementAST*; @@ -654,6 +696,7 @@ struct ASTRewriter::NewInitializerVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(NewParenInitializerAST* ast) -> NewInitializerAST*; @@ -671,6 +714,7 @@ struct ASTRewriter::MemInitializerVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(ParenMemInitializerAST* ast) -> MemInitializerAST*; @@ -688,6 +732,7 @@ struct ASTRewriter::LambdaCaptureVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(ThisLambdaCaptureAST* ast) -> LambdaCaptureAST*; @@ -714,6 +759,7 @@ struct ASTRewriter::ExceptionDeclarationVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(EllipsisExceptionDeclarationAST* ast) -> ExceptionDeclarationAST*; @@ -731,6 +777,7 @@ struct ASTRewriter::AttributeSpecifierVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(CxxAttributeAST* ast) -> AttributeSpecifierAST*; @@ -754,6 +801,7 @@ struct ASTRewriter::AttributeTokenVisitor { [[nodiscard]] auto control() const -> Control* { return rewrite.control(); } [[nodiscard]] auto arena() const -> Arena* { return rewrite.arena(); } [[nodiscard]] auto rewriter() const -> ASTRewriter* { return &rewrite; } + [[nodiscard]] auto binder() const -> Binder* { return &rewrite.binder_; } [[nodiscard]] auto operator()(ScopedAttributeTokenAST* ast) -> AttributeTokenAST*; @@ -1008,9 +1056,24 @@ auto ASTRewriter::operator()(InitDeclaratorAST* ast, const DeclSpecs& declSpecs) auto copy = make_node(arena()); copy->declarator = operator()(ast->declarator); + + auto decl = Decl{declSpecs, copy->declarator}; + + auto type = getDeclaratorType(translationUnit(), copy->declarator, + declSpecs.getType()); + + // ### fix scope + if (binder_.scope() && binder_.scope()->isClassScope()) { + auto symbol = binder_.declareMemberSymbol(ast->declarator, decl); + copy->symbol = symbol; + } else { + // ### TODO + copy->symbol = ast->symbol; + } + copy->requiresClause = operator()(ast->requiresClause); copy->initializer = operator()(ast->initializer); - copy->symbol = ast->symbol; + // copy->symbol = ast->symbol; // TODO remove, done above return copy; } @@ -1092,6 +1155,7 @@ auto ASTRewriter::operator()(TypeIdAST* ast) -> TypeIdAST* { copy->declarator = operator()(ast->declarator); + auto declaratorDecl = Decl{typeSpecifierListCtx, copy->declarator}; auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, typeSpecifierListCtx.getType()); copy->type = declaratorType; @@ -1135,6 +1199,8 @@ auto ASTRewriter::operator()(BaseSpecifierAST* ast) -> BaseSpecifierAST* { copy->accessSpecifier = ast->accessSpecifier; copy->symbol = ast->symbol; + binder_.bind(ast); + return copy; } @@ -1576,6 +1642,7 @@ auto ASTRewriter::DeclarationVisitor::operator()(FunctionDefinitionAST* ast) copy->declarator = rewrite(ast->declarator); + auto declaratorDecl = Decl{declSpecifierListCtx, copy->declarator}; auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, declSpecifierListCtx.getType()); copy->requiresClause = rewrite(ast->requiresClause); @@ -1814,6 +1881,7 @@ auto ASTRewriter::DeclarationVisitor::operator()(ParameterDeclarationAST* ast) copy->declarator = rewrite(ast->declarator); + auto declaratorDecl = Decl{typeSpecifierListCtx, copy->declarator}; auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, typeSpecifierListCtx.getType()); copy->type = declaratorType; @@ -1974,10 +2042,10 @@ auto ASTRewriter::StatementVisitor::operator()(CompoundStatementAST* ast) -> StatementAST* { auto copy = make_node(arena()); - auto _ = Binder::ScopeGuard(&rewrite.binder_); + auto _ = Binder::ScopeGuard(binder()); if (ast->symbol) { - copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); + copy->symbol = binder()->enterBlock(ast->symbol->location()); } copy->lbraceLoc = ast->lbraceLoc; @@ -1998,10 +2066,10 @@ auto ASTRewriter::StatementVisitor::operator()(IfStatementAST* ast) -> StatementAST* { auto copy = make_node(arena()); - auto _ = Binder::ScopeGuard(&rewrite.binder_); + auto _ = Binder::ScopeGuard(binder()); if (ast->symbol) { - copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); + copy->symbol = binder()->enterBlock(ast->symbol->location()); } copy->ifLoc = ast->ifLoc; @@ -2036,10 +2104,10 @@ auto ASTRewriter::StatementVisitor::operator()(SwitchStatementAST* ast) -> StatementAST* { auto copy = make_node(arena()); - auto _ = Binder::ScopeGuard(&rewrite.binder_); + auto _ = Binder::ScopeGuard(binder()); if (ast->symbol) { - copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); + copy->symbol = binder()->enterBlock(ast->symbol->location()); } copy->switchLoc = ast->switchLoc; @@ -2056,10 +2124,10 @@ auto ASTRewriter::StatementVisitor::operator()(WhileStatementAST* ast) -> StatementAST* { auto copy = make_node(arena()); - auto _ = Binder::ScopeGuard(&rewrite.binder_); + auto _ = Binder::ScopeGuard(binder()); if (ast->symbol) { - copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); + copy->symbol = binder()->enterBlock(ast->symbol->location()); } copy->whileLoc = ast->whileLoc; @@ -2090,10 +2158,10 @@ auto ASTRewriter::StatementVisitor::operator()(ForRangeStatementAST* ast) -> StatementAST* { auto copy = make_node(arena()); - auto _ = Binder::ScopeGuard(&rewrite.binder_); + auto _ = Binder::ScopeGuard(binder()); if (ast->symbol) { - copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); + copy->symbol = binder()->enterBlock(ast->symbol->location()); } copy->forLoc = ast->forLoc; @@ -2112,10 +2180,10 @@ auto ASTRewriter::StatementVisitor::operator()(ForStatementAST* ast) -> StatementAST* { auto copy = make_node(arena()); - auto _ = Binder::ScopeGuard(&rewrite.binder_); + auto _ = Binder::ScopeGuard(binder()); if (ast->symbol) { - copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); + copy->symbol = binder()->enterBlock(ast->symbol->location()); } copy->forLoc = ast->forLoc; @@ -2345,6 +2413,28 @@ auto ASTRewriter::ExpressionVisitor::operator()(NestedExpressionAST* ast) auto ASTRewriter::ExpressionVisitor::operator()(IdExpressionAST* ast) -> ExpressionAST* { + if (auto param = symbol_cast(ast->symbol); + param && param->depth() == 0 && + param->index() < rewrite.templateArguments_.size()) { + auto symbolPtr = + std::get_if(&rewrite.templateArguments_[param->index()]); + + if (!symbolPtr) { + cxx_runtime_error("expected initializer for non-type template parameter"); + } + + auto parameterPack = symbol_cast(*symbolPtr); + + if (parameterPack && parameterPack == rewrite.parameterPack_ && + rewrite.elementIndex_.has_value()) { + auto idx = rewrite.elementIndex_.value(); + auto element = parameterPack->elements()[idx]; + if (auto var = symbol_cast(element)) { + return rewrite(var->initializer()); + } + } + } + auto copy = make_node(arena()); copy->valueCategory = ast->valueCategory; @@ -2352,21 +2442,21 @@ auto ASTRewriter::ExpressionVisitor::operator()(IdExpressionAST* ast) copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); copy->templateLoc = ast->templateLoc; copy->unqualifiedId = rewrite(ast->unqualifiedId); - copy->symbol = ast->symbol; - if (auto x = symbol_cast(copy->symbol); - x && x->depth() == 0 && x->index() < rewrite.templateArguments_.size()) { - auto initializerPtr = - std::get_if(&rewrite.templateArguments_[x->index()]); - if (!initializerPtr) { + if (auto param = symbol_cast(copy->symbol); + param && param->depth() == 0 && + param->index() < rewrite.templateArguments_.size()) { + auto symbolPtr = + std::get_if(&rewrite.templateArguments_[param->index()]); + + if (!symbolPtr) { cxx_runtime_error("expected initializer for non-type template parameter"); } - copy->symbol = *initializerPtr; + copy->symbol = *symbolPtr; copy->type = copy->symbol->type(); } - copy->isTemplateIntroduced = ast->isTemplateIntroduced; return copy; @@ -2473,6 +2563,41 @@ auto ASTRewriter::ExpressionVisitor::operator()(RightFoldExpressionAST* ast) auto ASTRewriter::ExpressionVisitor::operator()(LeftFoldExpressionAST* ast) -> ExpressionAST* { + if (auto parameterPack = rewrite.getParameterPack(ast->expression)) { + auto savedParameterPack = rewrite.parameterPack_; + std::swap(rewrite.parameterPack_, parameterPack); + + std::vector instantiations; + ExpressionAST* current = nullptr; + + int n = 0; + for (auto element : rewrite.parameterPack_->elements()) { + std::optional index{n}; + std::swap(rewrite.elementIndex_, index); + + auto expression = rewrite(ast->expression); + if (!current) { + current = expression; + } else { + auto binop = make_node(arena()); + binop->valueCategory = current->valueCategory; + binop->type = current->type; + binop->leftExpression = current; + binop->op = ast->op; + binop->opLoc = ast->opLoc; + binop->rightExpression = expression; + current = binop; + } + + std::swap(rewrite.elementIndex_, index); + ++n; + } + + std::swap(rewrite.parameterPack_, parameterPack); + + return current; + } + auto copy = make_node(arena()); copy->valueCategory = ast->valueCategory; @@ -2912,6 +3037,7 @@ auto ASTRewriter::ExpressionVisitor::operator()(NewExpressionAST* ast) copy->declarator = rewrite(ast->declarator); + auto declaratorDecl = Decl{typeSpecifierListCtx, copy->declarator}; auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, typeSpecifierListCtx.getType()); copy->rparenLoc = ast->rparenLoc; @@ -3101,6 +3227,7 @@ auto ASTRewriter::ExpressionVisitor::operator()(ConditionExpressionAST* ast) copy->declarator = rewrite(ast->declarator); + auto declaratorDecl = Decl{declSpecifierListCtx, copy->declarator}; auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, declSpecifierListCtx.getType()); copy->initializer = rewrite(ast->initializer); @@ -3609,7 +3736,6 @@ auto ASTRewriter::SpecifierVisitor::operator()(EnumSpecifierAST* ast) } copy->lbraceLoc = ast->lbraceLoc; - copy->commaLoc = ast->commaLoc; for (auto enumeratorList = ©->enumeratorList; auto node : ListView{ast->enumeratorList}) { @@ -3618,6 +3744,7 @@ auto ASTRewriter::SpecifierVisitor::operator()(EnumSpecifierAST* ast) enumeratorList = &(*enumeratorList)->next; } + copy->commaLoc = ast->commaLoc; copy->rbraceLoc = ast->rbraceLoc; copy->symbol = ast->symbol; @@ -3642,11 +3769,27 @@ auto ASTRewriter::SpecifierVisitor::operator()(ClassSpecifierAST* ast) copy->finalLoc = ast->finalLoc; copy->colonLoc = ast->colonLoc; + // ### TODO: use Binder::bind() + auto _ = Binder::ScopeGuard{binder()}; + auto location = ast->symbol->location(); + auto className = ast->symbol->name(); + auto classSymbol = control()->newClassSymbol(binder()->scope(), location); + classSymbol->setName(className); + classSymbol->setIsUnion(ast->symbol->isUnion()); + classSymbol->setFinal(ast->isFinal); + binder()->setScope(classSymbol); + + copy->symbol = classSymbol; + for (auto baseSpecifierList = ©->baseSpecifierList; auto node : ListView{ast->baseSpecifierList}) { auto value = rewrite(node); *baseSpecifierList = make_list_node(arena(), value); baseSpecifierList = &(*baseSpecifierList)->next; + + if (value->symbol) { + classSymbol->addBaseClass(value->symbol); + } } copy->lbraceLoc = ast->lbraceLoc; @@ -3660,9 +3803,11 @@ auto ASTRewriter::SpecifierVisitor::operator()(ClassSpecifierAST* ast) copy->rbraceLoc = ast->rbraceLoc; copy->classKey = ast->classKey; - copy->symbol = ast->symbol; + // copy->symbol = ast->symbol; // TODO: remove done by the binder copy->isFinal = ast->isFinal; + binder()->complete(copy); + return copy; } @@ -3672,7 +3817,9 @@ auto ASTRewriter::SpecifierVisitor::operator()(TypenameSpecifierAST* ast) copy->typenameLoc = ast->typenameLoc; copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); + copy->templateLoc = ast->templateLoc; copy->unqualifiedId = rewrite(ast->unqualifiedId); + copy->isTemplateIntroduced = ast->isTemplateIntroduced; return copy; } @@ -4175,8 +4322,10 @@ auto ASTRewriter::RequirementVisitor::operator()(TypeRequirementAST* ast) copy->typenameLoc = ast->typenameLoc; copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); + copy->templateLoc = ast->templateLoc; copy->unqualifiedId = rewrite(ast->unqualifiedId); copy->semicolonLoc = ast->semicolonLoc; + copy->isTemplateIntroduced = ast->isTemplateIntroduced; return copy; } @@ -4352,6 +4501,7 @@ auto ASTRewriter::ExceptionDeclarationVisitor::operator()( copy->declarator = rewrite(ast->declarator); + auto declaratorDecl = Decl{typeSpecifierListCtx, copy->declarator}; auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, typeSpecifierListCtx.getType()); diff --git a/src/parser/cxx/ast_rewriter.h b/src/parser/cxx/ast_rewriter.h index dcde5380..0bf1d4cd 100644 --- a/src/parser/cxx/ast_rewriter.h +++ b/src/parser/cxx/ast_rewriter.h @@ -151,8 +151,13 @@ class ASTRewriter { private: [[nodiscard]] auto rewriter() -> ASTRewriter* { return this; } + [[nodiscard]] auto getParameterPack(ExpressionAST* ast) + -> ParameterPackSymbol*; + TypeChecker* typeChecker_ = nullptr; const std::vector& templateArguments_; + ParameterPackSymbol* parameterPack_ = nullptr; + std::optional elementIndex_; TranslationUnit* unit_ = nullptr; Binder binder_; bool restrictedToDeclarations_ = false; diff --git a/src/parser/cxx/ast_slot.cc b/src/parser/cxx/ast_slot.cc index 2a256e7d..0cfb50c0 100644 --- a/src/parser/cxx/ast_slot.cc +++ b/src/parser/cxx/ast_slot.cc @@ -3803,24 +3803,34 @@ void ASTSlot::visit(BaseSpecifierAST* ast) { slotKind_ = ASTSlotKind::kNode; slotNameIndex_ = SlotNameIndex{219}; break; - case 6: // isTemplateIntroduced + case 6: // ellipsisLoc + value_ = ast->ellipsisLoc.index(); + slotKind_ = ASTSlotKind::kToken; + slotNameIndex_ = SlotNameIndex{63}; + break; + case 7: // isTemplateIntroduced value_ = std::intptr_t(ast->isTemplateIntroduced != 0); slotKind_ = ASTSlotKind::kBoolAttribute; slotNameIndex_ = SlotNameIndex{115}; break; - case 7: // isVirtual + case 8: // isVirtual value_ = std::intptr_t(ast->isVirtual != 0); slotKind_ = ASTSlotKind::kBoolAttribute; slotNameIndex_ = SlotNameIndex{119}; break; - case 8: // accessSpecifier + case 9: // isVariadic + value_ = std::intptr_t(ast->isVariadic != 0); + slotKind_ = ASTSlotKind::kBoolAttribute; + slotNameIndex_ = SlotNameIndex{118}; + break; + case 10: // accessSpecifier value_ = std::intptr_t(ast->accessSpecifier); slotKind_ = ASTSlotKind::kIntAttribute; slotNameIndex_ = SlotNameIndex{2}; break; } // switch - slotCount_ = 9; + slotCount_ = 11; } void ASTSlot::visit(RequiresClauseAST* ast) { diff --git a/src/parser/cxx/ast_visitor.cc b/src/parser/cxx/ast_visitor.cc new file mode 100644 index 00000000..749e2ae7 --- /dev/null +++ b/src/parser/cxx/ast_visitor.cc @@ -0,0 +1,1034 @@ +// 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 + +namespace cxx { + +auto ASTVisitor::preVisit(AST*) -> bool { return true; } + +void ASTVisitor::postVisit(AST*) {} + +void ASTVisitor::accept(AST* ast) { + if (!ast) return; + if (preVisit(ast)) ast->accept(this); + postVisit(ast); +} + +void ASTVisitor::visit(TranslationUnitAST* ast) { + for (auto node : ListView{ast->declarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(ModuleUnitAST* ast) { + accept(ast->globalModuleFragment); + accept(ast->moduleDeclaration); + for (auto node : ListView{ast->declarationList}) { + accept(node); + } + accept(ast->privateModuleFragment); +} + +void ASTVisitor::visit(SimpleDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->declSpecifierList}) { + accept(node); + } + for (auto node : ListView{ast->initDeclaratorList}) { + accept(node); + } + accept(ast->requiresClause); +} + +void ASTVisitor::visit(AsmDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->asmQualifierList}) { + accept(node); + } + for (auto node : ListView{ast->outputOperandList}) { + accept(node); + } + for (auto node : ListView{ast->inputOperandList}) { + accept(node); + } + for (auto node : ListView{ast->clobberList}) { + accept(node); + } + for (auto node : ListView{ast->gotoLabelList}) { + accept(node); + } +} + +void ASTVisitor::visit(NamespaceAliasDefinitionAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(UsingDeclarationAST* ast) { + for (auto node : ListView{ast->usingDeclaratorList}) { + accept(node); + } +} + +void ASTVisitor::visit(UsingEnumDeclarationAST* ast) { + accept(ast->enumTypeSpecifier); +} + +void ASTVisitor::visit(UsingDirectiveAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(StaticAssertDeclarationAST* ast) { + accept(ast->expression); +} + +void ASTVisitor::visit(AliasDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->gnuAttributeList}) { + accept(node); + } + accept(ast->typeId); +} + +void ASTVisitor::visit(OpaqueEnumDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); + for (auto node : ListView{ast->typeSpecifierList}) { + accept(node); + } +} + +void ASTVisitor::visit(FunctionDefinitionAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->declSpecifierList}) { + accept(node); + } + accept(ast->declarator); + accept(ast->requiresClause); + accept(ast->functionBody); +} + +void ASTVisitor::visit(TemplateDeclarationAST* ast) { + for (auto node : ListView{ast->templateParameterList}) { + accept(node); + } + accept(ast->requiresClause); + accept(ast->declaration); +} + +void ASTVisitor::visit(ConceptDefinitionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(DeductionGuideAST* ast) { + accept(ast->explicitSpecifier); + accept(ast->parameterDeclarationClause); + accept(ast->templateId); +} + +void ASTVisitor::visit(ExplicitInstantiationAST* ast) { + accept(ast->declaration); +} + +void ASTVisitor::visit(ExportDeclarationAST* ast) { accept(ast->declaration); } + +void ASTVisitor::visit(ExportCompoundDeclarationAST* ast) { + for (auto node : ListView{ast->declarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(LinkageSpecificationAST* ast) { + for (auto node : ListView{ast->declarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(NamespaceDefinitionAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->nestedNamespaceSpecifierList}) { + accept(node); + } + for (auto node : ListView{ast->extraAttributeList}) { + accept(node); + } + for (auto node : ListView{ast->declarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(EmptyDeclarationAST* ast) {} + +void ASTVisitor::visit(AttributeDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } +} + +void ASTVisitor::visit(ModuleImportDeclarationAST* ast) { + accept(ast->importName); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } +} + +void ASTVisitor::visit(ParameterDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->typeSpecifierList}) { + accept(node); + } + accept(ast->declarator); + accept(ast->expression); +} + +void ASTVisitor::visit(AccessDeclarationAST* ast) {} + +void ASTVisitor::visit(ForRangeDeclarationAST* ast) {} + +void ASTVisitor::visit(StructuredBindingDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->declSpecifierList}) { + accept(node); + } + for (auto node : ListView{ast->bindingList}) { + accept(node); + } + accept(ast->initializer); +} + +void ASTVisitor::visit(AsmOperandAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(AsmQualifierAST* ast) {} + +void ASTVisitor::visit(AsmClobberAST* ast) {} + +void ASTVisitor::visit(AsmGotoLabelAST* ast) {} + +void ASTVisitor::visit(LabeledStatementAST* ast) {} + +void ASTVisitor::visit(CaseStatementAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(DefaultStatementAST* ast) {} + +void ASTVisitor::visit(ExpressionStatementAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(CompoundStatementAST* ast) { + for (auto node : ListView{ast->statementList}) { + accept(node); + } +} + +void ASTVisitor::visit(IfStatementAST* ast) { + accept(ast->initializer); + accept(ast->condition); + accept(ast->statement); + accept(ast->elseStatement); +} + +void ASTVisitor::visit(ConstevalIfStatementAST* ast) { + accept(ast->statement); + accept(ast->elseStatement); +} + +void ASTVisitor::visit(SwitchStatementAST* ast) { + accept(ast->initializer); + accept(ast->condition); + accept(ast->statement); +} + +void ASTVisitor::visit(WhileStatementAST* ast) { + accept(ast->condition); + accept(ast->statement); +} + +void ASTVisitor::visit(DoStatementAST* ast) { + accept(ast->statement); + accept(ast->expression); +} + +void ASTVisitor::visit(ForRangeStatementAST* ast) { + accept(ast->initializer); + accept(ast->rangeDeclaration); + accept(ast->rangeInitializer); + accept(ast->statement); +} + +void ASTVisitor::visit(ForStatementAST* ast) { + accept(ast->initializer); + accept(ast->condition); + accept(ast->expression); + accept(ast->statement); +} + +void ASTVisitor::visit(BreakStatementAST* ast) {} + +void ASTVisitor::visit(ContinueStatementAST* ast) {} + +void ASTVisitor::visit(ReturnStatementAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(CoroutineReturnStatementAST* ast) { + accept(ast->expression); +} + +void ASTVisitor::visit(GotoStatementAST* ast) {} + +void ASTVisitor::visit(DeclarationStatementAST* ast) { + accept(ast->declaration); +} + +void ASTVisitor::visit(TryBlockStatementAST* ast) { + accept(ast->statement); + for (auto node : ListView{ast->handlerList}) { + accept(node); + } +} + +void ASTVisitor::visit(GeneratedLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(CharLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(BoolLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(IntLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(FloatLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(NullptrLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(StringLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(UserDefinedStringLiteralExpressionAST* ast) {} + +void ASTVisitor::visit(ThisExpressionAST* ast) {} + +void ASTVisitor::visit(NestedStatementExpressionAST* ast) { + accept(ast->statement); +} + +void ASTVisitor::visit(NestedExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(IdExpressionAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(LambdaExpressionAST* ast) { + for (auto node : ListView{ast->captureList}) { + accept(node); + } + for (auto node : ListView{ast->templateParameterList}) { + accept(node); + } + accept(ast->templateRequiresClause); + accept(ast->parameterDeclarationClause); + for (auto node : ListView{ast->gnuAtributeList}) { + accept(node); + } + for (auto node : ListView{ast->lambdaSpecifierList}) { + accept(node); + } + accept(ast->exceptionSpecifier); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->trailingReturnType); + accept(ast->requiresClause); + accept(ast->statement); +} + +void ASTVisitor::visit(FoldExpressionAST* ast) { + accept(ast->leftExpression); + accept(ast->rightExpression); +} + +void ASTVisitor::visit(RightFoldExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(LeftFoldExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(RequiresExpressionAST* ast) { + accept(ast->parameterDeclarationClause); + for (auto node : ListView{ast->requirementList}) { + accept(node); + } +} + +void ASTVisitor::visit(VaArgExpressionAST* ast) { + accept(ast->expression); + accept(ast->typeId); +} + +void ASTVisitor::visit(SubscriptExpressionAST* ast) { + accept(ast->baseExpression); + accept(ast->indexExpression); +} + +void ASTVisitor::visit(CallExpressionAST* ast) { + accept(ast->baseExpression); + for (auto node : ListView{ast->expressionList}) { + accept(node); + } +} + +void ASTVisitor::visit(TypeConstructionAST* ast) { + accept(ast->typeSpecifier); + for (auto node : ListView{ast->expressionList}) { + accept(node); + } +} + +void ASTVisitor::visit(BracedTypeConstructionAST* ast) { + accept(ast->typeSpecifier); + accept(ast->bracedInitList); +} + +void ASTVisitor::visit(SpliceMemberExpressionAST* ast) { + accept(ast->baseExpression); + accept(ast->splicer); +} + +void ASTVisitor::visit(MemberExpressionAST* ast) { + accept(ast->baseExpression); + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(PostIncrExpressionAST* ast) { + accept(ast->baseExpression); +} + +void ASTVisitor::visit(CppCastExpressionAST* ast) { + accept(ast->typeId); + accept(ast->expression); +} + +void ASTVisitor::visit(BuiltinBitCastExpressionAST* ast) { + accept(ast->typeId); + accept(ast->expression); +} + +void ASTVisitor::visit(BuiltinOffsetofExpressionAST* ast) { + accept(ast->typeId); + accept(ast->expression); +} + +void ASTVisitor::visit(TypeidExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(TypeidOfTypeExpressionAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(SpliceExpressionAST* ast) { accept(ast->splicer); } + +void ASTVisitor::visit(GlobalScopeReflectExpressionAST* ast) {} + +void ASTVisitor::visit(NamespaceReflectExpressionAST* ast) {} + +void ASTVisitor::visit(TypeIdReflectExpressionAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(ReflectExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(UnaryExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(AwaitExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(SizeofExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(SizeofTypeExpressionAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(SizeofPackExpressionAST* ast) {} + +void ASTVisitor::visit(AlignofTypeExpressionAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(AlignofExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(NoexceptExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(NewExpressionAST* ast) { + accept(ast->newPlacement); + for (auto node : ListView{ast->typeSpecifierList}) { + accept(node); + } + accept(ast->declarator); + accept(ast->newInitalizer); +} + +void ASTVisitor::visit(DeleteExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(CastExpressionAST* ast) { + accept(ast->typeId); + accept(ast->expression); +} + +void ASTVisitor::visit(ImplicitCastExpressionAST* ast) { + accept(ast->expression); +} + +void ASTVisitor::visit(BinaryExpressionAST* ast) { + accept(ast->leftExpression); + accept(ast->rightExpression); +} + +void ASTVisitor::visit(ConditionalExpressionAST* ast) { + accept(ast->condition); + accept(ast->iftrueExpression); + accept(ast->iffalseExpression); +} + +void ASTVisitor::visit(YieldExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(ThrowExpressionAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(AssignmentExpressionAST* ast) { + accept(ast->leftExpression); + accept(ast->rightExpression); +} + +void ASTVisitor::visit(PackExpansionExpressionAST* ast) { + accept(ast->expression); +} + +void ASTVisitor::visit(DesignatedInitializerClauseAST* ast) { + accept(ast->initializer); +} + +void ASTVisitor::visit(TypeTraitExpressionAST* ast) { + for (auto node : ListView{ast->typeIdList}) { + accept(node); + } +} + +void ASTVisitor::visit(ConditionExpressionAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->declSpecifierList}) { + accept(node); + } + accept(ast->declarator); + accept(ast->initializer); +} + +void ASTVisitor::visit(EqualInitializerAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(BracedInitListAST* ast) { + for (auto node : ListView{ast->expressionList}) { + accept(node); + } +} + +void ASTVisitor::visit(ParenInitializerAST* ast) { + for (auto node : ListView{ast->expressionList}) { + accept(node); + } +} + +void ASTVisitor::visit(SplicerAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(GlobalModuleFragmentAST* ast) { + for (auto node : ListView{ast->declarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(PrivateModuleFragmentAST* ast) { + for (auto node : ListView{ast->declarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(ModuleDeclarationAST* ast) { + accept(ast->moduleName); + accept(ast->modulePartition); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } +} + +void ASTVisitor::visit(ModuleNameAST* ast) { accept(ast->moduleQualifier); } + +void ASTVisitor::visit(ModuleQualifierAST* ast) { + accept(ast->moduleQualifier); +} + +void ASTVisitor::visit(ModulePartitionAST* ast) { accept(ast->moduleName); } + +void ASTVisitor::visit(ImportNameAST* ast) { + accept(ast->modulePartition); + accept(ast->moduleName); +} + +void ASTVisitor::visit(InitDeclaratorAST* ast) { + accept(ast->declarator); + accept(ast->requiresClause); + accept(ast->initializer); +} + +void ASTVisitor::visit(DeclaratorAST* ast) { + for (auto node : ListView{ast->ptrOpList}) { + accept(node); + } + accept(ast->coreDeclarator); + for (auto node : ListView{ast->declaratorChunkList}) { + accept(node); + } +} + +void ASTVisitor::visit(UsingDeclaratorAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(EnumeratorAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->expression); +} + +void ASTVisitor::visit(TypeIdAST* ast) { + for (auto node : ListView{ast->typeSpecifierList}) { + accept(node); + } + accept(ast->declarator); +} + +void ASTVisitor::visit(HandlerAST* ast) { + accept(ast->exceptionDeclaration); + accept(ast->statement); +} + +void ASTVisitor::visit(BaseSpecifierAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(RequiresClauseAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(ParameterDeclarationClauseAST* ast) { + for (auto node : ListView{ast->parameterDeclarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(TrailingReturnTypeAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(LambdaSpecifierAST* ast) {} + +void ASTVisitor::visit(TypeConstraintAST* ast) { + accept(ast->nestedNameSpecifier); + for (auto node : ListView{ast->templateArgumentList}) { + accept(node); + } +} + +void ASTVisitor::visit(AttributeArgumentClauseAST* ast) {} + +void ASTVisitor::visit(AttributeAST* ast) { + accept(ast->attributeToken); + accept(ast->attributeArgumentClause); +} + +void ASTVisitor::visit(AttributeUsingPrefixAST* ast) {} + +void ASTVisitor::visit(NewPlacementAST* ast) { + for (auto node : ListView{ast->expressionList}) { + accept(node); + } +} + +void ASTVisitor::visit(NestedNamespaceSpecifierAST* ast) {} + +void ASTVisitor::visit(TemplateTypeParameterAST* ast) { + for (auto node : ListView{ast->templateParameterList}) { + accept(node); + } + accept(ast->requiresClause); + accept(ast->idExpression); +} + +void ASTVisitor::visit(NonTypeTemplateParameterAST* ast) { + accept(ast->declaration); +} + +void ASTVisitor::visit(TypenameTypeParameterAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(ConstraintTypeParameterAST* ast) { + accept(ast->typeConstraint); + accept(ast->typeId); +} + +void ASTVisitor::visit(GeneratedTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(TypedefSpecifierAST* ast) {} + +void ASTVisitor::visit(FriendSpecifierAST* ast) {} + +void ASTVisitor::visit(ConstevalSpecifierAST* ast) {} + +void ASTVisitor::visit(ConstinitSpecifierAST* ast) {} + +void ASTVisitor::visit(ConstexprSpecifierAST* ast) {} + +void ASTVisitor::visit(InlineSpecifierAST* ast) {} + +void ASTVisitor::visit(StaticSpecifierAST* ast) {} + +void ASTVisitor::visit(ExternSpecifierAST* ast) {} + +void ASTVisitor::visit(ThreadLocalSpecifierAST* ast) {} + +void ASTVisitor::visit(ThreadSpecifierAST* ast) {} + +void ASTVisitor::visit(MutableSpecifierAST* ast) {} + +void ASTVisitor::visit(VirtualSpecifierAST* ast) {} + +void ASTVisitor::visit(ExplicitSpecifierAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(AutoTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(VoidTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(SizeTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(SignTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(VaListTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(IntegralTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(FloatingPointTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(ComplexTypeSpecifierAST* ast) {} + +void ASTVisitor::visit(NamedTypeSpecifierAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(AtomicTypeSpecifierAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(UnderlyingTypeSpecifierAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(ElaboratedTypeSpecifierAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(DecltypeAutoSpecifierAST* ast) {} + +void ASTVisitor::visit(DecltypeSpecifierAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(PlaceholderTypeSpecifierAST* ast) { + accept(ast->typeConstraint); + accept(ast->specifier); +} + +void ASTVisitor::visit(ConstQualifierAST* ast) {} + +void ASTVisitor::visit(VolatileQualifierAST* ast) {} + +void ASTVisitor::visit(RestrictQualifierAST* ast) {} + +void ASTVisitor::visit(EnumSpecifierAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); + for (auto node : ListView{ast->typeSpecifierList}) { + accept(node); + } + for (auto node : ListView{ast->enumeratorList}) { + accept(node); + } +} + +void ASTVisitor::visit(ClassSpecifierAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); + for (auto node : ListView{ast->baseSpecifierList}) { + accept(node); + } + for (auto node : ListView{ast->declarationList}) { + accept(node); + } +} + +void ASTVisitor::visit(TypenameSpecifierAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(SplicerTypeSpecifierAST* ast) { accept(ast->splicer); } + +void ASTVisitor::visit(PointerOperatorAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->cvQualifierList}) { + accept(node); + } +} + +void ASTVisitor::visit(ReferenceOperatorAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } +} + +void ASTVisitor::visit(PtrToMemberOperatorAST* ast) { + accept(ast->nestedNameSpecifier); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->cvQualifierList}) { + accept(node); + } +} + +void ASTVisitor::visit(BitfieldDeclaratorAST* ast) { + accept(ast->unqualifiedId); + accept(ast->sizeExpression); +} + +void ASTVisitor::visit(ParameterPackAST* ast) { accept(ast->coreDeclarator); } + +void ASTVisitor::visit(IdDeclaratorAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } +} + +void ASTVisitor::visit(NestedDeclaratorAST* ast) { accept(ast->declarator); } + +void ASTVisitor::visit(FunctionDeclaratorChunkAST* ast) { + accept(ast->parameterDeclarationClause); + for (auto node : ListView{ast->cvQualifierList}) { + accept(node); + } + accept(ast->exceptionSpecifier); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + accept(ast->trailingReturnType); +} + +void ASTVisitor::visit(ArrayDeclaratorChunkAST* ast) { + accept(ast->expression); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } +} + +void ASTVisitor::visit(NameIdAST* ast) {} + +void ASTVisitor::visit(DestructorIdAST* ast) { accept(ast->id); } + +void ASTVisitor::visit(DecltypeIdAST* ast) { accept(ast->decltypeSpecifier); } + +void ASTVisitor::visit(OperatorFunctionIdAST* ast) {} + +void ASTVisitor::visit(LiteralOperatorIdAST* ast) {} + +void ASTVisitor::visit(ConversionFunctionIdAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(SimpleTemplateIdAST* ast) { + for (auto node : ListView{ast->templateArgumentList}) { + accept(node); + } +} + +void ASTVisitor::visit(LiteralOperatorTemplateIdAST* ast) { + accept(ast->literalOperatorId); + for (auto node : ListView{ast->templateArgumentList}) { + accept(node); + } +} + +void ASTVisitor::visit(OperatorFunctionTemplateIdAST* ast) { + accept(ast->operatorFunctionId); + for (auto node : ListView{ast->templateArgumentList}) { + accept(node); + } +} + +void ASTVisitor::visit(GlobalNestedNameSpecifierAST* ast) {} + +void ASTVisitor::visit(SimpleNestedNameSpecifierAST* ast) { + accept(ast->nestedNameSpecifier); +} + +void ASTVisitor::visit(DecltypeNestedNameSpecifierAST* ast) { + accept(ast->decltypeSpecifier); +} + +void ASTVisitor::visit(TemplateNestedNameSpecifierAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->templateId); +} + +void ASTVisitor::visit(DefaultFunctionBodyAST* ast) {} + +void ASTVisitor::visit(CompoundStatementFunctionBodyAST* ast) { + for (auto node : ListView{ast->memInitializerList}) { + accept(node); + } + accept(ast->statement); +} + +void ASTVisitor::visit(TryStatementFunctionBodyAST* ast) { + for (auto node : ListView{ast->memInitializerList}) { + accept(node); + } + accept(ast->statement); + for (auto node : ListView{ast->handlerList}) { + accept(node); + } +} + +void ASTVisitor::visit(DeleteFunctionBodyAST* ast) {} + +void ASTVisitor::visit(TypeTemplateArgumentAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(ExpressionTemplateArgumentAST* ast) { + accept(ast->expression); +} + +void ASTVisitor::visit(ThrowExceptionSpecifierAST* ast) {} + +void ASTVisitor::visit(NoexceptSpecifierAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(SimpleRequirementAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(CompoundRequirementAST* ast) { + accept(ast->expression); + accept(ast->typeConstraint); +} + +void ASTVisitor::visit(TypeRequirementAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); +} + +void ASTVisitor::visit(NestedRequirementAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(NewParenInitializerAST* ast) { + for (auto node : ListView{ast->expressionList}) { + accept(node); + } +} + +void ASTVisitor::visit(NewBracedInitializerAST* ast) { + accept(ast->bracedInitList); +} + +void ASTVisitor::visit(ParenMemInitializerAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); + for (auto node : ListView{ast->expressionList}) { + accept(node); + } +} + +void ASTVisitor::visit(BracedMemInitializerAST* ast) { + accept(ast->nestedNameSpecifier); + accept(ast->unqualifiedId); + accept(ast->bracedInitList); +} + +void ASTVisitor::visit(ThisLambdaCaptureAST* ast) {} + +void ASTVisitor::visit(DerefThisLambdaCaptureAST* ast) {} + +void ASTVisitor::visit(SimpleLambdaCaptureAST* ast) {} + +void ASTVisitor::visit(RefLambdaCaptureAST* ast) {} + +void ASTVisitor::visit(RefInitLambdaCaptureAST* ast) { + accept(ast->initializer); +} + +void ASTVisitor::visit(InitLambdaCaptureAST* ast) { accept(ast->initializer); } + +void ASTVisitor::visit(EllipsisExceptionDeclarationAST* ast) {} + +void ASTVisitor::visit(TypeExceptionDeclarationAST* ast) { + for (auto node : ListView{ast->attributeList}) { + accept(node); + } + for (auto node : ListView{ast->typeSpecifierList}) { + accept(node); + } + accept(ast->declarator); +} + +void ASTVisitor::visit(CxxAttributeAST* ast) { + accept(ast->attributeUsingPrefix); + for (auto node : ListView{ast->attributeList}) { + accept(node); + } +} + +void ASTVisitor::visit(GccAttributeAST* ast) {} + +void ASTVisitor::visit(AlignasAttributeAST* ast) { accept(ast->expression); } + +void ASTVisitor::visit(AlignasTypeAttributeAST* ast) { accept(ast->typeId); } + +void ASTVisitor::visit(AsmAttributeAST* ast) {} + +void ASTVisitor::visit(ScopedAttributeTokenAST* ast) {} + +void ASTVisitor::visit(SimpleAttributeTokenAST* ast) {} + +} // namespace cxx diff --git a/src/parser/cxx/ast_visitor.h b/src/parser/cxx/ast_visitor.h index f56c6f9d..0d0a57ca 100644 --- a/src/parser/cxx/ast_visitor.h +++ b/src/parser/cxx/ast_visitor.h @@ -28,276 +28,281 @@ class ASTVisitor { public: virtual ~ASTVisitor() = default; + void accept(AST* ast); + + [[nodiscard]] virtual bool preVisit(AST* ast); + virtual void postVisit(AST* ast); + // UnitAST - virtual void visit(TranslationUnitAST* ast) = 0; - virtual void visit(ModuleUnitAST* ast) = 0; + virtual void visit(TranslationUnitAST* ast); + virtual void visit(ModuleUnitAST* ast); // DeclarationAST - virtual void visit(SimpleDeclarationAST* ast) = 0; - virtual void visit(AsmDeclarationAST* ast) = 0; - virtual void visit(NamespaceAliasDefinitionAST* ast) = 0; - virtual void visit(UsingDeclarationAST* ast) = 0; - virtual void visit(UsingEnumDeclarationAST* ast) = 0; - virtual void visit(UsingDirectiveAST* ast) = 0; - virtual void visit(StaticAssertDeclarationAST* ast) = 0; - virtual void visit(AliasDeclarationAST* ast) = 0; - virtual void visit(OpaqueEnumDeclarationAST* ast) = 0; - virtual void visit(FunctionDefinitionAST* ast) = 0; - virtual void visit(TemplateDeclarationAST* ast) = 0; - virtual void visit(ConceptDefinitionAST* ast) = 0; - virtual void visit(DeductionGuideAST* ast) = 0; - virtual void visit(ExplicitInstantiationAST* ast) = 0; - virtual void visit(ExportDeclarationAST* ast) = 0; - virtual void visit(ExportCompoundDeclarationAST* ast) = 0; - virtual void visit(LinkageSpecificationAST* ast) = 0; - virtual void visit(NamespaceDefinitionAST* ast) = 0; - virtual void visit(EmptyDeclarationAST* ast) = 0; - virtual void visit(AttributeDeclarationAST* ast) = 0; - virtual void visit(ModuleImportDeclarationAST* ast) = 0; - virtual void visit(ParameterDeclarationAST* ast) = 0; - virtual void visit(AccessDeclarationAST* ast) = 0; - virtual void visit(ForRangeDeclarationAST* ast) = 0; - virtual void visit(StructuredBindingDeclarationAST* ast) = 0; - virtual void visit(AsmOperandAST* ast) = 0; - virtual void visit(AsmQualifierAST* ast) = 0; - virtual void visit(AsmClobberAST* ast) = 0; - virtual void visit(AsmGotoLabelAST* ast) = 0; + virtual void visit(SimpleDeclarationAST* ast); + virtual void visit(AsmDeclarationAST* ast); + virtual void visit(NamespaceAliasDefinitionAST* ast); + virtual void visit(UsingDeclarationAST* ast); + virtual void visit(UsingEnumDeclarationAST* ast); + virtual void visit(UsingDirectiveAST* ast); + virtual void visit(StaticAssertDeclarationAST* ast); + virtual void visit(AliasDeclarationAST* ast); + virtual void visit(OpaqueEnumDeclarationAST* ast); + virtual void visit(FunctionDefinitionAST* ast); + virtual void visit(TemplateDeclarationAST* ast); + virtual void visit(ConceptDefinitionAST* ast); + virtual void visit(DeductionGuideAST* ast); + virtual void visit(ExplicitInstantiationAST* ast); + virtual void visit(ExportDeclarationAST* ast); + virtual void visit(ExportCompoundDeclarationAST* ast); + virtual void visit(LinkageSpecificationAST* ast); + virtual void visit(NamespaceDefinitionAST* ast); + virtual void visit(EmptyDeclarationAST* ast); + virtual void visit(AttributeDeclarationAST* ast); + virtual void visit(ModuleImportDeclarationAST* ast); + virtual void visit(ParameterDeclarationAST* ast); + virtual void visit(AccessDeclarationAST* ast); + virtual void visit(ForRangeDeclarationAST* ast); + virtual void visit(StructuredBindingDeclarationAST* ast); + virtual void visit(AsmOperandAST* ast); + virtual void visit(AsmQualifierAST* ast); + virtual void visit(AsmClobberAST* ast); + virtual void visit(AsmGotoLabelAST* ast); // StatementAST - virtual void visit(LabeledStatementAST* ast) = 0; - virtual void visit(CaseStatementAST* ast) = 0; - virtual void visit(DefaultStatementAST* ast) = 0; - virtual void visit(ExpressionStatementAST* ast) = 0; - virtual void visit(CompoundStatementAST* ast) = 0; - virtual void visit(IfStatementAST* ast) = 0; - virtual void visit(ConstevalIfStatementAST* ast) = 0; - virtual void visit(SwitchStatementAST* ast) = 0; - virtual void visit(WhileStatementAST* ast) = 0; - virtual void visit(DoStatementAST* ast) = 0; - virtual void visit(ForRangeStatementAST* ast) = 0; - virtual void visit(ForStatementAST* ast) = 0; - virtual void visit(BreakStatementAST* ast) = 0; - virtual void visit(ContinueStatementAST* ast) = 0; - virtual void visit(ReturnStatementAST* ast) = 0; - virtual void visit(CoroutineReturnStatementAST* ast) = 0; - virtual void visit(GotoStatementAST* ast) = 0; - virtual void visit(DeclarationStatementAST* ast) = 0; - virtual void visit(TryBlockStatementAST* ast) = 0; + virtual void visit(LabeledStatementAST* ast); + virtual void visit(CaseStatementAST* ast); + virtual void visit(DefaultStatementAST* ast); + virtual void visit(ExpressionStatementAST* ast); + virtual void visit(CompoundStatementAST* ast); + virtual void visit(IfStatementAST* ast); + virtual void visit(ConstevalIfStatementAST* ast); + virtual void visit(SwitchStatementAST* ast); + virtual void visit(WhileStatementAST* ast); + virtual void visit(DoStatementAST* ast); + virtual void visit(ForRangeStatementAST* ast); + virtual void visit(ForStatementAST* ast); + virtual void visit(BreakStatementAST* ast); + virtual void visit(ContinueStatementAST* ast); + virtual void visit(ReturnStatementAST* ast); + virtual void visit(CoroutineReturnStatementAST* ast); + virtual void visit(GotoStatementAST* ast); + virtual void visit(DeclarationStatementAST* ast); + virtual void visit(TryBlockStatementAST* ast); // ExpressionAST - virtual void visit(GeneratedLiteralExpressionAST* ast) = 0; - virtual void visit(CharLiteralExpressionAST* ast) = 0; - virtual void visit(BoolLiteralExpressionAST* ast) = 0; - virtual void visit(IntLiteralExpressionAST* ast) = 0; - virtual void visit(FloatLiteralExpressionAST* ast) = 0; - virtual void visit(NullptrLiteralExpressionAST* ast) = 0; - virtual void visit(StringLiteralExpressionAST* ast) = 0; - virtual void visit(UserDefinedStringLiteralExpressionAST* ast) = 0; - virtual void visit(ThisExpressionAST* ast) = 0; - virtual void visit(NestedStatementExpressionAST* ast) = 0; - virtual void visit(NestedExpressionAST* ast) = 0; - virtual void visit(IdExpressionAST* ast) = 0; - virtual void visit(LambdaExpressionAST* ast) = 0; - virtual void visit(FoldExpressionAST* ast) = 0; - virtual void visit(RightFoldExpressionAST* ast) = 0; - virtual void visit(LeftFoldExpressionAST* ast) = 0; - virtual void visit(RequiresExpressionAST* ast) = 0; - virtual void visit(VaArgExpressionAST* ast) = 0; - virtual void visit(SubscriptExpressionAST* ast) = 0; - virtual void visit(CallExpressionAST* ast) = 0; - virtual void visit(TypeConstructionAST* ast) = 0; - virtual void visit(BracedTypeConstructionAST* ast) = 0; - virtual void visit(SpliceMemberExpressionAST* ast) = 0; - virtual void visit(MemberExpressionAST* ast) = 0; - virtual void visit(PostIncrExpressionAST* ast) = 0; - virtual void visit(CppCastExpressionAST* ast) = 0; - virtual void visit(BuiltinBitCastExpressionAST* ast) = 0; - virtual void visit(BuiltinOffsetofExpressionAST* ast) = 0; - virtual void visit(TypeidExpressionAST* ast) = 0; - virtual void visit(TypeidOfTypeExpressionAST* ast) = 0; - virtual void visit(SpliceExpressionAST* ast) = 0; - virtual void visit(GlobalScopeReflectExpressionAST* ast) = 0; - virtual void visit(NamespaceReflectExpressionAST* ast) = 0; - virtual void visit(TypeIdReflectExpressionAST* ast) = 0; - virtual void visit(ReflectExpressionAST* ast) = 0; - virtual void visit(UnaryExpressionAST* ast) = 0; - virtual void visit(AwaitExpressionAST* ast) = 0; - virtual void visit(SizeofExpressionAST* ast) = 0; - virtual void visit(SizeofTypeExpressionAST* ast) = 0; - virtual void visit(SizeofPackExpressionAST* ast) = 0; - virtual void visit(AlignofTypeExpressionAST* ast) = 0; - virtual void visit(AlignofExpressionAST* ast) = 0; - virtual void visit(NoexceptExpressionAST* ast) = 0; - virtual void visit(NewExpressionAST* ast) = 0; - virtual void visit(DeleteExpressionAST* ast) = 0; - virtual void visit(CastExpressionAST* ast) = 0; - virtual void visit(ImplicitCastExpressionAST* ast) = 0; - virtual void visit(BinaryExpressionAST* ast) = 0; - virtual void visit(ConditionalExpressionAST* ast) = 0; - virtual void visit(YieldExpressionAST* ast) = 0; - virtual void visit(ThrowExpressionAST* ast) = 0; - virtual void visit(AssignmentExpressionAST* ast) = 0; - virtual void visit(PackExpansionExpressionAST* ast) = 0; - virtual void visit(DesignatedInitializerClauseAST* ast) = 0; - virtual void visit(TypeTraitExpressionAST* ast) = 0; - virtual void visit(ConditionExpressionAST* ast) = 0; - virtual void visit(EqualInitializerAST* ast) = 0; - virtual void visit(BracedInitListAST* ast) = 0; - virtual void visit(ParenInitializerAST* ast) = 0; + virtual void visit(GeneratedLiteralExpressionAST* ast); + virtual void visit(CharLiteralExpressionAST* ast); + virtual void visit(BoolLiteralExpressionAST* ast); + virtual void visit(IntLiteralExpressionAST* ast); + virtual void visit(FloatLiteralExpressionAST* ast); + virtual void visit(NullptrLiteralExpressionAST* ast); + virtual void visit(StringLiteralExpressionAST* ast); + virtual void visit(UserDefinedStringLiteralExpressionAST* ast); + virtual void visit(ThisExpressionAST* ast); + virtual void visit(NestedStatementExpressionAST* ast); + virtual void visit(NestedExpressionAST* ast); + virtual void visit(IdExpressionAST* ast); + virtual void visit(LambdaExpressionAST* ast); + virtual void visit(FoldExpressionAST* ast); + virtual void visit(RightFoldExpressionAST* ast); + virtual void visit(LeftFoldExpressionAST* ast); + virtual void visit(RequiresExpressionAST* ast); + virtual void visit(VaArgExpressionAST* ast); + virtual void visit(SubscriptExpressionAST* ast); + virtual void visit(CallExpressionAST* ast); + virtual void visit(TypeConstructionAST* ast); + virtual void visit(BracedTypeConstructionAST* ast); + virtual void visit(SpliceMemberExpressionAST* ast); + virtual void visit(MemberExpressionAST* ast); + virtual void visit(PostIncrExpressionAST* ast); + virtual void visit(CppCastExpressionAST* ast); + virtual void visit(BuiltinBitCastExpressionAST* ast); + virtual void visit(BuiltinOffsetofExpressionAST* ast); + virtual void visit(TypeidExpressionAST* ast); + virtual void visit(TypeidOfTypeExpressionAST* ast); + virtual void visit(SpliceExpressionAST* ast); + virtual void visit(GlobalScopeReflectExpressionAST* ast); + virtual void visit(NamespaceReflectExpressionAST* ast); + virtual void visit(TypeIdReflectExpressionAST* ast); + virtual void visit(ReflectExpressionAST* ast); + virtual void visit(UnaryExpressionAST* ast); + virtual void visit(AwaitExpressionAST* ast); + virtual void visit(SizeofExpressionAST* ast); + virtual void visit(SizeofTypeExpressionAST* ast); + virtual void visit(SizeofPackExpressionAST* ast); + virtual void visit(AlignofTypeExpressionAST* ast); + virtual void visit(AlignofExpressionAST* ast); + virtual void visit(NoexceptExpressionAST* ast); + virtual void visit(NewExpressionAST* ast); + virtual void visit(DeleteExpressionAST* ast); + virtual void visit(CastExpressionAST* ast); + virtual void visit(ImplicitCastExpressionAST* ast); + virtual void visit(BinaryExpressionAST* ast); + virtual void visit(ConditionalExpressionAST* ast); + virtual void visit(YieldExpressionAST* ast); + virtual void visit(ThrowExpressionAST* ast); + virtual void visit(AssignmentExpressionAST* ast); + virtual void visit(PackExpansionExpressionAST* ast); + virtual void visit(DesignatedInitializerClauseAST* ast); + virtual void visit(TypeTraitExpressionAST* ast); + virtual void visit(ConditionExpressionAST* ast); + virtual void visit(EqualInitializerAST* ast); + virtual void visit(BracedInitListAST* ast); + virtual void visit(ParenInitializerAST* ast); // AST - virtual void visit(SplicerAST* ast) = 0; - virtual void visit(GlobalModuleFragmentAST* ast) = 0; - virtual void visit(PrivateModuleFragmentAST* ast) = 0; - virtual void visit(ModuleDeclarationAST* ast) = 0; - virtual void visit(ModuleNameAST* ast) = 0; - virtual void visit(ModuleQualifierAST* ast) = 0; - virtual void visit(ModulePartitionAST* ast) = 0; - virtual void visit(ImportNameAST* ast) = 0; - virtual void visit(InitDeclaratorAST* ast) = 0; - virtual void visit(DeclaratorAST* ast) = 0; - virtual void visit(UsingDeclaratorAST* ast) = 0; - virtual void visit(EnumeratorAST* ast) = 0; - virtual void visit(TypeIdAST* ast) = 0; - virtual void visit(HandlerAST* ast) = 0; - virtual void visit(BaseSpecifierAST* ast) = 0; - virtual void visit(RequiresClauseAST* ast) = 0; - virtual void visit(ParameterDeclarationClauseAST* ast) = 0; - virtual void visit(TrailingReturnTypeAST* ast) = 0; - virtual void visit(LambdaSpecifierAST* ast) = 0; - virtual void visit(TypeConstraintAST* ast) = 0; - virtual void visit(AttributeArgumentClauseAST* ast) = 0; - virtual void visit(AttributeAST* ast) = 0; - virtual void visit(AttributeUsingPrefixAST* ast) = 0; - virtual void visit(NewPlacementAST* ast) = 0; - virtual void visit(NestedNamespaceSpecifierAST* ast) = 0; + virtual void visit(SplicerAST* ast); + virtual void visit(GlobalModuleFragmentAST* ast); + virtual void visit(PrivateModuleFragmentAST* ast); + virtual void visit(ModuleDeclarationAST* ast); + virtual void visit(ModuleNameAST* ast); + virtual void visit(ModuleQualifierAST* ast); + virtual void visit(ModulePartitionAST* ast); + virtual void visit(ImportNameAST* ast); + virtual void visit(InitDeclaratorAST* ast); + virtual void visit(DeclaratorAST* ast); + virtual void visit(UsingDeclaratorAST* ast); + virtual void visit(EnumeratorAST* ast); + virtual void visit(TypeIdAST* ast); + virtual void visit(HandlerAST* ast); + virtual void visit(BaseSpecifierAST* ast); + virtual void visit(RequiresClauseAST* ast); + virtual void visit(ParameterDeclarationClauseAST* ast); + virtual void visit(TrailingReturnTypeAST* ast); + virtual void visit(LambdaSpecifierAST* ast); + virtual void visit(TypeConstraintAST* ast); + virtual void visit(AttributeArgumentClauseAST* ast); + virtual void visit(AttributeAST* ast); + virtual void visit(AttributeUsingPrefixAST* ast); + virtual void visit(NewPlacementAST* ast); + virtual void visit(NestedNamespaceSpecifierAST* ast); // TemplateParameterAST - virtual void visit(TemplateTypeParameterAST* ast) = 0; - virtual void visit(NonTypeTemplateParameterAST* ast) = 0; - virtual void visit(TypenameTypeParameterAST* ast) = 0; - virtual void visit(ConstraintTypeParameterAST* ast) = 0; + virtual void visit(TemplateTypeParameterAST* ast); + virtual void visit(NonTypeTemplateParameterAST* ast); + virtual void visit(TypenameTypeParameterAST* ast); + virtual void visit(ConstraintTypeParameterAST* ast); // SpecifierAST - virtual void visit(GeneratedTypeSpecifierAST* ast) = 0; - virtual void visit(TypedefSpecifierAST* ast) = 0; - virtual void visit(FriendSpecifierAST* ast) = 0; - virtual void visit(ConstevalSpecifierAST* ast) = 0; - virtual void visit(ConstinitSpecifierAST* ast) = 0; - virtual void visit(ConstexprSpecifierAST* ast) = 0; - virtual void visit(InlineSpecifierAST* ast) = 0; - virtual void visit(StaticSpecifierAST* ast) = 0; - virtual void visit(ExternSpecifierAST* ast) = 0; - virtual void visit(ThreadLocalSpecifierAST* ast) = 0; - virtual void visit(ThreadSpecifierAST* ast) = 0; - virtual void visit(MutableSpecifierAST* ast) = 0; - virtual void visit(VirtualSpecifierAST* ast) = 0; - virtual void visit(ExplicitSpecifierAST* ast) = 0; - virtual void visit(AutoTypeSpecifierAST* ast) = 0; - virtual void visit(VoidTypeSpecifierAST* ast) = 0; - virtual void visit(SizeTypeSpecifierAST* ast) = 0; - virtual void visit(SignTypeSpecifierAST* ast) = 0; - virtual void visit(VaListTypeSpecifierAST* ast) = 0; - virtual void visit(IntegralTypeSpecifierAST* ast) = 0; - virtual void visit(FloatingPointTypeSpecifierAST* ast) = 0; - virtual void visit(ComplexTypeSpecifierAST* ast) = 0; - virtual void visit(NamedTypeSpecifierAST* ast) = 0; - virtual void visit(AtomicTypeSpecifierAST* ast) = 0; - virtual void visit(UnderlyingTypeSpecifierAST* ast) = 0; - virtual void visit(ElaboratedTypeSpecifierAST* ast) = 0; - virtual void visit(DecltypeAutoSpecifierAST* ast) = 0; - virtual void visit(DecltypeSpecifierAST* ast) = 0; - virtual void visit(PlaceholderTypeSpecifierAST* ast) = 0; - virtual void visit(ConstQualifierAST* ast) = 0; - virtual void visit(VolatileQualifierAST* ast) = 0; - virtual void visit(RestrictQualifierAST* ast) = 0; - virtual void visit(EnumSpecifierAST* ast) = 0; - virtual void visit(ClassSpecifierAST* ast) = 0; - virtual void visit(TypenameSpecifierAST* ast) = 0; - virtual void visit(SplicerTypeSpecifierAST* ast) = 0; + virtual void visit(GeneratedTypeSpecifierAST* ast); + virtual void visit(TypedefSpecifierAST* ast); + virtual void visit(FriendSpecifierAST* ast); + virtual void visit(ConstevalSpecifierAST* ast); + virtual void visit(ConstinitSpecifierAST* ast); + virtual void visit(ConstexprSpecifierAST* ast); + virtual void visit(InlineSpecifierAST* ast); + virtual void visit(StaticSpecifierAST* ast); + virtual void visit(ExternSpecifierAST* ast); + virtual void visit(ThreadLocalSpecifierAST* ast); + virtual void visit(ThreadSpecifierAST* ast); + virtual void visit(MutableSpecifierAST* ast); + virtual void visit(VirtualSpecifierAST* ast); + virtual void visit(ExplicitSpecifierAST* ast); + virtual void visit(AutoTypeSpecifierAST* ast); + virtual void visit(VoidTypeSpecifierAST* ast); + virtual void visit(SizeTypeSpecifierAST* ast); + virtual void visit(SignTypeSpecifierAST* ast); + virtual void visit(VaListTypeSpecifierAST* ast); + virtual void visit(IntegralTypeSpecifierAST* ast); + virtual void visit(FloatingPointTypeSpecifierAST* ast); + virtual void visit(ComplexTypeSpecifierAST* ast); + virtual void visit(NamedTypeSpecifierAST* ast); + virtual void visit(AtomicTypeSpecifierAST* ast); + virtual void visit(UnderlyingTypeSpecifierAST* ast); + virtual void visit(ElaboratedTypeSpecifierAST* ast); + virtual void visit(DecltypeAutoSpecifierAST* ast); + virtual void visit(DecltypeSpecifierAST* ast); + virtual void visit(PlaceholderTypeSpecifierAST* ast); + virtual void visit(ConstQualifierAST* ast); + virtual void visit(VolatileQualifierAST* ast); + virtual void visit(RestrictQualifierAST* ast); + virtual void visit(EnumSpecifierAST* ast); + virtual void visit(ClassSpecifierAST* ast); + virtual void visit(TypenameSpecifierAST* ast); + virtual void visit(SplicerTypeSpecifierAST* ast); // PtrOperatorAST - virtual void visit(PointerOperatorAST* ast) = 0; - virtual void visit(ReferenceOperatorAST* ast) = 0; - virtual void visit(PtrToMemberOperatorAST* ast) = 0; + virtual void visit(PointerOperatorAST* ast); + virtual void visit(ReferenceOperatorAST* ast); + virtual void visit(PtrToMemberOperatorAST* ast); // CoreDeclaratorAST - virtual void visit(BitfieldDeclaratorAST* ast) = 0; - virtual void visit(ParameterPackAST* ast) = 0; - virtual void visit(IdDeclaratorAST* ast) = 0; - virtual void visit(NestedDeclaratorAST* ast) = 0; + virtual void visit(BitfieldDeclaratorAST* ast); + virtual void visit(ParameterPackAST* ast); + virtual void visit(IdDeclaratorAST* ast); + virtual void visit(NestedDeclaratorAST* ast); // DeclaratorChunkAST - virtual void visit(FunctionDeclaratorChunkAST* ast) = 0; - virtual void visit(ArrayDeclaratorChunkAST* ast) = 0; + virtual void visit(FunctionDeclaratorChunkAST* ast); + virtual void visit(ArrayDeclaratorChunkAST* ast); // UnqualifiedIdAST - virtual void visit(NameIdAST* ast) = 0; - virtual void visit(DestructorIdAST* ast) = 0; - virtual void visit(DecltypeIdAST* ast) = 0; - virtual void visit(OperatorFunctionIdAST* ast) = 0; - virtual void visit(LiteralOperatorIdAST* ast) = 0; - virtual void visit(ConversionFunctionIdAST* ast) = 0; - virtual void visit(SimpleTemplateIdAST* ast) = 0; - virtual void visit(LiteralOperatorTemplateIdAST* ast) = 0; - virtual void visit(OperatorFunctionTemplateIdAST* ast) = 0; + virtual void visit(NameIdAST* ast); + virtual void visit(DestructorIdAST* ast); + virtual void visit(DecltypeIdAST* ast); + virtual void visit(OperatorFunctionIdAST* ast); + virtual void visit(LiteralOperatorIdAST* ast); + virtual void visit(ConversionFunctionIdAST* ast); + virtual void visit(SimpleTemplateIdAST* ast); + virtual void visit(LiteralOperatorTemplateIdAST* ast); + virtual void visit(OperatorFunctionTemplateIdAST* ast); // NestedNameSpecifierAST - virtual void visit(GlobalNestedNameSpecifierAST* ast) = 0; - virtual void visit(SimpleNestedNameSpecifierAST* ast) = 0; - virtual void visit(DecltypeNestedNameSpecifierAST* ast) = 0; - virtual void visit(TemplateNestedNameSpecifierAST* ast) = 0; + virtual void visit(GlobalNestedNameSpecifierAST* ast); + virtual void visit(SimpleNestedNameSpecifierAST* ast); + virtual void visit(DecltypeNestedNameSpecifierAST* ast); + virtual void visit(TemplateNestedNameSpecifierAST* ast); // FunctionBodyAST - virtual void visit(DefaultFunctionBodyAST* ast) = 0; - virtual void visit(CompoundStatementFunctionBodyAST* ast) = 0; - virtual void visit(TryStatementFunctionBodyAST* ast) = 0; - virtual void visit(DeleteFunctionBodyAST* ast) = 0; + virtual void visit(DefaultFunctionBodyAST* ast); + virtual void visit(CompoundStatementFunctionBodyAST* ast); + virtual void visit(TryStatementFunctionBodyAST* ast); + virtual void visit(DeleteFunctionBodyAST* ast); // TemplateArgumentAST - virtual void visit(TypeTemplateArgumentAST* ast) = 0; - virtual void visit(ExpressionTemplateArgumentAST* ast) = 0; + virtual void visit(TypeTemplateArgumentAST* ast); + virtual void visit(ExpressionTemplateArgumentAST* ast); // ExceptionSpecifierAST - virtual void visit(ThrowExceptionSpecifierAST* ast) = 0; - virtual void visit(NoexceptSpecifierAST* ast) = 0; + virtual void visit(ThrowExceptionSpecifierAST* ast); + virtual void visit(NoexceptSpecifierAST* ast); // RequirementAST - virtual void visit(SimpleRequirementAST* ast) = 0; - virtual void visit(CompoundRequirementAST* ast) = 0; - virtual void visit(TypeRequirementAST* ast) = 0; - virtual void visit(NestedRequirementAST* ast) = 0; + virtual void visit(SimpleRequirementAST* ast); + virtual void visit(CompoundRequirementAST* ast); + virtual void visit(TypeRequirementAST* ast); + virtual void visit(NestedRequirementAST* ast); // NewInitializerAST - virtual void visit(NewParenInitializerAST* ast) = 0; - virtual void visit(NewBracedInitializerAST* ast) = 0; + virtual void visit(NewParenInitializerAST* ast); + virtual void visit(NewBracedInitializerAST* ast); // MemInitializerAST - virtual void visit(ParenMemInitializerAST* ast) = 0; - virtual void visit(BracedMemInitializerAST* ast) = 0; + virtual void visit(ParenMemInitializerAST* ast); + virtual void visit(BracedMemInitializerAST* ast); // LambdaCaptureAST - virtual void visit(ThisLambdaCaptureAST* ast) = 0; - virtual void visit(DerefThisLambdaCaptureAST* ast) = 0; - virtual void visit(SimpleLambdaCaptureAST* ast) = 0; - virtual void visit(RefLambdaCaptureAST* ast) = 0; - virtual void visit(RefInitLambdaCaptureAST* ast) = 0; - virtual void visit(InitLambdaCaptureAST* ast) = 0; + virtual void visit(ThisLambdaCaptureAST* ast); + virtual void visit(DerefThisLambdaCaptureAST* ast); + virtual void visit(SimpleLambdaCaptureAST* ast); + virtual void visit(RefLambdaCaptureAST* ast); + virtual void visit(RefInitLambdaCaptureAST* ast); + virtual void visit(InitLambdaCaptureAST* ast); // ExceptionDeclarationAST - virtual void visit(EllipsisExceptionDeclarationAST* ast) = 0; - virtual void visit(TypeExceptionDeclarationAST* ast) = 0; + virtual void visit(EllipsisExceptionDeclarationAST* ast); + virtual void visit(TypeExceptionDeclarationAST* ast); // AttributeSpecifierAST - virtual void visit(CxxAttributeAST* ast) = 0; - virtual void visit(GccAttributeAST* ast) = 0; - virtual void visit(AlignasAttributeAST* ast) = 0; - virtual void visit(AlignasTypeAttributeAST* ast) = 0; - virtual void visit(AsmAttributeAST* ast) = 0; + virtual void visit(CxxAttributeAST* ast); + virtual void visit(GccAttributeAST* ast); + virtual void visit(AlignasAttributeAST* ast); + virtual void visit(AlignasTypeAttributeAST* ast); + virtual void visit(AsmAttributeAST* ast); // AttributeTokenAST - virtual void visit(ScopedAttributeTokenAST* ast) = 0; - virtual void visit(SimpleAttributeTokenAST* ast) = 0; + virtual void visit(ScopedAttributeTokenAST* ast); + virtual void visit(SimpleAttributeTokenAST* ast); }; } // namespace cxx diff --git a/src/parser/cxx/binder.cc b/src/parser/cxx/binder.cc index 725f1000..71dfc3b2 100644 --- a/src/parser/cxx/binder.cc +++ b/src/parser/cxx/binder.cc @@ -55,11 +55,13 @@ void Binder::setReportErrors(bool reportErrors) { void Binder::error(SourceLocation loc, std::string message) { if (!reportErrors_) return; + if (!unit_->config().checkTypes) return; unit_->error(loc, std::move(message)); } void Binder::warning(SourceLocation loc, std::string message) { if (!reportErrors_) return; + if (!unit_->config().checkTypes) return; unit_->warning(loc, std::move(message)); } @@ -161,7 +163,10 @@ void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs) { classSymbol->setIsUnion(isUnion); classSymbol->setName(className); classSymbol->setTemplateParameters(currentTemplateParameters()); + classSymbol->setTemplateDeclaration(declSpecs.templateHead); declaringScope()->addSymbol(classSymbol); + + classSymbol->setDeclaration(ast); } ast->symbol = classSymbol; @@ -234,6 +239,12 @@ void Binder::bind(ClassSpecifierAST* ast, DeclSpecs& declSpecs) { } } + classSymbol->setDeclaration(ast); + + if (declSpecs.templateHead) { + classSymbol->setTemplateDeclaration(declSpecs.templateHead); + } + classSymbol->setFinal(ast->isFinal); ast->symbol = classSymbol; diff --git a/src/parser/cxx/binder.h b/src/parser/cxx/binder.h index 31e082d3..28bdf7ed 100644 --- a/src/parser/cxx/binder.h +++ b/src/parser/cxx/binder.h @@ -157,7 +157,7 @@ class Binder { TranslationUnit* unit_ = nullptr; Scope* scope_ = nullptr; bool inTemplate_ = false; - bool reportErrors_ = false; + bool reportErrors_ = true; }; } // namespace cxx diff --git a/src/parser/cxx/control.cc b/src/parser/cxx/control.cc index 950a3b1f..44e0a64e 100644 --- a/src/parser/cxx/control.cc +++ b/src/parser/cxx/control.cc @@ -143,6 +143,7 @@ struct Control::Private { std::forward_list variableSymbols; std::forward_list fieldSymbols; std::forward_list parameterSymbols; + std::forward_list parameterPackSymbols; std::forward_list typeParameterSymbols; std::forward_list nonTypeParameterSymbols; std::forward_list templateTypeParameterSymbols; @@ -592,6 +593,13 @@ auto Control::newParameterSymbol(Scope* enclosingScope, SourceLocation loc) return symbol; } +auto Control::newParameterPackSymbol(Scope* enclosingScope, SourceLocation loc) + -> ParameterPackSymbol* { + auto symbol = &d->parameterPackSymbols.emplace_front(enclosingScope); + symbol->setLocation(loc); + return symbol; +} + auto Control::newTypeParameterSymbol(Scope* enclosingScope, SourceLocation loc) -> TypeParameterSymbol* { auto symbol = &d->typeParameterSymbols.emplace_front(enclosingScope); diff --git a/src/parser/cxx/control.h b/src/parser/cxx/control.h index 68be55ce..bcf516c7 100644 --- a/src/parser/cxx/control.h +++ b/src/parser/cxx/control.h @@ -202,6 +202,9 @@ class Control { [[nodiscard]] auto newParameterSymbol(Scope* enclosingScope, SourceLocation sourceLocation) -> ParameterSymbol*; + [[nodiscard]] auto newParameterPackSymbol(Scope* enclosingScope, + SourceLocation sourceLocation) + -> ParameterPackSymbol*; [[nodiscard]] auto newTypeParameterSymbol(Scope* enclosingScope, SourceLocation sourceLocation) -> TypeParameterSymbol*; diff --git a/src/parser/cxx/decl.cc b/src/parser/cxx/decl.cc index bf8e9c8f..3794bb39 100644 --- a/src/parser/cxx/decl.cc +++ b/src/parser/cxx/decl.cc @@ -334,7 +334,24 @@ struct GetDeclaratorType { return getDeclaratorType(declarator, type); } -Decl::Decl(const DeclSpecs& specs) : specs{specs} {} +[[nodiscard]] auto getDeclaratorId(DeclaratorAST* declarator) + -> IdDeclaratorAST* { + if (!declarator) return nullptr; + + if (auto id = ast_cast(declarator->coreDeclarator)) { + return id; + } + + if (auto nested = ast_cast(declarator->coreDeclarator)) { + return getDeclaratorId(nested->declarator); + } + + return nullptr; +} + +Decl::Decl(const DeclSpecs& specs, DeclaratorAST* declarator) : specs{specs} { + declaratorId = getDeclaratorId(declarator); +} auto Decl::location() const -> SourceLocation { if (declaratorId) return declaratorId->firstSourceLocation(); diff --git a/src/parser/cxx/decl.h b/src/parser/cxx/decl.h index b87e0713..1b5b922d 100644 --- a/src/parser/cxx/decl.h +++ b/src/parser/cxx/decl.h @@ -33,7 +33,7 @@ class Decl { IdDeclaratorAST* declaratorId = nullptr; bool isPack = false; - explicit Decl(const DeclSpecs& specs); + explicit Decl(const DeclSpecs& specs, DeclaratorAST* declarator = nullptr); [[nodiscard]] auto location() const -> SourceLocation; [[nodiscard]] auto getName() const -> const Name*; @@ -41,6 +41,9 @@ class Decl { [[nodiscard]] auto getScope() const -> Scope*; }; +[[nodiscard]] auto getDeclaratorId(DeclaratorAST* declarator) + -> IdDeclaratorAST*; + [[nodiscard]] auto getFunctionPrototype(DeclaratorAST* declarator) -> FunctionDeclaratorChunkAST*; diff --git a/src/parser/cxx/decl_specs.h b/src/parser/cxx/decl_specs.h index b38c1dba..3ca346b9 100644 --- a/src/parser/cxx/decl_specs.h +++ b/src/parser/cxx/decl_specs.h @@ -49,6 +49,7 @@ class DeclSpecs { ASTRewriter* rewriter = nullptr; TranslationUnit* unit = nullptr; + TemplateDeclarationAST* templateHead = nullptr; const Type* type = nullptr; SpecifierAST* typeSpecifier = nullptr; diff --git a/src/parser/cxx/external_name_encoder.cc b/src/parser/cxx/external_name_encoder.cc index bded7dca..f477e5eb 100644 --- a/src/parser/cxx/external_name_encoder.cc +++ b/src/parser/cxx/external_name_encoder.cc @@ -156,6 +156,8 @@ struct ExternalNameEncoder::SymbolVisitor { void operator()(ParameterSymbol* symbol) {} + void operator()(ParameterPackSymbol* symbol) {} + void operator()(EnumeratorSymbol* symbol) {} void operator()(FunctionParametersSymbol* symbol) {} diff --git a/src/parser/cxx/flatbuffers/ast_decoder.cc b/src/parser/cxx/flatbuffers/ast_decoder.cc index fd7c3617..970c7699 100644 --- a/src/parser/cxx/flatbuffers/ast_decoder.cc +++ b/src/parser/cxx/flatbuffers/ast_decoder.cc @@ -2924,6 +2924,7 @@ auto ASTDecoder::decodeBaseSpecifier(const io::BaseSpecifier* node) ast->templateLoc = SourceLocation(node->template_loc()); ast->unqualifiedId = decodeUnqualifiedId(node->unqualified_id(), node->unqualified_id_type()); + ast->ellipsisLoc = SourceLocation(node->ellipsis_loc()); ast->accessSpecifier = static_cast(node->access_specifier()); return ast; } diff --git a/src/parser/cxx/flatbuffers/ast_encoder.cc b/src/parser/cxx/flatbuffers/ast_encoder.cc index 7447b951..8496feba 100644 --- a/src/parser/cxx/flatbuffers/ast_encoder.cc +++ b/src/parser/cxx/flatbuffers/ast_encoder.cc @@ -3262,6 +3262,7 @@ void ASTEncoder::visit(BaseSpecifierAST* ast) { builder.add_unqualified_id(unqualifiedId); builder.add_unqualified_id_type( static_cast(unqualifiedIdType)); + builder.add_ellipsis_loc(ast->ellipsisLoc.index()); builder.add_access_specifier( static_cast(ast->accessSpecifier)); diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index aa832aa3..b1a7d83f 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -4024,6 +4024,7 @@ auto Parser::parse_simple_declaration(DeclarationAST*& yyast, if (parse_notypespec_function_definition(yyast, attributes, ctx)) return true; DeclSpecs specs{unit}; + specs.templateHead = templateHead; List* declSpecifierList = nullptr; auto lookat_decl_specifiers = [&] { @@ -7938,6 +7939,11 @@ auto Parser::parse_base_specifier_list(ClassSpecifierAST* ast) -> bool { match(TokenKind::T_DOT_DOT_DOT, ellipsisLoc); + if (baseSpecifier && ellipsisLoc) { + baseSpecifier->ellipsisLoc = ellipsisLoc; + baseSpecifier->isVariadic = true; + } + if (baseSpecifier && baseSpecifier->symbol) { ast->symbol->addBaseClass(baseSpecifier->symbol); } @@ -7956,6 +7962,11 @@ auto Parser::parse_base_specifier_list(ClassSpecifierAST* ast) -> bool { match(TokenKind::T_DOT_DOT_DOT, ellipsisLoc); + if (baseSpecifier && ellipsisLoc) { + baseSpecifier->ellipsisLoc = ellipsisLoc; + baseSpecifier->isVariadic = true; + } + if (baseSpecifier && baseSpecifier->symbol) { ast->symbol->addBaseClass(baseSpecifier->symbol); } diff --git a/src/parser/cxx/symbol_instantiation.cc b/src/parser/cxx/symbol_instantiation.cc index 16419b41..c97168ce 100644 --- a/src/parser/cxx/symbol_instantiation.cc +++ b/src/parser/cxx/symbol_instantiation.cc @@ -62,6 +62,7 @@ struct SymbolInstantiation::VisitSymbol { [[nodiscard]] auto operator()(VariableSymbol* symbol) -> Symbol*; [[nodiscard]] auto operator()(FieldSymbol* symbol) -> Symbol*; [[nodiscard]] auto operator()(ParameterSymbol* symbol) -> Symbol*; + [[nodiscard]] auto operator()(ParameterPackSymbol* symbol) -> Symbol*; [[nodiscard]] auto operator()(EnumeratorSymbol* symbol) -> Symbol*; [[nodiscard]] auto operator()(FunctionParametersSymbol* symbol) -> Symbol*; [[nodiscard]] auto operator()(TemplateParametersSymbol* symbol) -> Symbol*; @@ -312,6 +313,12 @@ auto SymbolInstantiation::VisitSymbol::operator()(ParameterSymbol* symbol) return newSymbol; } +auto SymbolInstantiation::VisitSymbol::operator()(ParameterPackSymbol* symbol) + -> Symbol* { + auto newSymbol = self.replacement(symbol); + return newSymbol; +} + auto SymbolInstantiation::VisitSymbol::operator()(EnumeratorSymbol* symbol) -> Symbol* { auto newSymbol = self.replacement(symbol); diff --git a/src/parser/cxx/symbol_printer.cc b/src/parser/cxx/symbol_printer.cc index c14675a0..dfc2fc9d 100644 --- a/src/parser/cxx/symbol_printer.cc +++ b/src/parser/cxx/symbol_printer.cc @@ -100,6 +100,11 @@ struct DumpSymbols { } else { out << std::format("{} {}\n", classKey, to_string(symbol->name())); } + for (auto baseClass : symbol->baseClasses()) { + ++depth; + visit(*this, baseClass); + --depth; + } if (!symbol->constructors().empty()) { ++depth; for (auto constructor : symbol->constructors()) { @@ -269,6 +274,12 @@ struct DumpSymbols { to_string(symbol->type(), symbol->name())); } + void operator()(ParameterPackSymbol* symbol) { + indent(); + out << std::format("parameter pack {}\n", + to_string(symbol->type(), symbol->name())); + } + void operator()(TypeParameterSymbol* symbol) { std::string_view pack = symbol->isParameterPack() ? "..." : ""; indent(); diff --git a/src/parser/cxx/symbols.cc b/src/parser/cxx/symbols.cc index 7fef6a22..034df194 100644 --- a/src/parser/cxx/symbols.cc +++ b/src/parser/cxx/symbols.cc @@ -215,6 +215,21 @@ auto ClassSymbol::hasBaseClass( return false; } +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::templateParameters() const -> TemplateParametersSymbol* { return templateInfo_ ? templateInfo_->templateParameters() : nullptr; } @@ -615,6 +630,19 @@ ParameterSymbol::ParameterSymbol(Scope* enclosingScope) ParameterSymbol::~ParameterSymbol() {} +ParameterPackSymbol::ParameterPackSymbol(Scope* enclosingScope) + : Symbol(Kind, enclosingScope) {} + +ParameterPackSymbol::~ParameterPackSymbol() {} + +auto ParameterPackSymbol::elements() const -> const std::vector& { + return elements_; +} + +void ParameterPackSymbol::addElement(Symbol* element) { + elements_.push_back(element); +} + TypeParameterSymbol::TypeParameterSymbol(Scope* enclosingScope) : Symbol(Kind, enclosingScope) {} diff --git a/src/parser/cxx/symbols.h b/src/parser/cxx/symbols.h index 1c7be357..d3c7386f 100644 --- a/src/parser/cxx/symbols.h +++ b/src/parser/cxx/symbols.h @@ -263,6 +263,12 @@ class ClassSymbol final : public ScopedSymbol { [[nodiscard]] auto flags() const -> std::uint32_t; void setFlags(std::uint32_t flags); + [[nodiscard]] auto declaration() const -> SpecifierAST*; + void setDeclaration(SpecifierAST* ast); + + [[nodiscard]] auto templateDeclaration() const -> TemplateDeclarationAST*; + void setTemplateDeclaration(TemplateDeclarationAST* templateDeclaration); + [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; void setTemplateParameters(TemplateParametersSymbol* templateParameters); @@ -311,6 +317,8 @@ class ClassSymbol final : public ScopedSymbol { std::vector baseClasses_; std::vector constructors_; std::unique_ptr> templateInfo_; + SpecifierAST* specifier_ = nullptr; + TemplateDeclarationAST* templateDeclaration_ = nullptr; ClassSymbol* templateClass_ = nullptr; std::size_t templateSepcializationIndex_ = 0; int sizeInBytes_ = 0; @@ -624,6 +632,20 @@ class ParameterSymbol final : public Symbol { ~ParameterSymbol() override; }; +class ParameterPackSymbol final : public Symbol { + public: + constexpr static auto Kind = SymbolKind::kParameterPack; + + explicit ParameterPackSymbol(Scope* enclosingScope); + ~ParameterPackSymbol() override; + + [[nodiscard]] auto elements() const -> const std::vector&; + void addElement(Symbol* element); + + private: + std::vector elements_; +}; + class TypeParameterSymbol final : public Symbol { public: constexpr static auto Kind = SymbolKind::kTypeParameter; diff --git a/src/parser/cxx/symbols_fwd.h b/src/parser/cxx/symbols_fwd.h index f644eed2..ac48c868 100644 --- a/src/parser/cxx/symbols_fwd.h +++ b/src/parser/cxx/symbols_fwd.h @@ -37,6 +37,7 @@ namespace cxx { V(Variable) \ V(Field) \ V(Parameter) \ + V(ParameterPack) \ V(Enumerator) \ V(FunctionParameters) \ V(TemplateParameters) \ diff --git a/tests/api_tests/test_rewriter.cc b/tests/api_tests/test_rewriter.cc index e72c13e5..8ff81297 100644 --- a/tests/api_tests/test_rewriter.cc +++ b/tests/api_tests/test_rewriter.cc @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -109,13 +110,12 @@ using Func1 = Func; auto func1 = source.getAs("Func1"); ASSERT_TRUE(func1 != nullptr); - std::cout << "Func1: " << to_string(func1->type()) << "\n"; - auto func1Type = type_cast(func1->type()); ASSERT_TRUE(func1Type != nullptr); auto templateId = ast_cast(func1Type->unqualifiedId()); ASSERT_TRUE(templateId != nullptr); + auto templateSym = symbol_cast(templateId->primaryTemplateSymbol); ASSERT_TRUE(templateSym != nullptr); @@ -128,6 +128,7 @@ using Func1 = Func; getTemplateBodyAs( templateSym->templateDeclaration()), templateArguments); + ASSERT_EQ(to_string(funcInstance->typeId->type), "void (int, const float&)"); } @@ -145,6 +146,7 @@ constexpr int y = c<123 * 2>; auto y = source.getAs("y"); ASSERT_TRUE(y != nullptr); + auto yinit = ast_cast(y->initializer())->expression; ASSERT_TRUE(yinit != nullptr); @@ -160,6 +162,7 @@ constexpr int y = c<123 * 2>; auto templateSym = symbol_cast(templateId->primaryTemplateSymbol); ASSERT_TRUE(templateSym != nullptr); + auto templateDecl = getTemplateBodyAs( templateSym->templateDeclaration()); ASSERT_TRUE(templateDecl != nullptr); @@ -173,9 +176,149 @@ constexpr int y = c<123 * 2>; auto decl = instance->initDeclaratorList->value; ASSERT_TRUE(decl != nullptr); + auto init = ast_cast(decl->initializer); ASSERT_TRUE(init != nullptr); + auto value = interp.evaluate(init->expression); ASSERT_TRUE(value.has_value()); + ASSERT_EQ(std::visit(ArithmeticCast{}, *value), 123 * 2 + 321 + 123 * 2); } + +TEST(Rewriter, Pack) { + auto source = R"( +template +const auto S = (... + (xs * xs)); + +const auto N = S<0, 1, 2>; +)"_cxx_no_templates; + + ASTInterpreter interp{&source.unit}; + + auto control = source.control(); + + auto S = source.getAs("S"); + ASSERT_TRUE(S != nullptr); + + auto N = source.getAs("N"); + ASSERT_TRUE(N != nullptr); + auto Ninit = ast_cast(N->initializer())->expression; + ASSERT_TRUE(Ninit != nullptr); + + auto idExpr = ast_cast(Ninit); + ASSERT_TRUE(idExpr != nullptr); + + auto templateId = ast_cast(idExpr->unqualifiedId); + ASSERT_TRUE(templateId != nullptr); + ASSERT_EQ(templateId->primaryTemplateSymbol, S); + + auto parameterPack = control->newParameterPackSymbol(nullptr, {}); + + for (auto arg : ListView{templateId->templateArgumentList}) { + auto exprArg = ast_cast(arg); + ASSERT_TRUE(exprArg != nullptr); + + auto expr = exprArg->expression; + auto element = control->newVariableSymbol(nullptr, {}); + element->setInitializer(expr); + element->setType(control->add_const(expr->type)); + parameterPack->addElement(element); + } + + ASSERT_EQ(parameterPack->elements().size(), 3); + + std::vector arguments; + arguments.push_back(parameterPack); + + auto templateDecl = + getTemplateBodyAs(S->templateDeclaration()); + ASSERT_TRUE(templateDecl != nullptr); + + auto instance = substitute(source, templateDecl, arguments); + ASSERT_TRUE(instance != nullptr); + + auto decl_to_string = [&](DeclarationAST* ast) { + std::ostringstream os; + ASTPrettyPrinter printer{&source.unit, os}; + printer(ast); + return os.str(); + }; + + ASSERT_EQ(decl_to_string(instance), + "const auto S =(0 * 0) +(1 * 1) +(2 * 2);"); + + auto eq = ast_cast( + instance->initDeclaratorList->value->initializer); + ASSERT_TRUE(eq != nullptr); + + const auto value = interp.evaluate(eq->expression); + ASSERT_TRUE(value.has_value()); + ASSERT_EQ(std::visit(ArithmeticCast{}, *value), 0 * 0 + 1 * 1 + 2 * 2); +} + +TEST(Rewriter, Class) { + auto source = R"( +struct Base { + int x; +}; + +template +struct Pair : Base { + T1 first; + T2 second; + auto operator=(const Pair& other) -> Pair&; +}; + +using Pair1 = Pair; + +)"_cxx_no_templates; + + auto control = source.control(); + + auto pair = source.getAs("Pair"); + ASSERT_TRUE(pair != nullptr); + + ASSERT_TRUE(pair->declaration() != nullptr); + + auto classDecl = ast_cast(pair->declaration()); + ASSERT_TRUE(classDecl != nullptr); + + auto templateDecl = pair->templateDeclaration(); + ASSERT_TRUE(templateDecl != nullptr); + + auto pair1 = source.getAs("Pair1"); + ASSERT_TRUE(pair1 != nullptr); + + auto pair1Type = type_cast(pair1->type()); + ASSERT_TRUE(pair1Type != nullptr); + + auto templateId = ast_cast(pair1Type->unqualifiedId()); + ASSERT_TRUE(templateId != nullptr); + + auto templateArguments = make_substitution(&source.unit, templateDecl, + templateId->templateArgumentList); + + auto instance = substitute(source, classDecl, templateArguments); + ASSERT_TRUE(instance != nullptr); + + auto classDeclInstance = ast_cast(instance); + ASSERT_TRUE(classDeclInstance != nullptr); + + auto classInstance = classDeclInstance->symbol; + + ASSERT_TRUE(classInstance != nullptr); + + std::ostringstream os; + dump(os, classDeclInstance->symbol); + + ASSERT_EQ(os.str(), R"(class Pair + base class Base + field int first + field float* second + function ::Pair& operator =(const ::Pair&) +)"); + + ASSERT_EQ(classInstance->sizeInBytes(), 12); + ASSERT_EQ(classInstance->alignment(), 4); +} diff --git a/tests/api_tests/test_utils.h b/tests/api_tests/test_utils.h index 4ef6179c..0a6a4740 100644 --- a/tests/api_tests/test_utils.h +++ b/tests/api_tests/test_utils.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -40,10 +41,16 @@ inline auto dump_symbol(Symbol* symbol) -> std::string { } struct Source { + std::unique_ptr memoryLayout; DiagnosticsClient diagnosticsClient; TranslationUnit unit{&diagnosticsClient}; explicit Source(std::string_view source, bool templateInstantiation = true) { + // default to wasm32 memory layout + memoryLayout = std::make_unique(32); + + unit.control()->setMemoryLayout(memoryLayout.get()); + unit.setSource(std::string(source), ""); unit.parse({ diff --git a/tests/unit_tests/sema/member_access_02.cc b/tests/unit_tests/sema/member_access_02.cc index d8c451f4..cc959630 100644 --- a/tests/unit_tests/sema/member_access_02.cc +++ b/tests/unit_tests/sema/member_access_02.cc @@ -38,7 +38,10 @@ auto main() -> int { static_assert(__is_same(decltype(px->s_value), int)); int i; - W w{i, i}; + + // clang-format off + W w{i, i}; // expected-warning {{untyped expression of kind 'braced-init-list'}} + // clang-format on static_assert(__is_lvalue_reference(decltype(w.r))); static_assert(__is_same(decltype(w.r), int&)); @@ -49,7 +52,10 @@ auto main() -> int { static_assert(__is_same(decltype((w.const_k)), const int&)); static_assert(__is_same(decltype((w.k)), int&)); - const W cw{i, i}; + // clang-format off + const W cw{i, i}; // expected-warning {{untyped expression of kind 'braced-init-list'}} + // clang-format on + static_assert(__is_same(decltype(cw.const_k), const int)); static_assert(__is_same(decltype(cw.k), int)); diff --git a/tests/unit_tests/sema/using_decl_01.cc b/tests/unit_tests/sema/using_decl_01.cc index ae46f04e..31b2fab5 100644 --- a/tests/unit_tests/sema/using_decl_01.cc +++ b/tests/unit_tests/sema/using_decl_01.cc @@ -36,9 +36,9 @@ auto main() -> int { // CHECK-NEXT: function operator bool() const // CHECK-NEXT: function void f() // CHECK-NEXT: class Derived +// CHECK-NEXT: base class Base // CHECK-NEXT: using operator bool() const // CHECK-NEXT: using void f() // CHECK-NEXT: function int main() // CHECK-NEXT: block // CHECK-NEXT: using decltype(nullptr) nullptr_t -