From 9e96b6a6bf6659d3a2a3ca443a8283be7596cc14 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 14 Mar 2025 20:50:10 +0100 Subject: [PATCH 1/3] Make the AST rewriter available to DeclSpec Signed-off-by: Roberto Raggi --- .../cxx-gen-ast/src/new_ast_rewriter_cc.ts | 73 +- .../cxx-gen-ast/src/new_ast_rewriter_h.ts | 37 +- src/parser/cxx/ast_rewriter.cc | 1170 +++++++---------- src/parser/cxx/ast_rewriter.h | 16 + src/parser/cxx/decl_specs.cc | 4 + src/parser/cxx/decl_specs.h | 6 +- 6 files changed, 593 insertions(+), 713 deletions(-) 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 a7dc6ef4..7fa60112 100644 --- a/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts +++ b/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts @@ -25,7 +25,6 @@ import * as fs from "fs"; export function new_ast_rewriter_cc({ ast, - opName, opHeader, output, }: { @@ -61,16 +60,19 @@ export function new_ast_rewriter_cc({ const className = chopAST(base); emit(); emit(` struct ASTRewriter::${className}Visitor {`); - emit(` ${opName}& rewrite;`); + 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; }` ); nodes.forEach(({ name }) => { emit(); @@ -88,10 +90,7 @@ export function new_ast_rewriter_cc({ emit(`auto _ = Binder::ScopeGuard(&rewrite.binder_); if (ast->${blockSymbol.name}) { - copy->${blockSymbol.name} = control()->newBlockSymbol(rewrite.binder_.scope(), - ast->${blockSymbol.name}->location()); - - rewrite.binder_.setScope(copy->${blockSymbol.name}); + copy->${blockSymbol.name} = rewrite.binder_.enterBlock(ast->${blockSymbol.name}->location()); } `); } @@ -116,36 +115,35 @@ export function new_ast_rewriter_cc({ // check the base type has a context that must be passed switch (m.type) { case "SpecifierAST": - emit(` DeclSpecs ${m.name}Ctx{translationUnit()};`); + emit(` auto ${m.name}Ctx = DeclSpecs{rewriter()};`); break; default: break; } // switch - emit(` if (auto it = ast->${m.name}) {`); - emit(` auto out = ©->${m.name};`); - - emit(` for (auto node : ListView{ast->${m.name}}) {`); + emit( + `for (auto ${m.name} = ©->${m.name}; auto node : ListView{ast->${m.name}}) {` + ); switch (m.type) { case "InitDeclaratorAST": - emit( - ` auto value = ${visitor}(node, declSpecifierListCtx);` - ); + emit(`auto value = ${visitor}(node, declSpecifierListCtx);`); break; default: - emit(` auto value = ${visitor}(node);`); + emit(`auto value = ${visitor}(node);`); break; } // switch if (isBase(m.type)) { - emit(`*out = make_list_node(arena(), value);`); + emit(`*${m.name} = make_list_node(arena(), value);`); } else { - emit(`*out = make_list_node(arena(), ast_cast<${m.type}>(value));`); + emit( + `*${m.name} = make_list_node(arena(), ast_cast<${m.type}>(value));` + ); } - emit(` out = &(*out)->next;`); + emit(`${m.name} = &(*${m.name})->next;`); // update the context if needed switch (m.type) { @@ -158,7 +156,6 @@ export function new_ast_rewriter_cc({ } // switch emit(` }`); - emit(` }`); emit(); break; } @@ -180,7 +177,7 @@ export function new_ast_rewriter_cc({ switch (base) { case "ExpressionAST": - emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); + emit(`auto ASTRewriter::operator()(${base}* ast) -> ${base}* {`); emit(` if (!ast) return {};`); emit(` auto expr = visit(${chopAST(base)}Visitor{*this}, ast);`); emit(` if (expr) typeChecker_->check(expr);`); @@ -189,7 +186,7 @@ export function new_ast_rewriter_cc({ break; case "SpecifierAST": - emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); + emit(`auto ASTRewriter::operator()(${base}* ast) -> ${base}* {`); emit(` if (!ast) return {};`); emit(` auto specifier = visit(${chopAST(base)}Visitor{*this}, ast);`); emit(` return specifier;`); @@ -197,7 +194,7 @@ export function new_ast_rewriter_cc({ break; default: - emit(`auto ${opName}::operator()(${base}* ast) -> ${base}* {`); + emit(`auto ASTRewriter::operator()(${base}* ast) -> ${base}* {`); emit(` if (!ast) return {};`); emit(` return visit(${chopAST(base)}Visitor{*this}, ast);`); emit(`}`); @@ -210,11 +207,11 @@ export function new_ast_rewriter_cc({ switch (name) { case "InitDeclaratorAST": emit( - `auto ${opName}::operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}* {` + `auto ASTRewriter::operator()(${name}* ast, const DeclSpecs& declSpecs) -> ${name}* {` ); break; default: - emit(`auto ${opName}::operator()(${name}* ast) -> ${name}* {`); + emit(`auto ASTRewriter::operator()(${name}* ast) -> ${name}* {`); break; } // switch @@ -235,7 +232,7 @@ export function new_ast_rewriter_cc({ nodes.forEach(({ name, members }) => { emit(); emit( - `auto ${opName}::${className}Visitor::operator()(${name}* ast) -> ${base}* {` + `auto ASTRewriter::${className}Visitor::operator()(${name}* ast) -> ${base}* {` ); emit(` auto copy = make_node<${name}>(arena());`); emit(); @@ -266,21 +263,29 @@ export function new_ast_rewriter_cc({ namespace cxx { -${opName}::${opName}(TypeChecker* typeChcker, +ASTRewriter::ASTRewriter(TypeChecker* typeChcker, const std::vector& templateArguments) : typeChecker_(typeChcker) , unit_(typeChcker->translationUnit()) , templateArguments_(templateArguments) , binder_(typeChcker->translationUnit()) {} -${opName}::~${opName}() {} +ASTRewriter::~ASTRewriter() {} + +auto ASTRewriter::control() const -> Control* { + return unit_->control(); +} + +auto ASTRewriter::arena() const -> Arena* { + return unit_->arena(); +} -auto ${opName}::control() const -> Control* { - return unit_->control(); +auto ASTRewriter::restrictedToDeclarations() const -> bool { + return restrictedToDeclarations_; } -auto ${opName}::arena() const -> Arena* { - return unit_->arena(); +void ASTRewriter::setRestrictedToDeclarations(bool restrictedToDeclarations) { + restrictedToDeclarations_ = restrictedToDeclarations; } ${code.join("\n")} 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 8839ffa2..fc82748f 100644 --- a/packages/cxx-gen-ast/src/new_ast_rewriter_h.ts +++ b/packages/cxx-gen-ast/src/new_ast_rewriter_h.ts @@ -25,7 +25,6 @@ import * as fs from "fs"; export function new_ast_rewriter_h({ ast, - opName, output, }: { ast: AST; @@ -90,23 +89,39 @@ class TypeChecker; class Control; class Arena; -class ${opName} { +class ASTRewriter { public: - explicit ${opName}(TypeChecker* typeChecker, const std::vector& templateArguments); - ~${opName}(); + explicit ASTRewriter(TypeChecker* typeChecker, const std::vector& templateArguments); + ~ASTRewriter(); - [[nodiscard]] auto translationUnit() const -> TranslationUnit* { return unit_; } + [[nodiscard]] auto translationUnit() const -> TranslationUnit* { return unit_; } - [[nodiscard]] auto control() const -> Control*; - [[nodiscard]] auto arena() const -> Arena*; + [[nodiscard]] const std::vector& templateArguments() const { + return templateArguments_; + } + + [[nodiscard]] auto typeChecker() const -> TypeChecker* { + return typeChecker_; + } + + [[nodiscard]] auto binder() -> Binder& { return binder_; } + + [[nodiscard]] auto control() const -> Control*; + [[nodiscard]] auto arena() const -> Arena*; + + [[nodiscard]] auto restrictedToDeclarations() const -> bool; + void setRestrictedToDeclarations(bool restrictedToDeclarations); ${code.join("\n")} private: - TypeChecker* typeChecker_ = nullptr; - const std::vector& templateArguments_; - TranslationUnit* unit_ = nullptr; - Binder binder_; + [[nodiscard]] auto rewriter() -> ASTRewriter* { return this; } + + TypeChecker* typeChecker_ = nullptr; + const std::vector& templateArguments_; + TranslationUnit* unit_ = nullptr; + Binder binder_; + bool restrictedToDeclarations_ = false; }; } // namespace cxx diff --git a/src/parser/cxx/ast_rewriter.cc b/src/parser/cxx/ast_rewriter.cc index 6dd02df1..c8371b10 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -46,6 +46,14 @@ auto ASTRewriter::control() const -> Control* { return unit_->control(); } auto ASTRewriter::arena() const -> Arena* { return unit_->arena(); } +auto ASTRewriter::restrictedToDeclarations() const -> bool { + return restrictedToDeclarations_; +} + +void ASTRewriter::setRestrictedToDeclarations(bool restrictedToDeclarations) { + restrictedToDeclarations_ = restrictedToDeclarations; +} + struct ASTRewriter::UnitVisitor { ASTRewriter& rewrite; [[nodiscard]] auto translationUnit() const -> TranslationUnit* { @@ -54,6 +62,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 operator()(TranslationUnitAST* ast) -> UnitAST*; @@ -68,6 +77,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 operator()(SimpleDeclarationAST* ast) -> DeclarationAST*; @@ -147,6 +157,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 operator()(LabeledStatementAST* ast) -> StatementAST*; @@ -196,6 +207,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 operator()(GeneratedLiteralExpressionAST* ast) -> ExpressionAST*; @@ -345,6 +357,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 operator()(TemplateTypeParameterAST* ast) -> TemplateParameterAST*; @@ -367,6 +380,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 operator()(GeneratedTypeSpecifierAST* ast) -> SpecifierAST*; @@ -454,6 +468,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 operator()(PointerOperatorAST* ast) -> PtrOperatorAST*; @@ -470,6 +485,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 operator()(BitfieldDeclaratorAST* ast) -> CoreDeclaratorAST*; @@ -489,6 +505,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 operator()(FunctionDeclaratorChunkAST* ast) -> DeclaratorChunkAST*; @@ -505,6 +522,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 operator()(NameIdAST* ast) -> UnqualifiedIdAST*; @@ -537,6 +555,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 operator()(GlobalNestedNameSpecifierAST* ast) -> NestedNameSpecifierAST*; @@ -559,6 +578,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 operator()(DefaultFunctionBodyAST* ast) -> FunctionBodyAST*; @@ -580,6 +600,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 operator()(TypeTemplateArgumentAST* ast) -> TemplateArgumentAST*; @@ -596,6 +617,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 operator()(ThrowExceptionSpecifierAST* ast) -> ExceptionSpecifierAST*; @@ -612,6 +634,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 operator()(SimpleRequirementAST* ast) -> RequirementAST*; @@ -630,6 +653,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 operator()(NewParenInitializerAST* ast) -> NewInitializerAST*; @@ -646,6 +670,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 operator()(ParenMemInitializerAST* ast) -> MemInitializerAST*; @@ -662,6 +687,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 operator()(ThisLambdaCaptureAST* ast) -> LambdaCaptureAST*; @@ -687,6 +713,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 operator()(EllipsisExceptionDeclarationAST* ast) -> ExceptionDeclarationAST*; @@ -703,6 +730,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 operator()(CxxAttributeAST* ast) -> AttributeSpecifierAST*; @@ -725,6 +753,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 operator()(ScopedAttributeTokenAST* ast) -> AttributeTokenAST*; @@ -870,13 +899,11 @@ auto ASTRewriter::operator()(GlobalModuleFragmentAST* ast) copy->moduleLoc = ast->moduleLoc; copy->semicolonLoc = ast->semicolonLoc; - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = operator()(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } return copy; @@ -893,13 +920,11 @@ auto ASTRewriter::operator()(PrivateModuleFragmentAST* ast) copy->privateLoc = ast->privateLoc; copy->semicolonLoc = ast->semicolonLoc; - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = operator()(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } return copy; @@ -916,13 +941,11 @@ auto ASTRewriter::operator()(ModuleDeclarationAST* ast) copy->moduleName = operator()(ast->moduleName); copy->modulePartition = operator()(ast->modulePartition); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = operator()(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->semicolonLoc = ast->semicolonLoc; @@ -997,24 +1020,20 @@ auto ASTRewriter::operator()(DeclaratorAST* ast) -> DeclaratorAST* { auto copy = make_node(arena()); - if (auto it = ast->ptrOpList) { - auto out = ©->ptrOpList; - for (auto node : ListView{ast->ptrOpList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto ptrOpList = ©->ptrOpList; + auto node : ListView{ast->ptrOpList}) { + auto value = operator()(node); + *ptrOpList = make_list_node(arena(), value); + ptrOpList = &(*ptrOpList)->next; } copy->coreDeclarator = operator()(ast->coreDeclarator); - if (auto it = ast->declaratorChunkList) { - auto out = ©->declaratorChunkList; - for (auto node : ListView{ast->declaratorChunkList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declaratorChunkList = ©->declaratorChunkList; + auto node : ListView{ast->declaratorChunkList}) { + auto value = operator()(node); + *declaratorChunkList = make_list_node(arena(), value); + declaratorChunkList = &(*declaratorChunkList)->next; } return copy; @@ -1042,13 +1061,11 @@ auto ASTRewriter::operator()(EnumeratorAST* ast) -> EnumeratorAST* { copy->identifierLoc = ast->identifierLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = operator()(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->equalLoc = ast->equalLoc; @@ -1064,15 +1081,13 @@ auto ASTRewriter::operator()(TypeIdAST* ast) -> TypeIdAST* { auto copy = make_node(arena()); - DeclSpecs typeSpecifierListCtx{translationUnit()}; - if (auto it = ast->typeSpecifierList) { - auto out = ©->typeSpecifierList; - for (auto node : ListView{ast->typeSpecifierList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - typeSpecifierListCtx.accept(value); - } + auto typeSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto typeSpecifierList = ©->typeSpecifierList; + auto node : ListView{ast->typeSpecifierList}) { + auto value = operator()(node); + *typeSpecifierList = make_list_node(arena(), value); + typeSpecifierList = &(*typeSpecifierList)->next; + typeSpecifierListCtx.accept(value); } copy->declarator = operator()(ast->declarator); @@ -1100,13 +1115,11 @@ auto ASTRewriter::operator()(BaseSpecifierAST* ast) -> BaseSpecifierAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = operator()(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->nestedNameSpecifier = operator()(ast->nestedNameSpecifier); @@ -1137,13 +1150,12 @@ auto ASTRewriter::operator()(ParameterDeclarationClauseAST* ast) auto copy = make_node(arena()); - if (auto it = ast->parameterDeclarationList) { - auto out = ©->parameterDeclarationList; - for (auto node : ListView{ast->parameterDeclarationList}) { - auto value = operator()(node); - *out = make_list_node(arena(), ast_cast(value)); - out = &(*out)->next; - } + for (auto parameterDeclarationList = ©->parameterDeclarationList; + auto node : ListView{ast->parameterDeclarationList}) { + auto value = operator()(node); + *parameterDeclarationList = + make_list_node(arena(), ast_cast(value)); + parameterDeclarationList = &(*parameterDeclarationList)->next; } copy->commaLoc = ast->commaLoc; @@ -1186,13 +1198,11 @@ auto ASTRewriter::operator()(TypeConstraintAST* ast) -> TypeConstraintAST* { copy->identifierLoc = ast->identifierLoc; copy->lessLoc = ast->lessLoc; - if (auto it = ast->templateArgumentList) { - auto out = ©->templateArgumentList; - for (auto node : ListView{ast->templateArgumentList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto templateArgumentList = ©->templateArgumentList; + auto node : ListView{ast->templateArgumentList}) { + auto value = operator()(node); + *templateArgumentList = make_list_node(arena(), value); + templateArgumentList = &(*templateArgumentList)->next; } copy->greaterLoc = ast->greaterLoc; @@ -1245,13 +1255,11 @@ auto ASTRewriter::operator()(NewPlacementAST* ast) -> NewPlacementAST* { copy->lparenLoc = ast->lparenLoc; - if (auto it = ast->expressionList) { - auto out = ©->expressionList; - for (auto node : ListView{ast->expressionList}) { - auto value = operator()(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto expressionList = ©->expressionList; + auto node : ListView{ast->expressionList}) { + auto value = operator()(node); + *expressionList = make_list_node(arena(), value); + expressionList = &(*expressionList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -1277,13 +1285,11 @@ auto ASTRewriter::operator()(NestedNamespaceSpecifierAST* ast) auto ASTRewriter::UnitVisitor::operator()(TranslationUnitAST* ast) -> UnitAST* { auto copy = make_node(arena()); - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = rewrite(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } return copy; @@ -1295,13 +1301,11 @@ auto ASTRewriter::UnitVisitor::operator()(ModuleUnitAST* ast) -> UnitAST* { copy->globalModuleFragment = rewrite(ast->globalModuleFragment); copy->moduleDeclaration = rewrite(ast->moduleDeclaration); - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = rewrite(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } copy->privateModuleFragment = rewrite(ast->privateModuleFragment); @@ -1313,33 +1317,27 @@ auto ASTRewriter::DeclarationVisitor::operator()(SimpleDeclarationAST* ast) -> DeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - DeclSpecs declSpecifierListCtx{translationUnit()}; - if (auto it = ast->declSpecifierList) { - auto out = ©->declSpecifierList; - for (auto node : ListView{ast->declSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - declSpecifierListCtx.accept(value); - } + auto declSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto declSpecifierList = ©->declSpecifierList; + auto node : ListView{ast->declSpecifierList}) { + auto value = rewrite(node); + *declSpecifierList = make_list_node(arena(), value); + declSpecifierList = &(*declSpecifierList)->next; + declSpecifierListCtx.accept(value); } - if (auto it = ast->initDeclaratorList) { - auto out = ©->initDeclaratorList; - for (auto node : ListView{ast->initDeclaratorList}) { - auto value = rewrite(node, declSpecifierListCtx); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto initDeclaratorList = ©->initDeclaratorList; + auto node : ListView{ast->initDeclaratorList}) { + auto value = rewrite(node, declSpecifierListCtx); + *initDeclaratorList = make_list_node(arena(), value); + initDeclaratorList = &(*initDeclaratorList)->next; } copy->requiresClause = rewrite(ast->requiresClause); @@ -1352,62 +1350,52 @@ auto ASTRewriter::DeclarationVisitor::operator()(AsmDeclarationAST* ast) -> DeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - if (auto it = ast->asmQualifierList) { - auto out = ©->asmQualifierList; - for (auto node : ListView{ast->asmQualifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), ast_cast(value)); - out = &(*out)->next; - } + for (auto asmQualifierList = ©->asmQualifierList; + auto node : ListView{ast->asmQualifierList}) { + auto value = rewrite(node); + *asmQualifierList = + make_list_node(arena(), ast_cast(value)); + asmQualifierList = &(*asmQualifierList)->next; } copy->asmLoc = ast->asmLoc; copy->lparenLoc = ast->lparenLoc; copy->literalLoc = ast->literalLoc; - if (auto it = ast->outputOperandList) { - auto out = ©->outputOperandList; - for (auto node : ListView{ast->outputOperandList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), ast_cast(value)); - out = &(*out)->next; - } + for (auto outputOperandList = ©->outputOperandList; + auto node : ListView{ast->outputOperandList}) { + auto value = rewrite(node); + *outputOperandList = + make_list_node(arena(), ast_cast(value)); + outputOperandList = &(*outputOperandList)->next; } - if (auto it = ast->inputOperandList) { - auto out = ©->inputOperandList; - for (auto node : ListView{ast->inputOperandList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), ast_cast(value)); - out = &(*out)->next; - } + for (auto inputOperandList = ©->inputOperandList; + auto node : ListView{ast->inputOperandList}) { + auto value = rewrite(node); + *inputOperandList = make_list_node(arena(), ast_cast(value)); + inputOperandList = &(*inputOperandList)->next; } - if (auto it = ast->clobberList) { - auto out = ©->clobberList; - for (auto node : ListView{ast->clobberList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), ast_cast(value)); - out = &(*out)->next; - } + for (auto clobberList = ©->clobberList; + auto node : ListView{ast->clobberList}) { + auto value = rewrite(node); + *clobberList = make_list_node(arena(), ast_cast(value)); + clobberList = &(*clobberList)->next; } - if (auto it = ast->gotoLabelList) { - auto out = ©->gotoLabelList; - for (auto node : ListView{ast->gotoLabelList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), ast_cast(value)); - out = &(*out)->next; - } + for (auto gotoLabelList = ©->gotoLabelList; + auto node : ListView{ast->gotoLabelList}) { + auto value = rewrite(node); + *gotoLabelList = make_list_node(arena(), ast_cast(value)); + gotoLabelList = &(*gotoLabelList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -1438,13 +1426,11 @@ auto ASTRewriter::DeclarationVisitor::operator()(UsingDeclarationAST* ast) copy->usingLoc = ast->usingLoc; - if (auto it = ast->usingDeclaratorList) { - auto out = ©->usingDeclaratorList; - for (auto node : ListView{ast->usingDeclaratorList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto usingDeclaratorList = ©->usingDeclaratorList; + auto node : ListView{ast->usingDeclaratorList}) { + auto value = rewrite(node); + *usingDeclaratorList = make_list_node(arena(), value); + usingDeclaratorList = &(*usingDeclaratorList)->next; } copy->semicolonLoc = ast->semicolonLoc; @@ -1468,13 +1454,11 @@ auto ASTRewriter::DeclarationVisitor::operator()(UsingDirectiveAST* ast) -> DeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->usingLoc = ast->usingLoc; @@ -1509,24 +1493,20 @@ auto ASTRewriter::DeclarationVisitor::operator()(AliasDeclarationAST* ast) copy->usingLoc = ast->usingLoc; copy->identifierLoc = ast->identifierLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->equalLoc = ast->equalLoc; - if (auto it = ast->gnuAttributeList) { - auto out = ©->gnuAttributeList; - for (auto node : ListView{ast->gnuAttributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto gnuAttributeList = ©->gnuAttributeList; + auto node : ListView{ast->gnuAttributeList}) { + auto value = rewrite(node); + *gnuAttributeList = make_list_node(arena(), value); + gnuAttributeList = &(*gnuAttributeList)->next; } copy->typeId = rewrite(ast->typeId); @@ -1544,28 +1524,24 @@ auto ASTRewriter::DeclarationVisitor::operator()(OpaqueEnumDeclarationAST* ast) copy->enumLoc = ast->enumLoc; copy->classLoc = ast->classLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); copy->unqualifiedId = ast_cast(rewrite(ast->unqualifiedId)); copy->colonLoc = ast->colonLoc; - DeclSpecs typeSpecifierListCtx{translationUnit()}; - if (auto it = ast->typeSpecifierList) { - auto out = ©->typeSpecifierList; - for (auto node : ListView{ast->typeSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - typeSpecifierListCtx.accept(value); - } + auto typeSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto typeSpecifierList = ©->typeSpecifierList; + auto node : ListView{ast->typeSpecifierList}) { + auto value = rewrite(node); + *typeSpecifierList = make_list_node(arena(), value); + typeSpecifierList = &(*typeSpecifierList)->next; + typeSpecifierListCtx.accept(value); } copy->emicolonLoc = ast->emicolonLoc; @@ -1577,24 +1553,20 @@ auto ASTRewriter::DeclarationVisitor::operator()(FunctionDefinitionAST* ast) -> DeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - DeclSpecs declSpecifierListCtx{translationUnit()}; - if (auto it = ast->declSpecifierList) { - auto out = ©->declSpecifierList; - for (auto node : ListView{ast->declSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - declSpecifierListCtx.accept(value); - } + auto declSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto declSpecifierList = ©->declSpecifierList; + auto node : ListView{ast->declSpecifierList}) { + auto value = rewrite(node); + *declSpecifierList = make_list_node(arena(), value); + declSpecifierList = &(*declSpecifierList)->next; + declSpecifierListCtx.accept(value); } copy->declarator = rewrite(ast->declarator); @@ -1612,13 +1584,11 @@ auto ASTRewriter::DeclarationVisitor::operator()(TemplateDeclarationAST* ast) copy->templateLoc = ast->templateLoc; copy->lessLoc = ast->lessLoc; - if (auto it = ast->templateParameterList) { - auto out = ©->templateParameterList; - for (auto node : ListView{ast->templateParameterList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto templateParameterList = ©->templateParameterList; + auto node : ListView{ast->templateParameterList}) { + auto value = rewrite(node); + *templateParameterList = make_list_node(arena(), value); + templateParameterList = &(*templateParameterList)->next; } copy->greaterLoc = ast->greaterLoc; @@ -1689,13 +1659,11 @@ auto ASTRewriter::DeclarationVisitor::operator()( copy->exportLoc = ast->exportLoc; copy->lbraceLoc = ast->lbraceLoc; - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = rewrite(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } copy->rbraceLoc = ast->rbraceLoc; @@ -1711,13 +1679,11 @@ auto ASTRewriter::DeclarationVisitor::operator()(LinkageSpecificationAST* ast) copy->stringliteralLoc = ast->stringliteralLoc; copy->lbraceLoc = ast->lbraceLoc; - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = rewrite(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } copy->rbraceLoc = ast->rbraceLoc; @@ -1733,44 +1699,36 @@ auto ASTRewriter::DeclarationVisitor::operator()(NamespaceDefinitionAST* ast) copy->inlineLoc = ast->inlineLoc; copy->namespaceLoc = ast->namespaceLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - if (auto it = ast->nestedNamespaceSpecifierList) { - auto out = ©->nestedNamespaceSpecifierList; - for (auto node : ListView{ast->nestedNamespaceSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto nestedNamespaceSpecifierList = ©->nestedNamespaceSpecifierList; + auto node : ListView{ast->nestedNamespaceSpecifierList}) { + auto value = rewrite(node); + *nestedNamespaceSpecifierList = make_list_node(arena(), value); + nestedNamespaceSpecifierList = &(*nestedNamespaceSpecifierList)->next; } copy->identifierLoc = ast->identifierLoc; - if (auto it = ast->extraAttributeList) { - auto out = ©->extraAttributeList; - for (auto node : ListView{ast->extraAttributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto extraAttributeList = ©->extraAttributeList; + auto node : ListView{ast->extraAttributeList}) { + auto value = rewrite(node); + *extraAttributeList = make_list_node(arena(), value); + extraAttributeList = &(*extraAttributeList)->next; } copy->lbraceLoc = ast->lbraceLoc; - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = rewrite(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } copy->rbraceLoc = ast->rbraceLoc; @@ -1793,13 +1751,11 @@ auto ASTRewriter::DeclarationVisitor::operator()(AttributeDeclarationAST* ast) -> DeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->semicolonLoc = ast->semicolonLoc; @@ -1814,13 +1770,11 @@ auto ASTRewriter::DeclarationVisitor::operator()( copy->importLoc = ast->importLoc; copy->importName = rewrite(ast->importName); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->semicolonLoc = ast->semicolonLoc; @@ -1832,26 +1786,22 @@ auto ASTRewriter::DeclarationVisitor::operator()(ParameterDeclarationAST* ast) -> DeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->thisLoc = ast->thisLoc; - DeclSpecs typeSpecifierListCtx{translationUnit()}; - if (auto it = ast->typeSpecifierList) { - auto out = ©->typeSpecifierList; - for (auto node : ListView{ast->typeSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - typeSpecifierListCtx.accept(value); - } + auto typeSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto typeSpecifierList = ©->typeSpecifierList; + auto node : ListView{ast->typeSpecifierList}) { + auto value = rewrite(node); + *typeSpecifierList = make_list_node(arena(), value); + typeSpecifierList = &(*typeSpecifierList)->next; + typeSpecifierListCtx.accept(value); } copy->declarator = rewrite(ast->declarator); @@ -1887,36 +1837,30 @@ auto ASTRewriter::DeclarationVisitor::operator()( StructuredBindingDeclarationAST* ast) -> DeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - DeclSpecs declSpecifierListCtx{translationUnit()}; - if (auto it = ast->declSpecifierList) { - auto out = ©->declSpecifierList; - for (auto node : ListView{ast->declSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - declSpecifierListCtx.accept(value); - } + auto declSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto declSpecifierList = ©->declSpecifierList; + auto node : ListView{ast->declSpecifierList}) { + auto value = rewrite(node); + *declSpecifierList = make_list_node(arena(), value); + declSpecifierList = &(*declSpecifierList)->next; + declSpecifierListCtx.accept(value); } copy->refQualifierLoc = ast->refQualifierLoc; copy->lbracketLoc = ast->lbracketLoc; - if (auto it = ast->bindingList) { - auto out = ©->bindingList; - for (auto node : ListView{ast->bindingList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), ast_cast(value)); - out = &(*out)->next; - } + for (auto bindingList = ©->bindingList; + auto node : ListView{ast->bindingList}) { + auto value = rewrite(node); + *bindingList = make_list_node(arena(), ast_cast(value)); + bindingList = &(*bindingList)->next; } copy->rbracketLoc = ast->rbracketLoc; @@ -2022,21 +1966,16 @@ auto ASTRewriter::StatementVisitor::operator()(CompoundStatementAST* ast) auto _ = Binder::ScopeGuard(&rewrite.binder_); if (ast->symbol) { - copy->symbol = control()->newBlockSymbol(rewrite.binder_.scope(), - ast->symbol->location()); - - rewrite.binder_.setScope(copy->symbol); + copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); } copy->lbraceLoc = ast->lbraceLoc; - if (auto it = ast->statementList) { - auto out = ©->statementList; - for (auto node : ListView{ast->statementList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto statementList = ©->statementList; + auto node : ListView{ast->statementList}) { + auto value = rewrite(node); + *statementList = make_list_node(arena(), value); + statementList = &(*statementList)->next; } copy->rbraceLoc = ast->rbraceLoc; @@ -2051,10 +1990,7 @@ auto ASTRewriter::StatementVisitor::operator()(IfStatementAST* ast) auto _ = Binder::ScopeGuard(&rewrite.binder_); if (ast->symbol) { - copy->symbol = control()->newBlockSymbol(rewrite.binder_.scope(), - ast->symbol->location()); - - rewrite.binder_.setScope(copy->symbol); + copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); } copy->ifLoc = ast->ifLoc; @@ -2092,10 +2028,7 @@ auto ASTRewriter::StatementVisitor::operator()(SwitchStatementAST* ast) auto _ = Binder::ScopeGuard(&rewrite.binder_); if (ast->symbol) { - copy->symbol = control()->newBlockSymbol(rewrite.binder_.scope(), - ast->symbol->location()); - - rewrite.binder_.setScope(copy->symbol); + copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); } copy->switchLoc = ast->switchLoc; @@ -2115,10 +2048,7 @@ auto ASTRewriter::StatementVisitor::operator()(WhileStatementAST* ast) auto _ = Binder::ScopeGuard(&rewrite.binder_); if (ast->symbol) { - copy->symbol = control()->newBlockSymbol(rewrite.binder_.scope(), - ast->symbol->location()); - - rewrite.binder_.setScope(copy->symbol); + copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); } copy->whileLoc = ast->whileLoc; @@ -2152,10 +2082,7 @@ auto ASTRewriter::StatementVisitor::operator()(ForRangeStatementAST* ast) auto _ = Binder::ScopeGuard(&rewrite.binder_); if (ast->symbol) { - copy->symbol = control()->newBlockSymbol(rewrite.binder_.scope(), - ast->symbol->location()); - - rewrite.binder_.setScope(copy->symbol); + copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); } copy->forLoc = ast->forLoc; @@ -2177,10 +2104,7 @@ auto ASTRewriter::StatementVisitor::operator()(ForStatementAST* ast) auto _ = Binder::ScopeGuard(&rewrite.binder_); if (ast->symbol) { - copy->symbol = control()->newBlockSymbol(rewrite.binder_.scope(), - ast->symbol->location()); - - rewrite.binder_.setScope(copy->symbol); + copy->symbol = rewrite.binder_.enterBlock(ast->symbol->location()); } copy->forLoc = ast->forLoc; @@ -2265,13 +2189,11 @@ auto ASTRewriter::StatementVisitor::operator()(TryBlockStatementAST* ast) copy->tryLoc = ast->tryLoc; copy->statement = ast_cast(rewrite(ast->statement)); - if (auto it = ast->handlerList) { - auto out = ©->handlerList; - for (auto node : ListView{ast->handlerList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto handlerList = ©->handlerList; + auto node : ListView{ast->handlerList}) { + auto value = rewrite(node); + *handlerList = make_list_node(arena(), value); + handlerList = &(*handlerList)->next; } return copy; @@ -2434,25 +2356,21 @@ auto ASTRewriter::ExpressionVisitor::operator()(LambdaExpressionAST* ast) copy->lbracketLoc = ast->lbracketLoc; copy->captureDefaultLoc = ast->captureDefaultLoc; - if (auto it = ast->captureList) { - auto out = ©->captureList; - for (auto node : ListView{ast->captureList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto captureList = ©->captureList; + auto node : ListView{ast->captureList}) { + auto value = rewrite(node); + *captureList = make_list_node(arena(), value); + captureList = &(*captureList)->next; } copy->rbracketLoc = ast->rbracketLoc; copy->lessLoc = ast->lessLoc; - if (auto it = ast->templateParameterList) { - auto out = ©->templateParameterList; - for (auto node : ListView{ast->templateParameterList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto templateParameterList = ©->templateParameterList; + auto node : ListView{ast->templateParameterList}) { + auto value = rewrite(node); + *templateParameterList = make_list_node(arena(), value); + templateParameterList = &(*templateParameterList)->next; } copy->greaterLoc = ast->greaterLoc; @@ -2461,33 +2379,27 @@ auto ASTRewriter::ExpressionVisitor::operator()(LambdaExpressionAST* ast) copy->parameterDeclarationClause = rewrite(ast->parameterDeclarationClause); copy->rparenLoc = ast->rparenLoc; - if (auto it = ast->gnuAtributeList) { - auto out = ©->gnuAtributeList; - for (auto node : ListView{ast->gnuAtributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto gnuAtributeList = ©->gnuAtributeList; + auto node : ListView{ast->gnuAtributeList}) { + auto value = rewrite(node); + *gnuAtributeList = make_list_node(arena(), value); + gnuAtributeList = &(*gnuAtributeList)->next; } - if (auto it = ast->lambdaSpecifierList) { - auto out = ©->lambdaSpecifierList; - for (auto node : ListView{ast->lambdaSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto lambdaSpecifierList = ©->lambdaSpecifierList; + auto node : ListView{ast->lambdaSpecifierList}) { + auto value = rewrite(node); + *lambdaSpecifierList = make_list_node(arena(), value); + lambdaSpecifierList = &(*lambdaSpecifierList)->next; } copy->exceptionSpecifier = rewrite(ast->exceptionSpecifier); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->trailingReturnType = rewrite(ast->trailingReturnType); @@ -2562,13 +2474,11 @@ auto ASTRewriter::ExpressionVisitor::operator()(RequiresExpressionAST* ast) copy->rparenLoc = ast->rparenLoc; copy->lbraceLoc = ast->lbraceLoc; - if (auto it = ast->requirementList) { - auto out = ©->requirementList; - for (auto node : ListView{ast->requirementList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto requirementList = ©->requirementList; + auto node : ListView{ast->requirementList}) { + auto value = rewrite(node); + *requirementList = make_list_node(arena(), value); + requirementList = &(*requirementList)->next; } copy->rbraceLoc = ast->rbraceLoc; @@ -2615,13 +2525,11 @@ auto ASTRewriter::ExpressionVisitor::operator()(CallExpressionAST* ast) copy->baseExpression = rewrite(ast->baseExpression); copy->lparenLoc = ast->lparenLoc; - if (auto it = ast->expressionList) { - auto out = ©->expressionList; - for (auto node : ListView{ast->expressionList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto expressionList = ©->expressionList; + auto node : ListView{ast->expressionList}) { + auto value = rewrite(node); + *expressionList = make_list_node(arena(), value); + expressionList = &(*expressionList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -2638,13 +2546,11 @@ auto ASTRewriter::ExpressionVisitor::operator()(TypeConstructionAST* ast) copy->typeSpecifier = rewrite(ast->typeSpecifier); copy->lparenLoc = ast->lparenLoc; - if (auto it = ast->expressionList) { - auto out = ©->expressionList; - for (auto node : ListView{ast->expressionList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto expressionList = ©->expressionList; + auto node : ListView{ast->expressionList}) { + auto value = rewrite(node); + *expressionList = make_list_node(arena(), value); + expressionList = &(*expressionList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -2970,15 +2876,13 @@ auto ASTRewriter::ExpressionVisitor::operator()(NewExpressionAST* ast) copy->newPlacement = rewrite(ast->newPlacement); copy->lparenLoc = ast->lparenLoc; - DeclSpecs typeSpecifierListCtx{translationUnit()}; - if (auto it = ast->typeSpecifierList) { - auto out = ©->typeSpecifierList; - for (auto node : ListView{ast->typeSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - typeSpecifierListCtx.accept(value); - } + auto typeSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto typeSpecifierList = ©->typeSpecifierList; + auto node : ListView{ast->typeSpecifierList}) { + auto value = rewrite(node); + *typeSpecifierList = make_list_node(arena(), value); + typeSpecifierList = &(*typeSpecifierList)->next; + typeSpecifierListCtx.accept(value); } copy->declarator = rewrite(ast->declarator); @@ -3131,13 +3035,11 @@ auto ASTRewriter::ExpressionVisitor::operator()(TypeTraitExpressionAST* ast) copy->typeTraitLoc = ast->typeTraitLoc; copy->lparenLoc = ast->lparenLoc; - if (auto it = ast->typeIdList) { - auto out = ©->typeIdList; - for (auto node : ListView{ast->typeIdList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto typeIdList = ©->typeIdList; + auto node : ListView{ast->typeIdList}) { + auto value = rewrite(node); + *typeIdList = make_list_node(arena(), value); + typeIdList = &(*typeIdList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -3153,24 +3055,20 @@ auto ASTRewriter::ExpressionVisitor::operator()(ConditionExpressionAST* ast) copy->valueCategory = ast->valueCategory; copy->type = ast->type; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - DeclSpecs declSpecifierListCtx{translationUnit()}; - if (auto it = ast->declSpecifierList) { - auto out = ©->declSpecifierList; - for (auto node : ListView{ast->declSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - declSpecifierListCtx.accept(value); - } + auto declSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto declSpecifierList = ©->declSpecifierList; + auto node : ListView{ast->declSpecifierList}) { + auto value = rewrite(node); + *declSpecifierList = make_list_node(arena(), value); + declSpecifierList = &(*declSpecifierList)->next; + declSpecifierListCtx.accept(value); } copy->declarator = rewrite(ast->declarator); @@ -3200,13 +3098,11 @@ auto ASTRewriter::ExpressionVisitor::operator()(BracedInitListAST* ast) copy->type = ast->type; copy->lbraceLoc = ast->lbraceLoc; - if (auto it = ast->expressionList) { - auto out = ©->expressionList; - for (auto node : ListView{ast->expressionList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto expressionList = ©->expressionList; + auto node : ListView{ast->expressionList}) { + auto value = rewrite(node); + *expressionList = make_list_node(arena(), value); + expressionList = &(*expressionList)->next; } copy->commaLoc = ast->commaLoc; @@ -3223,13 +3119,11 @@ auto ASTRewriter::ExpressionVisitor::operator()(ParenInitializerAST* ast) copy->type = ast->type; copy->lparenLoc = ast->lparenLoc; - if (auto it = ast->expressionList) { - auto out = ©->expressionList; - for (auto node : ListView{ast->expressionList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto expressionList = ©->expressionList; + auto node : ListView{ast->expressionList}) { + auto value = rewrite(node); + *expressionList = make_list_node(arena(), value); + expressionList = &(*expressionList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -3247,13 +3141,11 @@ auto ASTRewriter::TemplateParameterVisitor::operator()( copy->templateLoc = ast->templateLoc; copy->lessLoc = ast->lessLoc; - if (auto it = ast->templateParameterList) { - auto out = ©->templateParameterList; - for (auto node : ListView{ast->templateParameterList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto templateParameterList = ©->templateParameterList; + auto node : ListView{ast->templateParameterList}) { + auto value = rewrite(node); + *templateParameterList = make_list_node(arena(), value); + templateParameterList = &(*templateParameterList)->next; } copy->greaterLoc = ast->greaterLoc; @@ -3567,13 +3459,11 @@ auto ASTRewriter::SpecifierVisitor::operator()(ElaboratedTypeSpecifierAST* ast) copy->classLoc = ast->classLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); @@ -3655,40 +3545,34 @@ auto ASTRewriter::SpecifierVisitor::operator()(EnumSpecifierAST* ast) copy->enumLoc = ast->enumLoc; copy->classLoc = ast->classLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); copy->unqualifiedId = ast_cast(rewrite(ast->unqualifiedId)); copy->colonLoc = ast->colonLoc; - DeclSpecs typeSpecifierListCtx{translationUnit()}; - if (auto it = ast->typeSpecifierList) { - auto out = ©->typeSpecifierList; - for (auto node : ListView{ast->typeSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - typeSpecifierListCtx.accept(value); - } + auto typeSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto typeSpecifierList = ©->typeSpecifierList; + auto node : ListView{ast->typeSpecifierList}) { + auto value = rewrite(node); + *typeSpecifierList = make_list_node(arena(), value); + typeSpecifierList = &(*typeSpecifierList)->next; + typeSpecifierListCtx.accept(value); } copy->lbraceLoc = ast->lbraceLoc; copy->commaLoc = ast->commaLoc; - if (auto it = ast->enumeratorList) { - auto out = ©->enumeratorList; - for (auto node : ListView{ast->enumeratorList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto enumeratorList = ©->enumeratorList; + auto node : ListView{ast->enumeratorList}) { + auto value = rewrite(node); + *enumeratorList = make_list_node(arena(), value); + enumeratorList = &(*enumeratorList)->next; } copy->rbraceLoc = ast->rbraceLoc; @@ -3703,13 +3587,11 @@ auto ASTRewriter::SpecifierVisitor::operator()(ClassSpecifierAST* ast) copy->classLoc = ast->classLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); @@ -3717,24 +3599,20 @@ auto ASTRewriter::SpecifierVisitor::operator()(ClassSpecifierAST* ast) copy->finalLoc = ast->finalLoc; copy->colonLoc = ast->colonLoc; - if (auto it = ast->baseSpecifierList) { - auto out = ©->baseSpecifierList; - for (auto node : ListView{ast->baseSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto baseSpecifierList = ©->baseSpecifierList; + auto node : ListView{ast->baseSpecifierList}) { + auto value = rewrite(node); + *baseSpecifierList = make_list_node(arena(), value); + baseSpecifierList = &(*baseSpecifierList)->next; } copy->lbraceLoc = ast->lbraceLoc; - if (auto it = ast->declarationList) { - auto out = ©->declarationList; - for (auto node : ListView{ast->declarationList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto declarationList = ©->declarationList; + auto node : ListView{ast->declarationList}) { + auto value = rewrite(node); + *declarationList = make_list_node(arena(), value); + declarationList = &(*declarationList)->next; } copy->rbraceLoc = ast->rbraceLoc; @@ -3772,24 +3650,20 @@ auto ASTRewriter::PtrOperatorVisitor::operator()(PointerOperatorAST* ast) copy->starLoc = ast->starLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - DeclSpecs cvQualifierListCtx{translationUnit()}; - if (auto it = ast->cvQualifierList) { - auto out = ©->cvQualifierList; - for (auto node : ListView{ast->cvQualifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - cvQualifierListCtx.accept(value); - } + auto cvQualifierListCtx = DeclSpecs{rewriter()}; + for (auto cvQualifierList = ©->cvQualifierList; + auto node : ListView{ast->cvQualifierList}) { + auto value = rewrite(node); + *cvQualifierList = make_list_node(arena(), value); + cvQualifierList = &(*cvQualifierList)->next; + cvQualifierListCtx.accept(value); } return copy; @@ -3801,13 +3675,11 @@ auto ASTRewriter::PtrOperatorVisitor::operator()(ReferenceOperatorAST* ast) copy->refLoc = ast->refLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->refOp = ast->refOp; @@ -3822,24 +3694,20 @@ auto ASTRewriter::PtrOperatorVisitor::operator()(PtrToMemberOperatorAST* ast) copy->nestedNameSpecifier = rewrite(ast->nestedNameSpecifier); copy->starLoc = ast->starLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - DeclSpecs cvQualifierListCtx{translationUnit()}; - if (auto it = ast->cvQualifierList) { - auto out = ©->cvQualifierList; - for (auto node : ListView{ast->cvQualifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - cvQualifierListCtx.accept(value); - } + auto cvQualifierListCtx = DeclSpecs{rewriter()}; + for (auto cvQualifierList = ©->cvQualifierList; + auto node : ListView{ast->cvQualifierList}) { + auto value = rewrite(node); + *cvQualifierList = make_list_node(arena(), value); + cvQualifierList = &(*cvQualifierList)->next; + cvQualifierListCtx.accept(value); } return copy; @@ -3874,13 +3742,11 @@ auto ASTRewriter::CoreDeclaratorVisitor::operator()(IdDeclaratorAST* ast) copy->templateLoc = ast->templateLoc; copy->unqualifiedId = rewrite(ast->unqualifiedId); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->isTemplateIntroduced = ast->isTemplateIntroduced; @@ -3907,27 +3773,23 @@ auto ASTRewriter::DeclaratorChunkVisitor::operator()( copy->parameterDeclarationClause = rewrite(ast->parameterDeclarationClause); copy->rparenLoc = ast->rparenLoc; - DeclSpecs cvQualifierListCtx{translationUnit()}; - if (auto it = ast->cvQualifierList) { - auto out = ©->cvQualifierList; - for (auto node : ListView{ast->cvQualifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - cvQualifierListCtx.accept(value); - } + auto cvQualifierListCtx = DeclSpecs{rewriter()}; + for (auto cvQualifierList = ©->cvQualifierList; + auto node : ListView{ast->cvQualifierList}) { + auto value = rewrite(node); + *cvQualifierList = make_list_node(arena(), value); + cvQualifierList = &(*cvQualifierList)->next; + cvQualifierListCtx.accept(value); } copy->refLoc = ast->refLoc; copy->exceptionSpecifier = rewrite(ast->exceptionSpecifier); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->trailingReturnType = rewrite(ast->trailingReturnType); @@ -3946,13 +3808,11 @@ auto ASTRewriter::DeclaratorChunkVisitor::operator()( copy->expression = rewrite(ast->expression); copy->rbracketLoc = ast->rbracketLoc; - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } return copy; @@ -4031,13 +3891,11 @@ auto ASTRewriter::UnqualifiedIdVisitor::operator()(SimpleTemplateIdAST* ast) copy->identifierLoc = ast->identifierLoc; copy->lessLoc = ast->lessLoc; - if (auto it = ast->templateArgumentList) { - auto out = ©->templateArgumentList; - for (auto node : ListView{ast->templateArgumentList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto templateArgumentList = ©->templateArgumentList; + auto node : ListView{ast->templateArgumentList}) { + auto value = rewrite(node); + *templateArgumentList = make_list_node(arena(), value); + templateArgumentList = &(*templateArgumentList)->next; } copy->greaterLoc = ast->greaterLoc; @@ -4055,13 +3913,11 @@ auto ASTRewriter::UnqualifiedIdVisitor::operator()( ast_cast(rewrite(ast->literalOperatorId)); copy->lessLoc = ast->lessLoc; - if (auto it = ast->templateArgumentList) { - auto out = ©->templateArgumentList; - for (auto node : ListView{ast->templateArgumentList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto templateArgumentList = ©->templateArgumentList; + auto node : ListView{ast->templateArgumentList}) { + auto value = rewrite(node); + *templateArgumentList = make_list_node(arena(), value); + templateArgumentList = &(*templateArgumentList)->next; } copy->greaterLoc = ast->greaterLoc; @@ -4077,13 +3933,11 @@ auto ASTRewriter::UnqualifiedIdVisitor::operator()( ast_cast(rewrite(ast->operatorFunctionId)); copy->lessLoc = ast->lessLoc; - if (auto it = ast->templateArgumentList) { - auto out = ©->templateArgumentList; - for (auto node : ListView{ast->templateArgumentList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto templateArgumentList = ©->templateArgumentList; + auto node : ListView{ast->templateArgumentList}) { + auto value = rewrite(node); + *templateArgumentList = make_list_node(arena(), value); + templateArgumentList = &(*templateArgumentList)->next; } copy->greaterLoc = ast->greaterLoc; @@ -4157,13 +4011,11 @@ auto ASTRewriter::FunctionBodyVisitor::operator()( copy->colonLoc = ast->colonLoc; - if (auto it = ast->memInitializerList) { - auto out = ©->memInitializerList; - for (auto node : ListView{ast->memInitializerList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto memInitializerList = ©->memInitializerList; + auto node : ListView{ast->memInitializerList}) { + auto value = rewrite(node); + *memInitializerList = make_list_node(arena(), value); + memInitializerList = &(*memInitializerList)->next; } copy->statement = ast_cast(rewrite(ast->statement)); @@ -4178,24 +4030,20 @@ auto ASTRewriter::FunctionBodyVisitor::operator()( copy->tryLoc = ast->tryLoc; copy->colonLoc = ast->colonLoc; - if (auto it = ast->memInitializerList) { - auto out = ©->memInitializerList; - for (auto node : ListView{ast->memInitializerList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto memInitializerList = ©->memInitializerList; + auto node : ListView{ast->memInitializerList}) { + auto value = rewrite(node); + *memInitializerList = make_list_node(arena(), value); + memInitializerList = &(*memInitializerList)->next; } copy->statement = ast_cast(rewrite(ast->statement)); - if (auto it = ast->handlerList) { - auto out = ©->handlerList; - for (auto node : ListView{ast->handlerList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto handlerList = ©->handlerList; + auto node : ListView{ast->handlerList}) { + auto value = rewrite(node); + *handlerList = make_list_node(arena(), value); + handlerList = &(*handlerList)->next; } return copy; @@ -4307,13 +4155,11 @@ auto ASTRewriter::NewInitializerVisitor::operator()(NewParenInitializerAST* ast) copy->lparenLoc = ast->lparenLoc; - if (auto it = ast->expressionList) { - auto out = ©->expressionList; - for (auto node : ListView{ast->expressionList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto expressionList = ©->expressionList; + auto node : ListView{ast->expressionList}) { + auto value = rewrite(node); + *expressionList = make_list_node(arena(), value); + expressionList = &(*expressionList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -4339,13 +4185,11 @@ auto ASTRewriter::MemInitializerVisitor::operator()(ParenMemInitializerAST* ast) copy->unqualifiedId = rewrite(ast->unqualifiedId); copy->lparenLoc = ast->lparenLoc; - if (auto it = ast->expressionList) { - auto out = ©->expressionList; - for (auto node : ListView{ast->expressionList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto expressionList = ©->expressionList; + auto node : ListView{ast->expressionList}) { + auto value = rewrite(node); + *expressionList = make_list_node(arena(), value); + expressionList = &(*expressionList)->next; } copy->rparenLoc = ast->rparenLoc; @@ -4447,24 +4291,20 @@ auto ASTRewriter::ExceptionDeclarationVisitor::operator()( TypeExceptionDeclarationAST* ast) -> ExceptionDeclarationAST* { auto copy = make_node(arena()); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } - DeclSpecs typeSpecifierListCtx{translationUnit()}; - if (auto it = ast->typeSpecifierList) { - auto out = ©->typeSpecifierList; - for (auto node : ListView{ast->typeSpecifierList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - typeSpecifierListCtx.accept(value); - } + auto typeSpecifierListCtx = DeclSpecs{rewriter()}; + for (auto typeSpecifierList = ©->typeSpecifierList; + auto node : ListView{ast->typeSpecifierList}) { + auto value = rewrite(node); + *typeSpecifierList = make_list_node(arena(), value); + typeSpecifierList = &(*typeSpecifierList)->next; + typeSpecifierListCtx.accept(value); } copy->declarator = rewrite(ast->declarator); @@ -4480,13 +4320,11 @@ auto ASTRewriter::AttributeSpecifierVisitor::operator()(CxxAttributeAST* ast) copy->lbracket2Loc = ast->lbracket2Loc; copy->attributeUsingPrefix = rewrite(ast->attributeUsingPrefix); - if (auto it = ast->attributeList) { - auto out = ©->attributeList; - for (auto node : ListView{ast->attributeList}) { - auto value = rewrite(node); - *out = make_list_node(arena(), value); - out = &(*out)->next; - } + for (auto attributeList = ©->attributeList; + auto node : ListView{ast->attributeList}) { + auto value = rewrite(node); + *attributeList = make_list_node(arena(), value); + attributeList = &(*attributeList)->next; } copy->rbracketLoc = ast->rbracketLoc; diff --git a/src/parser/cxx/ast_rewriter.h b/src/parser/cxx/ast_rewriter.h index 8ae7c989..dcde5380 100644 --- a/src/parser/cxx/ast_rewriter.h +++ b/src/parser/cxx/ast_rewriter.h @@ -43,9 +43,22 @@ class ASTRewriter { return unit_; } + [[nodiscard]] const std::vector& templateArguments() const { + return templateArguments_; + } + + [[nodiscard]] auto typeChecker() const -> TypeChecker* { + return typeChecker_; + } + + [[nodiscard]] auto binder() -> Binder& { return binder_; } + [[nodiscard]] auto control() const -> Control*; [[nodiscard]] auto arena() const -> Arena*; + [[nodiscard]] auto restrictedToDeclarations() const -> bool; + void setRestrictedToDeclarations(bool restrictedToDeclarations); + // run on the base nodes [[nodiscard]] auto operator()(UnitAST* ast) -> UnitAST*; [[nodiscard]] auto operator()(DeclarationAST* ast) -> DeclarationAST*; @@ -136,10 +149,13 @@ class ASTRewriter { struct AttributeTokenVisitor; private: + [[nodiscard]] auto rewriter() -> ASTRewriter* { return this; } + TypeChecker* typeChecker_ = nullptr; const std::vector& templateArguments_; TranslationUnit* unit_ = nullptr; Binder binder_; + bool restrictedToDeclarations_ = false; }; } // namespace cxx diff --git a/src/parser/cxx/decl_specs.cc b/src/parser/cxx/decl_specs.cc index bd773f4a..074d709e 100644 --- a/src/parser/cxx/decl_specs.cc +++ b/src/parser/cxx/decl_specs.cc @@ -22,6 +22,7 @@ // cxx #include +#include #include #include #include @@ -340,6 +341,9 @@ void DeclSpecs::Visitor::operator()(SplicerTypeSpecifierAST* ast) { DeclSpecs::DeclSpecs(TranslationUnit* unit) : unit(unit) {} +DeclSpecs::DeclSpecs(ASTRewriter* rewriter) + : rewriter(rewriter), unit(rewriter->translationUnit()) {} + auto DeclSpecs::control() const -> Control* { return unit->control(); } void DeclSpecs::accept(SpecifierAST* specifier) { diff --git a/src/parser/cxx/decl_specs.h b/src/parser/cxx/decl_specs.h index 6b311f1d..b38c1dba 100644 --- a/src/parser/cxx/decl_specs.h +++ b/src/parser/cxx/decl_specs.h @@ -27,12 +27,14 @@ namespace cxx { class Control; class TranslationUnit; +class ASTRewriter; class DeclSpecs { struct Visitor; public: explicit DeclSpecs(TranslationUnit* unit = nullptr); + explicit DeclSpecs(ASTRewriter* rewriter); [[nodiscard]] auto control() const -> Control*; [[nodiscard]] auto getType() const -> const Type*; @@ -45,11 +47,11 @@ class DeclSpecs { void accept(SpecifierAST* specifier); + ASTRewriter* rewriter = nullptr; + TranslationUnit* unit = nullptr; const Type* type = nullptr; SpecifierAST* typeSpecifier = nullptr; - TranslationUnit* unit; - bool isTypedef = false; bool isFriend = false; bool isConstexpr = false; From f43e32b9109dba66f0cfc900387d9fa888fe1c54 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 14 Mar 2025 22:23:53 +0100 Subject: [PATCH 2/3] Rewrite the type parameters --- .../cxx-gen-ast/src/new_ast_rewriter_cc.ts | 31 +++++- src/frontend/CMakeLists.txt | 7 +- src/parser/cxx/ast_rewriter.cc | 22 ++++- src/parser/cxx/decl_specs.cc | 15 +++ src/parser/cxx/parser.cc | 2 + src/parser/cxx/symbols.cc | 8 ++ src/parser/cxx/symbols.h | 4 + tests/api_tests/CMakeLists.txt | 9 +- tests/api_tests/test_rewriter.cc | 71 ++++++++++++++ tests/api_tests/test_substitution.cc | 60 +----------- tests/api_tests/test_utils.h | 97 +++++++++++++++++++ 11 files changed, 259 insertions(+), 67 deletions(-) create mode 100644 tests/api_tests/test_rewriter.cc create mode 100644 tests/api_tests/test_utils.h 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 7fa60112..cef8eb9c 100644 --- a/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts +++ b/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts @@ -95,16 +95,43 @@ export function new_ast_rewriter_cc({ `); } + let typeAttr: Member | undefined; + members.forEach((m) => { if (m === blockSymbol) return; + if (m === typeAttr) return; switch (m.kind) { case "node": { if (isBase(m.type)) { - emit(` copy->${m.name} = ${visitor}(ast->${m.name});`); + emit(`copy->${m.name} = ${visitor}(ast->${m.name});`); + + switch (m.type) { + case "DeclaratorAST": + const specsAttr = + members.find((m) => m.name == "typeSpecifierList")?.name ?? + members.find((m) => m.name == "declSpecifierList")?.name; + if (specsAttr) { + emit(); + emit( + `auto ${m.name}Type = getDeclaratorType(translationUnit(), copy->${m.name}, ${specsAttr}Ctx.getType());` + ); + + typeAttr = members.find( + (m) => m.kind === "attribute" && m.name === "type" + ); + + if (typeAttr) { + emit(`copy->${typeAttr.name} = ${m.name}Type;`); + } + } + break; + default: + break; + } // 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; diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index c655727b..36fbfd76 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -17,9 +17,12 @@ # 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. -aux_source_directory(cxx SOURCES) -add_executable(cxx ${SOURCES}) +add_executable(cxx + cxx/ast_printer.cc + cxx/frontend.cc + cxx/verify_diagnostics_client.cc +) target_link_libraries(cxx PRIVATE cxx-lsp) diff --git a/src/parser/cxx/ast_rewriter.cc b/src/parser/cxx/ast_rewriter.cc index c8371b10..847caac5 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -1091,7 +1091,10 @@ auto ASTRewriter::operator()(TypeIdAST* ast) -> TypeIdAST* { } copy->declarator = operator()(ast->declarator); - copy->type = ast->type; + + auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, + typeSpecifierListCtx.getType()); + copy->type = declaratorType; return copy; } @@ -1570,6 +1573,9 @@ auto ASTRewriter::DeclarationVisitor::operator()(FunctionDefinitionAST* ast) } copy->declarator = rewrite(ast->declarator); + + auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, + declSpecifierListCtx.getType()); copy->requiresClause = rewrite(ast->requiresClause); copy->functionBody = rewrite(ast->functionBody); copy->symbol = ast->symbol; @@ -1805,9 +1811,12 @@ auto ASTRewriter::DeclarationVisitor::operator()(ParameterDeclarationAST* ast) } copy->declarator = rewrite(ast->declarator); + + auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, + typeSpecifierListCtx.getType()); + copy->type = declaratorType; copy->equalLoc = ast->equalLoc; copy->expression = rewrite(ast->expression); - copy->type = ast->type; copy->identifier = ast->identifier; copy->isThisIntroduced = ast->isThisIntroduced; copy->isPack = ast->isPack; @@ -2886,6 +2895,9 @@ auto ASTRewriter::ExpressionVisitor::operator()(NewExpressionAST* ast) } copy->declarator = rewrite(ast->declarator); + + auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, + typeSpecifierListCtx.getType()); copy->rparenLoc = ast->rparenLoc; copy->newInitalizer = rewrite(ast->newInitalizer); @@ -3072,6 +3084,9 @@ auto ASTRewriter::ExpressionVisitor::operator()(ConditionExpressionAST* ast) } copy->declarator = rewrite(ast->declarator); + + auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, + declSpecifierListCtx.getType()); copy->initializer = rewrite(ast->initializer); copy->symbol = ast->symbol; @@ -4309,6 +4324,9 @@ auto ASTRewriter::ExceptionDeclarationVisitor::operator()( copy->declarator = rewrite(ast->declarator); + auto declaratorType = getDeclaratorType(translationUnit(), copy->declarator, + typeSpecifierListCtx.getType()); + return copy; } diff --git a/src/parser/cxx/decl_specs.cc b/src/parser/cxx/decl_specs.cc index 074d709e..53cb9997 100644 --- a/src/parser/cxx/decl_specs.cc +++ b/src/parser/cxx/decl_specs.cc @@ -256,6 +256,21 @@ void DeclSpecs::Visitor::operator()(ComplexTypeSpecifierAST* ast) { void DeclSpecs::Visitor::operator()(NamedTypeSpecifierAST* ast) { specs.typeSpecifier = ast; + if (specs.rewriter) { + auto typeParameter = symbol_cast(ast->symbol); + const auto& args = specs.rewriter->templateArguments(); + + if (typeParameter && typeParameter->depth() == 0 && + typeParameter->index() < args.size()) { + auto index = typeParameter->index(); + + if (auto ty = std::get_if(&args[index])) { + specs.type = *ty; + return; + } + } + } + if (ast->symbol) specs.type = ast->symbol->type(); else diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 4a7ad862..8b54f1af 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -3813,6 +3813,8 @@ auto Parser::parse_alias_declaration(DeclarationAST*& yyast) -> bool { ast->semicolonLoc = semicolonLoc; ast->symbol = symbol; + ast->symbol->setDeclaration(ast); + return true; } diff --git a/src/parser/cxx/symbols.cc b/src/parser/cxx/symbols.cc index 708cd858..9a7ffc61 100644 --- a/src/parser/cxx/symbols.cc +++ b/src/parser/cxx/symbols.cc @@ -493,6 +493,14 @@ void TypeAliasSymbol::setTemplateParameters( templateParameters_ = templateParameters; } +auto TypeAliasSymbol::declaration() const -> AliasDeclarationAST* { + return declaration_; +} + +void TypeAliasSymbol::setDeclaration(AliasDeclarationAST* declaration) { + declaration_ = declaration; +} + VariableSymbol::VariableSymbol(Scope* enclosingScope) : Symbol(Kind, enclosingScope) {} diff --git a/src/parser/cxx/symbols.h b/src/parser/cxx/symbols.h index e80e835a..402b0a84 100644 --- a/src/parser/cxx/symbols.h +++ b/src/parser/cxx/symbols.h @@ -505,8 +505,12 @@ class TypeAliasSymbol final : public Symbol { [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; void setTemplateParameters(TemplateParametersSymbol* templateParameters); + [[nodiscard]] auto declaration() const -> AliasDeclarationAST*; + void setDeclaration(AliasDeclarationAST* declaration); + private: TemplateParametersSymbol* templateParameters_ = nullptr; + AliasDeclarationAST* declaration_ = nullptr; }; class VariableSymbol final : public Symbol { diff --git a/tests/api_tests/CMakeLists.txt b/tests/api_tests/CMakeLists.txt index f80daf57..a4ebd820 100644 --- a/tests/api_tests/CMakeLists.txt +++ b/tests/api_tests/CMakeLists.txt @@ -22,8 +22,13 @@ if (CMAKE_SYSTEM_NAME STREQUAL "WASI") return() endif() -aux_source_directory(. SOURCES) -add_executable(test_api ${SOURCES}) +add_executable(test_api + test_control.cc + test_external_names.cc + test_rewriter.cc + test_substitution.cc + test_type_printer.cc +) target_link_libraries(test_api GTest::gtest_main diff --git a/tests/api_tests/test_rewriter.cc b/tests/api_tests/test_rewriter.cc new file mode 100644 index 00000000..7e0b188d --- /dev/null +++ b/tests/api_tests/test_rewriter.cc @@ -0,0 +1,71 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "test_utils.h" + +using namespace cxx; + +template +auto subst(Source& source, Node* ast, std::vector args) { + auto control = source.control(); + TypeChecker typeChecker(&source.unit); + ASTRewriter rewrite{&typeChecker, args}; + return ast_cast(rewrite(ast)); +}; + +TEST(Rewriter, TypeAlias) { + auto source = R"( + template + using Ptr = const T*; + + template + using Func = void(T, U); + )"_cxx; + + auto control = source.control(); + + auto ptrTypeAlias = + subst(source, source.getAs("Ptr")->declaration(), + {control->getIntType()}); + + ASSERT_EQ(to_string(ptrTypeAlias->typeId->type), "const int*"); + + auto funcTypeAlias = + subst(source, source.getAs("Func")->declaration(), + {control->getIntType(), control->getFloatType()}); + + ASSERT_EQ(to_string(funcTypeAlias->typeId->type), "void (int, float)"); +} diff --git a/tests/api_tests/test_substitution.cc b/tests/api_tests/test_substitution.cc index 29403397..29e4da45 100644 --- a/tests/api_tests/test_substitution.cc +++ b/tests/api_tests/test_substitution.cc @@ -32,65 +32,7 @@ #include #include -namespace cxx { - -auto dump_symbol(Symbol* symbol) -> std::string { - std::ostringstream out; - out << symbol; - return out.str(); -} - -struct Source { - DiagnosticsClient diagnosticsClient; - TranslationUnit unit{&diagnosticsClient}; - - explicit Source(std::string_view source) { - unit.setSource(std::string(source), ""); - unit.parse({ - .checkTypes = true, - .fuzzyTemplateResolution = false, - .reflect = true, - }); - } - - auto control() -> Control* { return unit.control(); } - auto ast() -> UnitAST* { return unit.ast(); } - auto scope() -> Scope* { return unit.globalScope(); } - - auto get(std::string_view name) -> Symbol* { - Symbol* symbol = nullptr; - auto id = unit.control()->getIdentifier(name); - for (auto candidate : scope()->find(id)) { - if (symbol) return nullptr; - symbol = candidate; - } - return symbol; - } - - auto instantiate(std::string_view name, - const std::vector& arguments) -> Symbol* { - auto symbol = get(name); - return control()->instantiate(&unit, symbol, arguments); - } -}; - -auto operator""_cxx(const char* source, std::size_t size) -> Source { - return Source{std::string_view{source, size}}; -} - -struct LookupMember { - Source& source; - - auto operator()(Scope* scope, std::string_view name) -> Symbol* { - auto id = source.control()->getIdentifier(name); - for (auto candidate : scope->find(id)) { - return candidate; - } - return nullptr; - } -}; - -} // namespace cxx +#include "test_utils.h" using namespace cxx; diff --git a/tests/api_tests/test_utils.h b/tests/api_tests/test_utils.h new file mode 100644 index 00000000..3a16a984 --- /dev/null +++ b/tests/api_tests/test_utils.h @@ -0,0 +1,97 @@ +// Copyright (c) 2025 Roberto Raggi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace cxx { + +inline auto dump_symbol(Symbol* symbol) -> std::string { + std::ostringstream out; + out << symbol; + return out.str(); +} + +struct Source { + DiagnosticsClient diagnosticsClient; + TranslationUnit unit{&diagnosticsClient}; + + explicit Source(std::string_view source) { + unit.setSource(std::string(source), ""); + unit.parse({ + .checkTypes = true, + .fuzzyTemplateResolution = false, + .reflect = true, + }); + } + + auto control() -> Control* { return unit.control(); } + auto ast() -> UnitAST* { return unit.ast(); } + auto scope() -> Scope* { return unit.globalScope(); } + + auto get(std::string_view name) -> Symbol* { + Symbol* symbol = nullptr; + auto id = unit.control()->getIdentifier(name); + for (auto candidate : scope()->find(id)) { + if (symbol) return nullptr; + symbol = candidate; + } + return symbol; + } + + template + auto getAs(std::string_view name) -> S* { + auto symbol = get(name); + return symbol_cast(symbol); + } + + auto instantiate(std::string_view name, + const std::vector& arguments) -> Symbol* { + auto symbol = get(name); + return control()->instantiate(&unit, symbol, arguments); + } +}; + +inline auto operator""_cxx(const char* source, std::size_t size) -> Source { + return Source{std::string_view{source, size}}; +} + +struct LookupMember { + Source& source; + + auto operator()(Scope* scope, std::string_view name) -> Symbol* { + auto id = source.control()->getIdentifier(name); + for (auto candidate : scope->find(id)) { + return candidate; + } + return nullptr; + } +}; + +} // namespace cxx \ No newline at end of file From 182700f3f445f1aa92dc36bb9ba579961c502c4a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Sat, 15 Mar 2025 10:58:53 +0100 Subject: [PATCH 3/3] Rewrite non-type parameters --- .../cxx-gen-ast/src/new_ast_rewriter_cc.ts | 24 ++++++ src/parser/cxx/ast.h | 2 +- src/parser/cxx/ast_rewriter.cc | 21 +++++ src/parser/cxx/parser.cc | 83 ++++++++++++------- src/parser/cxx/parser.h | 47 +++++++---- src/parser/cxx/symbols.cc | 26 +++++- src/parser/cxx/symbols.h | 14 +++- tests/api_tests/test_rewriter.cc | 76 ++++++++++++++--- 8 files changed, 227 insertions(+), 66 deletions(-) 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 cef8eb9c..a8d4dc8c 100644 --- a/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts +++ b/packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts @@ -261,6 +261,30 @@ export function new_ast_rewriter_cc({ emit( `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) { + cxx_runtime_error("expected initializer for non-type template parameter"); + } + + auto initializer = rewrite(*initializerPtr); + + if (auto eq = ast_cast(initializer)) { + return eq->expression; + } + + if (auto bracedInit = ast_cast(initializer)) { + if (bracedInit->expressionList && !bracedInit->expressionList->next) { + return bracedInit->expressionList->value; + } + } +} +`); + } emit(` auto copy = make_node<${name}>(arena());`); emit(); ast.baseMembers.get(base)?.forEach((m) => { diff --git a/src/parser/cxx/ast.h b/src/parser/cxx/ast.h index 5aaf06f0..9c0551b2 100644 --- a/src/parser/cxx/ast.h +++ b/src/parser/cxx/ast.h @@ -2120,7 +2120,7 @@ class ConditionExpressionAST final : public ExpressionAST { List* declSpecifierList = nullptr; DeclaratorAST* declarator = nullptr; ExpressionAST* initializer = nullptr; - Symbol* symbol = nullptr; + VariableSymbol* symbol = nullptr; void accept(ASTVisitor* visitor) override { visitor->visit(this); } diff --git a/src/parser/cxx/ast_rewriter.cc b/src/parser/cxx/ast_rewriter.cc index 847caac5..aca0e2e2 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -2343,6 +2343,27 @@ auto ASTRewriter::ExpressionVisitor::operator()(NestedExpressionAST* ast) auto ASTRewriter::ExpressionVisitor::operator()(IdExpressionAST* ast) -> ExpressionAST* { + 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) { + cxx_runtime_error("expected initializer for non-type template parameter"); + } + + auto initializer = rewrite(*initializerPtr); + + if (auto eq = ast_cast(initializer)) { + return eq->expression; + } + + if (auto bracedInit = ast_cast(initializer)) { + if (bracedInit->expressionList && !bracedInit->expressionList->next) { + return bracedInit->expressionList->value; + } + } + } + auto copy = make_node(arena()); copy->valueCategory = ast->valueCategory; diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 8b54f1af..e679519a 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -3715,12 +3715,14 @@ auto Parser::parse_maybe_module() -> bool { return is_module; } -auto Parser::parse_template_declaration_body(DeclarationAST*& yyast) -> bool { - if (parse_deduction_guide(yyast)) return true; - if (parse_export_declaration(yyast)) return true; - if (parse_opaque_enum_declaration(yyast)) return true; - if (parse_alias_declaration(yyast)) return true; - return parse_simple_declaration(yyast, BindingContext::kTemplate); +auto Parser::parse_template_declaration_body( + DeclarationAST*& yyast, TemplateDeclarationAST* templateHead) -> bool { + if (parse_deduction_guide(yyast, templateHead)) return true; + if (parse_export_declaration(yyast, templateHead)) return true; + if (parse_opaque_enum_declaration(yyast, templateHead)) return true; + if (parse_alias_declaration(yyast, templateHead)) return true; + return parse_simple_declaration(yyast, BindingContext::kTemplate, + templateHead); } auto Parser::parse_declaration(DeclarationAST*& yyast, BindingContext ctx) @@ -3755,7 +3757,9 @@ auto Parser::parse_block_declaration(DeclarationAST*& yyast, BindingContext ctx) return parse_simple_declaration(yyast, ctx); } -auto Parser::parse_alias_declaration(DeclarationAST*& yyast) -> bool { +auto Parser::parse_alias_declaration(DeclarationAST*& yyast, + TemplateDeclarationAST* templateHead) + -> bool { SourceLocation usingLoc; SourceLocation identifierLoc; const Identifier* identifier = nullptr; @@ -3795,6 +3799,7 @@ auto Parser::parse_alias_declaration(DeclarationAST*& yyast) -> bool { expect(TokenKind::T_SEMICOLON, semicolonLoc); auto symbol = binder_.declareTypeAlias(identifierLoc, typeId); + symbol->setTemplateDeclaration(templateHead); if (is_template(symbol)) { mark_maybe_template_name(identifier); @@ -3813,8 +3818,6 @@ auto Parser::parse_alias_declaration(DeclarationAST*& yyast) -> bool { ast->semicolonLoc = semicolonLoc; ast->symbol = symbol; - ast->symbol->setDeclaration(ast); - return true; } @@ -3919,7 +3922,7 @@ auto Parser::parse_notypespec_function_definition( auto Parser::parse_type_or_forward_declaration( DeclarationAST*& yyast, List* attributes, List* declSpecifierList, const DeclSpecs& specs, - BindingContext ctx) -> bool { + BindingContext ctx, TemplateDeclarationAST* templateHead) -> bool { if (ctx == BindingContext::kInitStatement) return false; LookaheadParser lookahead{this}; @@ -3995,7 +3998,9 @@ auto Parser::parse_structured_binding(DeclarationAST*& yyast, } auto Parser::parse_simple_declaration(DeclarationAST*& yyast, - BindingContext ctx) -> bool { + BindingContext ctx, + TemplateDeclarationAST* templateHead) + -> bool { SourceLocation extensionLoc; match(TokenKind::T___EXTENSION__, extensionLoc); @@ -4035,22 +4040,21 @@ auto Parser::parse_simple_declaration(DeclarationAST*& yyast, if (!lookat_decl_specifiers()) return false; if (parse_type_or_forward_declaration(yyast, attributes, declSpecifierList, - specs, ctx)) + specs, ctx, templateHead)) return true; - if (parse_structured_binding(yyast, attributes, declSpecifierList, specs, - ctx)) + if (!templateHead && parse_structured_binding(yyast, attributes, + declSpecifierList, specs, ctx)) return true; return parse_simple_declaration(yyast, attributes, declSpecifierList, specs, - ctx); + ctx, templateHead); } -auto Parser::parse_simple_declaration(DeclarationAST*& yyast, - List* attributes, - List* declSpecifierList, - const DeclSpecs& specs, - BindingContext ctx) -> bool { +auto Parser::parse_simple_declaration( + DeclarationAST*& yyast, List* attributes, + List* declSpecifierList, const DeclSpecs& specs, + BindingContext ctx, TemplateDeclarationAST* templateHead) -> bool { DeclaratorAST* declarator = nullptr; Decl decl{specs}; if (!parse_declarator(declarator, decl)) return false; @@ -4136,7 +4140,8 @@ auto Parser::parse_simple_declaration(DeclarationAST*& yyast, auto declIt = &initDeclaratorList; InitDeclaratorAST* initDeclarator = nullptr; - if (!parse_init_declarator(initDeclarator, declarator, decl, ctx)) + if (!parse_init_declarator(initDeclarator, declarator, decl, ctx, + templateHead)) return false; if (ctx == BindingContext::kTemplate) { @@ -4152,7 +4157,8 @@ auto Parser::parse_simple_declaration(DeclarationAST*& yyast, while (match(TokenKind::T_COMMA, commaLoc)) { InitDeclaratorAST* initDeclarator = nullptr; - if (!parse_init_declarator(initDeclarator, specs, ctx)) return false; + if (!parse_init_declarator(initDeclarator, specs, ctx, templateHead)) + return false; *declIt = make_list_node(pool_, initDeclarator); declIt = &(*declIt)->next; @@ -5206,7 +5212,8 @@ auto Parser::parse_placeholder_type_specifier(SpecifierAST*& yyast, } auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, - const DeclSpecs& specs, BindingContext ctx) + const DeclSpecs& specs, BindingContext ctx, + TemplateDeclarationAST* templateHead) -> bool { DeclaratorAST* declarator = nullptr; Decl decl{specs}; @@ -5217,7 +5224,9 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, DeclaratorAST* declarator, Decl& decl, - BindingContext ctx) -> bool { + BindingContext ctx, + TemplateDeclarationAST* templateHead) + -> bool { Symbol* symbol = nullptr; if (auto declId = decl.declaratorId; declId) { @@ -5229,6 +5238,7 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, symbol = functionSymbol; } else { auto variableSymbol = binder_.declareVariable(declarator, decl); + variableSymbol->setTemplateDeclaration(templateHead); symbol = variableSymbol; } } @@ -5249,6 +5259,10 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, ast->initializer = initializer; ast->symbol = symbol; + if (auto var = symbol_cast(ast->symbol)) { + var->setInitializer(initializer); + } + return true; } @@ -6186,7 +6200,9 @@ auto Parser::parse_enum_head_name(NestedNameSpecifierAST*& nestedNameSpecifier, return true; } -auto Parser::parse_opaque_enum_declaration(DeclarationAST*& yyast) -> bool { +auto Parser::parse_opaque_enum_declaration(DeclarationAST*& yyast, + TemplateDeclarationAST* templateHead) + -> bool { SourceLocation enumLoc; SourceLocation classLoc; List* attributes = nullptr; @@ -7255,7 +7271,9 @@ auto Parser::parse_module_partition(ModulePartitionAST*& yyast) -> bool { return true; } -auto Parser::parse_export_declaration(DeclarationAST*& yyast) -> bool { +auto Parser::parse_export_declaration(DeclarationAST*& yyast, + TemplateDeclarationAST* templateHead) + -> bool { SourceLocation exportLoc; if (!match(TokenKind::T_EXPORT, exportLoc)) return false; @@ -8284,7 +8302,8 @@ auto Parser::parse_literal_operator_id(LiteralOperatorIdAST*& yyast) -> bool { return true; } -auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast) +auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast, + TemplateDeclarationAST* templateHead) -> bool { if (!lookat(TokenKind::T_TEMPLATE, TokenKind::T_LESS)) return false; @@ -8294,6 +8313,8 @@ auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast) auto ast = make_node(pool_); yyast = ast; + if (!templateHead) templateHead = ast; + auto templateParametersSymbol = control_->newTemplateParametersSymbol(scope(), {}); ast->symbol = templateParametersSymbol; @@ -8312,7 +8333,7 @@ auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast) if (lookat(TokenKind::T_TEMPLATE, TokenKind::T_LESS)) { TemplateDeclarationAST* templateDeclaration = nullptr; - (void)parse_template_declaration(templateDeclaration); + (void)parse_template_declaration(templateDeclaration, templateHead); ast->declaration = templateDeclaration; return true; } @@ -8321,7 +8342,7 @@ auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast) return true; } - if (!parse_template_declaration_body(ast->declaration)) + if (!parse_template_declaration_body(ast->declaration, templateHead)) parse_error("expected a declaration"); return true; @@ -8910,7 +8931,9 @@ auto Parser::parse_constraint_expression(ExpressionAST*& yyast) -> bool { return parse_logical_or_expression(yyast, exprContext); } -auto Parser::parse_deduction_guide(DeclarationAST*& yyast) -> bool { +auto Parser::parse_deduction_guide(DeclarationAST*& yyast, + TemplateDeclarationAST* templateHead) + -> bool { SpecifierAST* explicitSpecifier = nullptr; SourceLocation identifierLoc; SourceLocation lparenLoc; diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index 542fff49..4c090474 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -365,15 +365,18 @@ class Parser final { -> bool; [[nodiscard]] auto parse_declaration_statement(StatementAST*& yyast) -> bool; [[nodiscard]] auto parse_maybe_module() -> bool; - [[nodiscard]] auto parse_template_declaration_body(DeclarationAST*& yyast) - -> bool; + [[nodiscard]] auto parse_template_declaration_body( + DeclarationAST*& yyast, TemplateDeclarationAST* templateHead) -> bool; [[nodiscard]] auto parse_declaration(DeclarationAST*& yyast, BindingContext ctx) -> bool; [[nodiscard]] auto parse_block_declaration(DeclarationAST*& yyast, BindingContext ctx) -> bool; - [[nodiscard]] auto parse_alias_declaration(DeclarationAST*& yyast) -> bool; - [[nodiscard]] auto parse_simple_declaration(DeclarationAST*& yyast, - BindingContext ctx) -> bool; + [[nodiscard]] auto parse_alias_declaration( + DeclarationAST*& yyast, TemplateDeclarationAST* templateHead = nullptr) + -> bool; + [[nodiscard]] auto parse_simple_declaration( + DeclarationAST*& yyast, BindingContext ctx, + TemplateDeclarationAST* templateHead = nullptr) -> bool; [[nodiscard]] auto parse_empty_or_attribute_declaration( DeclarationAST*& yyast, List* attributes, @@ -390,7 +393,8 @@ class Parser final { [[nodiscard]] auto parse_type_or_forward_declaration( DeclarationAST*& yyast, List* attributes, List* declSpecifierList, const DeclSpecs& specs, - BindingContext ctx) -> bool; + BindingContext ctx, TemplateDeclarationAST* templateHead = nullptr) + -> bool; [[nodiscard]] auto parse_structured_binding( DeclarationAST*& yyast, List* attributes, @@ -400,7 +404,8 @@ class Parser final { [[nodiscard]] auto parse_simple_declaration( DeclarationAST*& yyast, List* attributes, List* declSpecifierList, const DeclSpecs& specs, - BindingContext ctx) -> bool; + BindingContext ctx, TemplateDeclarationAST* templateHead = nullptr) + -> bool; [[nodiscard]] auto parse_static_assert_declaration(DeclarationAST*& yyast) -> bool; @@ -460,12 +465,12 @@ class Parser final { -> bool; [[nodiscard]] auto parse_placeholder_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) -> bool; - [[nodiscard]] auto parse_init_declarator(InitDeclaratorAST*& yyast, - const DeclSpecs& specs, - BindingContext ctx) -> bool; - [[nodiscard]] auto parse_init_declarator(InitDeclaratorAST*& yyast, - DeclaratorAST* declarator, - Decl& decl, BindingContext ctx) + [[nodiscard]] auto parse_init_declarator( + InitDeclaratorAST*& yyast, const DeclSpecs& specs, BindingContext ctx, + TemplateDeclarationAST* templateHead = nullptr) -> bool; + [[nodiscard]] auto parse_init_declarator( + InitDeclaratorAST*& yyast, DeclaratorAST* declarator, Decl& decl, + BindingContext ctx, TemplateDeclarationAST* templateHead = nullptr) -> bool; [[nodiscard]] auto parse_declarator_initializer( RequiresClauseAST*& requiresClause, ExpressionAST*& yyast) -> bool; @@ -540,7 +545,8 @@ class Parser final { DeclSpecs& specs) -> bool; [[nodiscard]] auto parse_enum_head_name( NestedNameSpecifierAST*& nestedNameSpecifier, NameIdAST*& name) -> bool; - [[nodiscard]] auto parse_opaque_enum_declaration(DeclarationAST*& yyast) + [[nodiscard]] auto parse_opaque_enum_declaration( + DeclarationAST*& yyast, TemplateDeclarationAST* templateHead = nullptr) -> bool; [[nodiscard]] auto parse_enum_key(SourceLocation& enumLoc, SourceLocation& classLoc) -> bool; @@ -612,7 +618,9 @@ class Parser final { -> bool; void parse_module_name(ModuleNameAST*& yyast); [[nodiscard]] auto parse_module_partition(ModulePartitionAST*& yyast) -> bool; - [[nodiscard]] auto parse_export_declaration(DeclarationAST*& yyast) -> bool; + [[nodiscard]] auto parse_export_declaration( + DeclarationAST*& yyast, TemplateDeclarationAST* templateHead = nullptr) + -> bool; [[nodiscard]] auto parse_maybe_import() -> bool; [[nodiscard]] auto parse_module_import_declaration(DeclarationAST*& yyast) -> bool; @@ -663,8 +671,9 @@ class Parser final { SourceLocation& closeLoc) -> bool; [[nodiscard]] auto parse_literal_operator_id(LiteralOperatorIdAST*& yyast) -> bool; - [[nodiscard]] auto parse_template_declaration(TemplateDeclarationAST*& yyast) - -> bool; + [[nodiscard]] auto parse_template_declaration( + TemplateDeclarationAST*& yyast, + TemplateDeclarationAST* templateHead = nullptr) -> bool; [[nodiscard]] auto parse_template_declaration( TemplateDeclarationAST*& yyast, std::vector& chain) -> bool; @@ -705,7 +714,9 @@ class Parser final { [[nodiscard]] auto parse_template_argument(TemplateArgumentAST*& yyast) -> bool; [[nodiscard]] auto parse_constraint_expression(ExpressionAST*& yyast) -> bool; - [[nodiscard]] auto parse_deduction_guide(DeclarationAST*& yyast) -> bool; + [[nodiscard]] auto parse_deduction_guide( + DeclarationAST*& yyast, TemplateDeclarationAST* templateHead = nullptr) + -> bool; [[nodiscard]] auto parse_concept_definition(DeclarationAST*& yyast) -> bool; [[nodiscard]] auto parse_splicer_specifier(SpecifierAST*& yyast, DeclSpecs& specs) -> bool; diff --git a/src/parser/cxx/symbols.cc b/src/parser/cxx/symbols.cc index 9a7ffc61..830633ee 100644 --- a/src/parser/cxx/symbols.cc +++ b/src/parser/cxx/symbols.cc @@ -493,12 +493,13 @@ void TypeAliasSymbol::setTemplateParameters( templateParameters_ = templateParameters; } -auto TypeAliasSymbol::declaration() const -> AliasDeclarationAST* { - return declaration_; +auto TypeAliasSymbol::templateDeclaration() const -> TemplateDeclarationAST* { + return templateDeclaration_; } -void TypeAliasSymbol::setDeclaration(AliasDeclarationAST* declaration) { - declaration_ = declaration; +void TypeAliasSymbol::setTemplateDeclaration( + TemplateDeclarationAST* declaration) { + templateDeclaration_ = declaration; } VariableSymbol::VariableSymbol(Scope* enclosingScope) @@ -545,6 +546,23 @@ auto VariableSymbol::isInline() const -> bool { return isInline_; } void VariableSymbol::setInline(bool isInline) { isInline_ = isInline; } +auto VariableSymbol::templateDeclaration() const -> TemplateDeclarationAST* { + return templateDeclaration_; +} + +void VariableSymbol::setTemplateDeclaration( + TemplateDeclarationAST* declaration) { + templateDeclaration_ = declaration; +} + +auto VariableSymbol::initializer() const -> ExpressionAST* { + return initializer_; +} + +void VariableSymbol::setInitializer(ExpressionAST* initializer) { + initializer_ = initializer; +} + FieldSymbol::FieldSymbol(Scope* enclosingScope) : Symbol(Kind, enclosingScope) {} diff --git a/src/parser/cxx/symbols.h b/src/parser/cxx/symbols.h index 402b0a84..c806a939 100644 --- a/src/parser/cxx/symbols.h +++ b/src/parser/cxx/symbols.h @@ -505,12 +505,12 @@ class TypeAliasSymbol final : public Symbol { [[nodiscard]] auto templateParameters() const -> TemplateParametersSymbol*; void setTemplateParameters(TemplateParametersSymbol* templateParameters); - [[nodiscard]] auto declaration() const -> AliasDeclarationAST*; - void setDeclaration(AliasDeclarationAST* declaration); + [[nodiscard]] auto templateDeclaration() const -> TemplateDeclarationAST*; + void setTemplateDeclaration(TemplateDeclarationAST* declaration); private: TemplateParametersSymbol* templateParameters_ = nullptr; - AliasDeclarationAST* declaration_ = nullptr; + TemplateDeclarationAST* templateDeclaration_ = nullptr; }; class VariableSymbol final : public Symbol { @@ -541,8 +541,16 @@ class VariableSymbol final : public Symbol { [[nodiscard]] auto isInline() const -> bool; void setInline(bool isInline); + [[nodiscard]] auto templateDeclaration() const -> TemplateDeclarationAST*; + void setTemplateDeclaration(TemplateDeclarationAST* declaration); + + [[nodiscard]] auto initializer() const -> ExpressionAST*; + void setInitializer(ExpressionAST*); + private: TemplateParametersSymbol* templateParameters_ = nullptr; + TemplateDeclarationAST* templateDeclaration_ = nullptr; + ExpressionAST* initializer_ = nullptr; union { std::uint32_t flags_{}; diff --git a/tests/api_tests/test_rewriter.cc b/tests/api_tests/test_rewriter.cc index 7e0b188d..b915ab1b 100644 --- a/tests/api_tests/test_rewriter.cc +++ b/tests/api_tests/test_rewriter.cc @@ -19,6 +19,7 @@ // SOFTWARE. #include +#include #include #include #include @@ -46,26 +47,81 @@ auto subst(Source& source, Node* ast, std::vector args) { return ast_cast(rewrite(ast)); }; +[[nodiscard]] auto getTemplateBody(TemplateDeclarationAST* ast) + -> DeclarationAST* { + if (auto nested = ast_cast(ast->declaration)) + return getTemplateBody(nested); + return ast->declaration; +} + +template +[[nodiscard]] auto getTemplateBodyAs(TemplateDeclarationAST* ast) -> Node* { + return ast_cast(getTemplateBody(ast)); +} + TEST(Rewriter, TypeAlias) { auto source = R"( - template - using Ptr = const T*; +template +using Ptr = const T*; - template - using Func = void(T, U); +template +using Func = void(T, const U&); )"_cxx; auto control = source.control(); - auto ptrTypeAlias = - subst(source, source.getAs("Ptr")->declaration(), + auto ptrInstance = + subst(source, + getTemplateBodyAs( + source.getAs("Ptr")->templateDeclaration()), {control->getIntType()}); - ASSERT_EQ(to_string(ptrTypeAlias->typeId->type), "const int*"); + ASSERT_EQ(to_string(ptrInstance->typeId->type), "const int*"); - auto funcTypeAlias = - subst(source, source.getAs("Func")->declaration(), + auto funcInstance = + subst(source, + getTemplateBodyAs( + source.getAs("Func")->templateDeclaration()), {control->getIntType(), control->getFloatType()}); + ASSERT_EQ(to_string(funcInstance->typeId->type), "void (int, const float&)"); +} + +TEST(Rewriter, Var) { + auto source = R"( +template +const int c = i + 321; + +constexpr int x = 123; + +)"_cxx; + + auto control = source.control(); + + auto c = source.getAs("c"); + ASSERT_TRUE(c != nullptr); + auto templateDeclaration = c->templateDeclaration(); + ASSERT_TRUE(templateDeclaration != nullptr); + + auto x = source.getAs("x"); + ASSERT_TRUE(x != nullptr); + auto xinit = x->initializer(); + ASSERT_TRUE(xinit != nullptr); + + auto instance = subst( + source, getTemplateBodyAs(templateDeclaration), + {xinit}); + + auto decl = instance->initDeclaratorList->value; + ASSERT_TRUE(decl != nullptr); + + auto init = ast_cast(decl->initializer); + ASSERT_TRUE(init); + + ASTInterpreter interp{&source.unit}; + + auto value = interp.evaluate(init->expression); + + ASSERT_TRUE(value.has_value()); - ASSERT_EQ(to_string(funcTypeAlias->typeId->type), "void (int, float)"); + ASSERT_EQ(std::visit(ArithmeticCast{}, *value), 123 + 321); }