Skip to content

Commit b2cd1c2

Browse files
committed
Rewrite non-type parameters
1 parent 9ea7693 commit b2cd1c2

File tree

8 files changed

+227
-66
lines changed

8 files changed

+227
-66
lines changed

packages/cxx-gen-ast/src/new_ast_rewriter_cc.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,30 @@ export function new_ast_rewriter_cc({
261261
emit(
262262
`auto ASTRewriter::${className}Visitor::operator()(${name}* ast) -> ${base}* {`
263263
);
264+
if (name === "IdExpressionAST") {
265+
emit(`
266+
if (auto x = symbol_cast<NonTypeParameterSymbol>(ast->symbol);
267+
x && x->depth() == 0 && x->index() < rewrite.templateArguments_.size()) {
268+
auto initializerPtr =
269+
std::get_if<ExpressionAST*>(&rewrite.templateArguments_[x->index()]);
270+
if (!initializerPtr) {
271+
cxx_runtime_error("expected initializer for non-type template parameter");
272+
}
273+
274+
auto initializer = rewrite(*initializerPtr);
275+
276+
if (auto eq = ast_cast<EqualInitializerAST>(initializer)) {
277+
return eq->expression;
278+
}
279+
280+
if (auto bracedInit = ast_cast<BracedInitListAST>(initializer)) {
281+
if (bracedInit->expressionList && !bracedInit->expressionList->next) {
282+
return bracedInit->expressionList->value;
283+
}
284+
}
285+
}
286+
`);
287+
}
264288
emit(` auto copy = make_node<${name}>(arena());`);
265289
emit();
266290
ast.baseMembers.get(base)?.forEach((m) => {

src/parser/cxx/ast.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,7 @@ class ConditionExpressionAST final : public ExpressionAST {
21202120
List<SpecifierAST*>* declSpecifierList = nullptr;
21212121
DeclaratorAST* declarator = nullptr;
21222122
ExpressionAST* initializer = nullptr;
2123-
Symbol* symbol = nullptr;
2123+
VariableSymbol* symbol = nullptr;
21242124

21252125
void accept(ASTVisitor* visitor) override { visitor->visit(this); }
21262126

src/parser/cxx/ast_rewriter.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,6 +2343,27 @@ auto ASTRewriter::ExpressionVisitor::operator()(NestedExpressionAST* ast)
23432343

23442344
auto ASTRewriter::ExpressionVisitor::operator()(IdExpressionAST* ast)
23452345
-> ExpressionAST* {
2346+
if (auto x = symbol_cast<NonTypeParameterSymbol>(ast->symbol);
2347+
x && x->depth() == 0 && x->index() < rewrite.templateArguments_.size()) {
2348+
auto initializerPtr =
2349+
std::get_if<ExpressionAST*>(&rewrite.templateArguments_[x->index()]);
2350+
if (!initializerPtr) {
2351+
cxx_runtime_error("expected initializer for non-type template parameter");
2352+
}
2353+
2354+
auto initializer = rewrite(*initializerPtr);
2355+
2356+
if (auto eq = ast_cast<EqualInitializerAST>(initializer)) {
2357+
return eq->expression;
2358+
}
2359+
2360+
if (auto bracedInit = ast_cast<BracedInitListAST>(initializer)) {
2361+
if (bracedInit->expressionList && !bracedInit->expressionList->next) {
2362+
return bracedInit->expressionList->value;
2363+
}
2364+
}
2365+
}
2366+
23462367
auto copy = make_node<IdExpressionAST>(arena());
23472368

23482369
copy->valueCategory = ast->valueCategory;

src/parser/cxx/parser.cc

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3715,12 +3715,14 @@ auto Parser::parse_maybe_module() -> bool {
37153715
return is_module;
37163716
}
37173717

3718-
auto Parser::parse_template_declaration_body(DeclarationAST*& yyast) -> bool {
3719-
if (parse_deduction_guide(yyast)) return true;
3720-
if (parse_export_declaration(yyast)) return true;
3721-
if (parse_opaque_enum_declaration(yyast)) return true;
3722-
if (parse_alias_declaration(yyast)) return true;
3723-
return parse_simple_declaration(yyast, BindingContext::kTemplate);
3718+
auto Parser::parse_template_declaration_body(
3719+
DeclarationAST*& yyast, TemplateDeclarationAST* templateHead) -> bool {
3720+
if (parse_deduction_guide(yyast, templateHead)) return true;
3721+
if (parse_export_declaration(yyast, templateHead)) return true;
3722+
if (parse_opaque_enum_declaration(yyast, templateHead)) return true;
3723+
if (parse_alias_declaration(yyast, templateHead)) return true;
3724+
return parse_simple_declaration(yyast, BindingContext::kTemplate,
3725+
templateHead);
37243726
}
37253727

37263728
auto Parser::parse_declaration(DeclarationAST*& yyast, BindingContext ctx)
@@ -3755,7 +3757,9 @@ auto Parser::parse_block_declaration(DeclarationAST*& yyast, BindingContext ctx)
37553757
return parse_simple_declaration(yyast, ctx);
37563758
}
37573759

3758-
auto Parser::parse_alias_declaration(DeclarationAST*& yyast) -> bool {
3760+
auto Parser::parse_alias_declaration(DeclarationAST*& yyast,
3761+
TemplateDeclarationAST* templateHead)
3762+
-> bool {
37593763
SourceLocation usingLoc;
37603764
SourceLocation identifierLoc;
37613765
const Identifier* identifier = nullptr;
@@ -3795,6 +3799,7 @@ auto Parser::parse_alias_declaration(DeclarationAST*& yyast) -> bool {
37953799
expect(TokenKind::T_SEMICOLON, semicolonLoc);
37963800

37973801
auto symbol = binder_.declareTypeAlias(identifierLoc, typeId);
3802+
symbol->setTemplateDeclaration(templateHead);
37983803

37993804
if (is_template(symbol)) {
38003805
mark_maybe_template_name(identifier);
@@ -3813,8 +3818,6 @@ auto Parser::parse_alias_declaration(DeclarationAST*& yyast) -> bool {
38133818
ast->semicolonLoc = semicolonLoc;
38143819
ast->symbol = symbol;
38153820

3816-
ast->symbol->setDeclaration(ast);
3817-
38183821
return true;
38193822
}
38203823

@@ -3919,7 +3922,7 @@ auto Parser::parse_notypespec_function_definition(
39193922
auto Parser::parse_type_or_forward_declaration(
39203923
DeclarationAST*& yyast, List<AttributeSpecifierAST*>* attributes,
39213924
List<SpecifierAST*>* declSpecifierList, const DeclSpecs& specs,
3922-
BindingContext ctx) -> bool {
3925+
BindingContext ctx, TemplateDeclarationAST* templateHead) -> bool {
39233926
if (ctx == BindingContext::kInitStatement) return false;
39243927

39253928
LookaheadParser lookahead{this};
@@ -3995,7 +3998,9 @@ auto Parser::parse_structured_binding(DeclarationAST*& yyast,
39953998
}
39963999

39974000
auto Parser::parse_simple_declaration(DeclarationAST*& yyast,
3998-
BindingContext ctx) -> bool {
4001+
BindingContext ctx,
4002+
TemplateDeclarationAST* templateHead)
4003+
-> bool {
39994004
SourceLocation extensionLoc;
40004005

40014006
match(TokenKind::T___EXTENSION__, extensionLoc);
@@ -4035,22 +4040,21 @@ auto Parser::parse_simple_declaration(DeclarationAST*& yyast,
40354040
if (!lookat_decl_specifiers()) return false;
40364041

40374042
if (parse_type_or_forward_declaration(yyast, attributes, declSpecifierList,
4038-
specs, ctx))
4043+
specs, ctx, templateHead))
40394044
return true;
40404045

4041-
if (parse_structured_binding(yyast, attributes, declSpecifierList, specs,
4042-
ctx))
4046+
if (!templateHead && parse_structured_binding(yyast, attributes,
4047+
declSpecifierList, specs, ctx))
40434048
return true;
40444049

40454050
return parse_simple_declaration(yyast, attributes, declSpecifierList, specs,
4046-
ctx);
4051+
ctx, templateHead);
40474052
}
40484053

4049-
auto Parser::parse_simple_declaration(DeclarationAST*& yyast,
4050-
List<AttributeSpecifierAST*>* attributes,
4051-
List<SpecifierAST*>* declSpecifierList,
4052-
const DeclSpecs& specs,
4053-
BindingContext ctx) -> bool {
4054+
auto Parser::parse_simple_declaration(
4055+
DeclarationAST*& yyast, List<AttributeSpecifierAST*>* attributes,
4056+
List<SpecifierAST*>* declSpecifierList, const DeclSpecs& specs,
4057+
BindingContext ctx, TemplateDeclarationAST* templateHead) -> bool {
40544058
DeclaratorAST* declarator = nullptr;
40554059
Decl decl{specs};
40564060
if (!parse_declarator(declarator, decl)) return false;
@@ -4136,7 +4140,8 @@ auto Parser::parse_simple_declaration(DeclarationAST*& yyast,
41364140
auto declIt = &initDeclaratorList;
41374141

41384142
InitDeclaratorAST* initDeclarator = nullptr;
4139-
if (!parse_init_declarator(initDeclarator, declarator, decl, ctx))
4143+
if (!parse_init_declarator(initDeclarator, declarator, decl, ctx,
4144+
templateHead))
41404145
return false;
41414146

41424147
if (ctx == BindingContext::kTemplate) {
@@ -4152,7 +4157,8 @@ auto Parser::parse_simple_declaration(DeclarationAST*& yyast,
41524157

41534158
while (match(TokenKind::T_COMMA, commaLoc)) {
41544159
InitDeclaratorAST* initDeclarator = nullptr;
4155-
if (!parse_init_declarator(initDeclarator, specs, ctx)) return false;
4160+
if (!parse_init_declarator(initDeclarator, specs, ctx, templateHead))
4161+
return false;
41564162

41574163
*declIt = make_list_node(pool_, initDeclarator);
41584164
declIt = &(*declIt)->next;
@@ -5206,7 +5212,8 @@ auto Parser::parse_placeholder_type_specifier(SpecifierAST*& yyast,
52065212
}
52075213

52085214
auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast,
5209-
const DeclSpecs& specs, BindingContext ctx)
5215+
const DeclSpecs& specs, BindingContext ctx,
5216+
TemplateDeclarationAST* templateHead)
52105217
-> bool {
52115218
DeclaratorAST* declarator = nullptr;
52125219
Decl decl{specs};
@@ -5217,7 +5224,9 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast,
52175224

52185225
auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast,
52195226
DeclaratorAST* declarator, Decl& decl,
5220-
BindingContext ctx) -> bool {
5227+
BindingContext ctx,
5228+
TemplateDeclarationAST* templateHead)
5229+
-> bool {
52215230
Symbol* symbol = nullptr;
52225231

52235232
if (auto declId = decl.declaratorId; declId) {
@@ -5229,6 +5238,7 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast,
52295238
symbol = functionSymbol;
52305239
} else {
52315240
auto variableSymbol = binder_.declareVariable(declarator, decl);
5241+
variableSymbol->setTemplateDeclaration(templateHead);
52325242
symbol = variableSymbol;
52335243
}
52345244
}
@@ -5249,6 +5259,10 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast,
52495259
ast->initializer = initializer;
52505260
ast->symbol = symbol;
52515261

5262+
if (auto var = symbol_cast<VariableSymbol>(ast->symbol)) {
5263+
var->setInitializer(initializer);
5264+
}
5265+
52525266
return true;
52535267
}
52545268

@@ -6186,7 +6200,9 @@ auto Parser::parse_enum_head_name(NestedNameSpecifierAST*& nestedNameSpecifier,
61866200
return true;
61876201
}
61886202

6189-
auto Parser::parse_opaque_enum_declaration(DeclarationAST*& yyast) -> bool {
6203+
auto Parser::parse_opaque_enum_declaration(DeclarationAST*& yyast,
6204+
TemplateDeclarationAST* templateHead)
6205+
-> bool {
61906206
SourceLocation enumLoc;
61916207
SourceLocation classLoc;
61926208
List<AttributeSpecifierAST*>* attributes = nullptr;
@@ -7255,7 +7271,9 @@ auto Parser::parse_module_partition(ModulePartitionAST*& yyast) -> bool {
72557271
return true;
72567272
}
72577273

7258-
auto Parser::parse_export_declaration(DeclarationAST*& yyast) -> bool {
7274+
auto Parser::parse_export_declaration(DeclarationAST*& yyast,
7275+
TemplateDeclarationAST* templateHead)
7276+
-> bool {
72597277
SourceLocation exportLoc;
72607278

72617279
if (!match(TokenKind::T_EXPORT, exportLoc)) return false;
@@ -8284,7 +8302,8 @@ auto Parser::parse_literal_operator_id(LiteralOperatorIdAST*& yyast) -> bool {
82848302
return true;
82858303
}
82868304

8287-
auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast)
8305+
auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast,
8306+
TemplateDeclarationAST* templateHead)
82888307
-> bool {
82898308
if (!lookat(TokenKind::T_TEMPLATE, TokenKind::T_LESS)) return false;
82908309

@@ -8294,6 +8313,8 @@ auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast)
82948313
auto ast = make_node<TemplateDeclarationAST>(pool_);
82958314
yyast = ast;
82968315

8316+
if (!templateHead) templateHead = ast;
8317+
82978318
auto templateParametersSymbol =
82988319
control_->newTemplateParametersSymbol(scope(), {});
82998320
ast->symbol = templateParametersSymbol;
@@ -8312,7 +8333,7 @@ auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast)
83128333

83138334
if (lookat(TokenKind::T_TEMPLATE, TokenKind::T_LESS)) {
83148335
TemplateDeclarationAST* templateDeclaration = nullptr;
8315-
(void)parse_template_declaration(templateDeclaration);
8336+
(void)parse_template_declaration(templateDeclaration, templateHead);
83168337
ast->declaration = templateDeclaration;
83178338
return true;
83188339
}
@@ -8321,7 +8342,7 @@ auto Parser::parse_template_declaration(TemplateDeclarationAST*& yyast)
83218342
return true;
83228343
}
83238344

8324-
if (!parse_template_declaration_body(ast->declaration))
8345+
if (!parse_template_declaration_body(ast->declaration, templateHead))
83258346
parse_error("expected a declaration");
83268347

83278348
return true;
@@ -8910,7 +8931,9 @@ auto Parser::parse_constraint_expression(ExpressionAST*& yyast) -> bool {
89108931
return parse_logical_or_expression(yyast, exprContext);
89118932
}
89128933

8913-
auto Parser::parse_deduction_guide(DeclarationAST*& yyast) -> bool {
8934+
auto Parser::parse_deduction_guide(DeclarationAST*& yyast,
8935+
TemplateDeclarationAST* templateHead)
8936+
-> bool {
89148937
SpecifierAST* explicitSpecifier = nullptr;
89158938
SourceLocation identifierLoc;
89168939
SourceLocation lparenLoc;

0 commit comments

Comments
 (0)