Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9717,27 +9717,24 @@ auto Parser::parse_explicit_instantiation(DeclarationAST*& yyast) -> bool {
if (!parse_declaration(ast->declaration, BindingContext::kTemplate))
parse_error("expected a declaration");

auto check_elaborated_type_specifier = [&] {
if (!config().checkTypes) return;

auto check_elaborated_type_specifier = [&]() -> bool {
auto simpleDecl = ast_cast<SimpleDeclarationAST>(ast->declaration);
if (!simpleDecl) return;
if (!simpleDecl) return false;

if (!simpleDecl->declSpecifierList) return;
if (!simpleDecl->declSpecifierList) return false;

auto elabSpec = ast_cast<ElaboratedTypeSpecifierAST>(
simpleDecl->declSpecifierList->value);
if (!elabSpec) {
type_error(currentLocation(), "expected an elaborated type specifier");
return;
return false;
}

if (elabSpec->nestedNameSpecifier) {
auto templateId = ast_cast<SimpleTemplateIdAST>(elabSpec->unqualifiedId);
if (!templateId) {
type_error(elabSpec->unqualifiedId->firstSourceLocation(),
"expected a template id");
return;
return true;
}

auto candidate = Lookup{scope()}.qualifiedLookup(
Expand All @@ -9746,7 +9743,7 @@ auto Parser::parse_explicit_instantiation(DeclarationAST*& yyast) -> bool {
if (!is_template(candidate)) {
type_error(elabSpec->unqualifiedId->firstSourceLocation(),
std::format("expected a template"));
return;
return true;
}

auto classSymbol = symbol_cast<ClassSymbol>(candidate);
Expand All @@ -9755,37 +9752,48 @@ auto Parser::parse_explicit_instantiation(DeclarationAST*& yyast) -> bool {
elabSpec->unqualifiedId->firstSourceLocation(),
std::format("expected a class template, got '{}'",
to_string(candidate->type(), candidate->name())));
return;
return true;
}

auto instance = ASTRewriter::instantiateClassTemplate(
unit, templateId->templateArgumentList, classSymbol);
if (config().checkTypes) {
auto instance = ASTRewriter::instantiateClassTemplate(
unit, templateId->templateArgumentList, classSymbol);

return;
(void)instance;
}

return true;
}

auto templateId = ast_cast<SimpleTemplateIdAST>(elabSpec->unqualifiedId);
if (!templateId) {
type_error(elabSpec->unqualifiedId->firstSourceLocation(),
"expected a template id");
return;
return true;
}

auto classSymbol = symbol_cast<ClassSymbol>(templateId->symbol);
if (!classSymbol) {
type_error(
templateId->identifierLoc,
"explicit instantiation of this template is not yet supported");
return;
return true;
}

auto instance = ASTRewriter::instantiateClassTemplate(
unit, templateId->templateArgumentList, classSymbol);
if (config().checkTypes) {
auto instance = ASTRewriter::instantiateClassTemplate(
unit, templateId->templateArgumentList, classSymbol);

(void)instance;
}

(void)instance;
return true;
};

check_elaborated_type_specifier();
if (check_elaborated_type_specifier()) return true;

// todo: handle other template kinds
type_error(ast->firstSourceLocation(), "failed to instantiate template");

return true;
}
Expand Down
Loading