Skip to content

Commit 85a1e8a

Browse files
authored
fix(parse): make template-argument-list optional (#473)
* fix(parse): make template-argument-list optional * refactor: use `open_angle` as cue for temp arg list * test: add `test-results/gcc-13`
1 parent c5919be commit 85a1e8a

8 files changed

+45
-18
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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
c++ (GCC) 13.1.1 20230429
2+
Copyright (C) 2023 Free Software Foundation, Inc.
3+
This is free software; see the source for copying conditions. There is NO
4+
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5+

regression-tests/test-results/gcc-13/pure2-bugfix-for-optional-template-argument-list.cpp.execution

Whitespace-only changes.

regression-tests/test-results/gcc-13/pure2-bugfix-for-optional-template-argument-list.cpp.output

Whitespace-only changes.
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1666,7 +1666,7 @@ 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.open_angle != source_position{}) {
16701670
printer.print_cpp2("<", n.open_angle);
16711671
auto first = true;
16721672
for (auto& a : n.template_args) {

source/parse.h

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ struct unqualified_id_node
886886
auto get_token() const
887887
-> token const*
888888
{
889-
if (template_args.empty()) {
889+
if (open_angle == source_position{}) {
890890
assert (identifier);
891891
return identifier;
892892
}
@@ -911,12 +911,13 @@ struct unqualified_id_node
911911
assert (identifier);
912912
v.start(*identifier, depth+1);
913913

914-
if (!template_args.empty()) {
914+
if (open_angle != source_position{}) {
915915
// Inform the visitor that this is a template args list
916916
v.start(template_args_tag{}, depth);
917917
assert(open_angle != source_position{});
918918
assert(close_angle != source_position{});
919-
assert(template_args.front().comma == source_position{});
919+
assert(template_args.empty()
920+
|| template_args.front().comma == source_position{});
920921
for (auto& a : template_args) {
921922
try_visit<expression>(a.arg, v, depth+1);
922923
try_visit<type_id >(a.arg, v, depth+1);
@@ -1118,7 +1119,7 @@ auto unqualified_id_node::to_string() const
11181119
{
11191120
assert(identifier);
11201121
auto ret = identifier->to_string(true);
1121-
if (!template_args.empty()) {
1122+
if (open_angle != source_position{}) {
11221123
auto separator = std::string{"<"};
11231124
for (auto& t : template_args) {
11241125
ret += separator;
@@ -4815,18 +4816,9 @@ class parser
48154816
// Remember current position, in case this < is isn't a template argument list
48164817
auto start_pos = pos;
48174818

4818-
// And since we'll do this in two places, factor it into a local function
4819-
auto back_out_template_arg_list = [&]{
4820-
// Aha, this wasn't a template argument list after all,
4821-
// so back out just that part and return the identifier
4822-
n->open_angle = source_position{};
4823-
n->template_args.clear();
4824-
pos = start_pos;
4825-
};
4826-
48274819
n->open_angle = curr().position();
48284820
next();
4829-
4821+
48304822
auto term = unqualified_id_node::term{};
48314823

48324824
do {
@@ -4838,8 +4830,7 @@ class parser
48384830
term.arg = std::move(i);
48394831
}
48404832
else {
4841-
back_out_template_arg_list();
4842-
return n;
4833+
break;
48434834
}
48444835
n->template_args.push_back( std::move(term) );
48454836
}
@@ -4853,7 +4844,11 @@ class parser
48534844
// next term.comma = curr().position();
48544845

48554846
if (curr().type() != lexeme::Greater) {
4856-
back_out_template_arg_list();
4847+
// Aha, this wasn't a template argument list after all,
4848+
// so back out just that part and return the identifier
4849+
n->open_angle = source_position{};
4850+
n->template_args.clear();
4851+
pos = start_pos;
48574852
return n;
48584853
}
48594854
n->close_angle = curr().position();

0 commit comments

Comments
 (0)