Skip to content

Commit a5227e0

Browse files
committed
fix(parse): make template-argument-list optional
1 parent 9584fcc commit a5227e0

5 files changed

+51
-24
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
plus: const std::plus<> = ();
2+
main: () -> int = std::plus<>()(0, 0);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
10+
11+
//=== Cpp2 type definitions and function declarations ===========================
12+
13+
#line 1 "pure2-bugfix-for-optional-template-argument-list.cpp2"
14+
extern std::plus<> const plus;
15+
[[nodiscard]] auto main() -> int;
16+
17+
18+
//=== Cpp2 function definitions =================================================
19+
20+
#line 1 "pure2-bugfix-for-optional-template-argument-list.cpp2"
21+
std::plus<> const plus {};
22+
[[nodiscard]] auto main() -> int { return std::plus<>()(0, 0); }
23+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-optional-template-argument-list.cpp2... ok (all Cpp2, passes safety checks)
2+

source/cppfront.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,10 +1666,10 @@ class cppfront
16661666
assert(n.identifier);
16671667
emit(*n.identifier, is_qualified); // inform the identifier if we know this is qualified
16681668

1669-
if (!n.template_args.empty()) {
1669+
if (n.template_args.has_value()) {
16701670
printer.print_cpp2("<", n.open_angle);
16711671
auto first = true;
1672-
for (auto& a : n.template_args) {
1672+
for (auto& a : n.template_args.value()) {
16731673
if (!first) {
16741674
printer.print_cpp2(",", a.comma);
16751675
}

source/parse.h

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <memory>
2323
#include <variant>
2424
#include <iostream>
25+
#include <optional>
2526

2627

2728
namespace cpp2 {
@@ -682,18 +683,21 @@ struct unqualified_id_node
682683
std::unique_ptr<type_id_node>
683684
> arg;
684685
};
685-
std::vector<term> template_args;
686+
std::optional<std::vector<term>> template_args;
686687

687688
auto template_args_count()
688689
-> int
689690
{
690-
return std::ssize(template_args);
691+
if (template_args.has_value())
692+
return std::ssize(template_args.value());
693+
// else
694+
return 0;
691695
}
692696

693697
auto get_token() const
694698
-> token const*
695699
{
696-
if (template_args.empty()) {
700+
if (!template_args.has_value()) {
697701
assert (identifier);
698702
return identifier;
699703
}
@@ -718,13 +722,14 @@ struct unqualified_id_node
718722
assert (identifier);
719723
v.start(*identifier, depth+1);
720724

721-
if (!template_args.empty()) {
725+
if (template_args.has_value()) {
722726
// Inform the visitor that this is a template args list
723727
v.start(template_args_tag{}, depth);
724728
assert(open_angle != source_position{});
725729
assert(close_angle != source_position{});
726-
assert(template_args.front().comma == source_position{});
727-
for (auto& a : template_args) {
730+
assert(template_args.value().empty()
731+
|| template_args.value().front().comma == source_position{});
732+
for (auto& a : template_args.value()) {
728733
try_visit<expression>(a.arg, v, depth+1);
729734
try_visit<type_id >(a.arg, v, depth+1);
730735
}
@@ -925,9 +930,9 @@ auto unqualified_id_node::to_string() const
925930
{
926931
assert(identifier);
927932
auto ret = identifier->to_string(true);
928-
if (!template_args.empty()) {
933+
if (template_args.has_value()) {
929934
auto separator = std::string{"<"};
930-
for (auto& t : template_args) {
935+
for (auto& t : template_args.value()) {
931936
ret += separator;
932937
assert(t.arg.index() != empty);
933938
if (t.arg.index() == expression) {
@@ -4454,18 +4459,10 @@ class parser
44544459
// Remember current position, in case this < is isn't a template argument list
44554460
auto start_pos = pos;
44564461

4457-
// And since we'll do this in two places, factor it into a local function
4458-
auto back_out_template_arg_list = [&]{
4459-
// Aha, this wasn't a template argument list after all,
4460-
// so back out just that part and return the identifier
4461-
n->open_angle = source_position{};
4462-
n->template_args.clear();
4463-
pos = start_pos;
4464-
};
4465-
44664462
n->open_angle = curr().position();
44674463
next();
4468-
4464+
4465+
n->template_args.emplace();
44694466
auto term = unqualified_id_node::term{};
44704467

44714468
do {
@@ -4477,10 +4474,9 @@ class parser
44774474
term.arg = std::move(i);
44784475
}
44794476
else {
4480-
back_out_template_arg_list();
4481-
return n;
4477+
break;
44824478
}
4483-
n->template_args.push_back( std::move(term) );
4479+
n->template_args.value().push_back( std::move(term) );
44844480
}
44854481
// Use the lambda trick to jam in a "next" clause
44864482
while (
@@ -4492,7 +4488,11 @@ class parser
44924488
// next term.comma = curr().position();
44934489

44944490
if (curr().type() != lexeme::Greater) {
4495-
back_out_template_arg_list();
4491+
// Aha, this wasn't a template argument list after all,
4492+
// so back out just that part and return the identifier
4493+
n->open_angle = source_position{};
4494+
n->template_args.reset();
4495+
pos = start_pos;
44964496
return n;
44974497
}
44984498
n->close_angle = curr().position();

0 commit comments

Comments
 (0)