Skip to content

Commit fe990ca

Browse files
committed
Restore missing parens to expression_list_node output
Except where externally provided, by `f(list)` (provides parens) or `x[list]` (provides brackets) or `type var = {list}` (provides braces) This corrects cases like `(1+2)*3` and `a<(b>c)>`which had been emitted without parens See new regression test `mixed-test-parens.cpp2` to exercise these cases in one place
1 parent 2e2bece commit fe990ca

File tree

5 files changed

+60
-9
lines changed

5 files changed

+60
-9
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <vector>
2+
3+
template<bool>
4+
auto f(auto, auto) -> void { }
5+
6+
main: () -> int = {
7+
v : std::vector<int> = ( 1, 2, 3 );
8+
std::cout << (1+2)*(3+v[0]);
9+
f<(1>2)>(3,4);
10+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// ----- Cpp2 support -----
2+
#include "cpp2util.h"
3+
4+
#line 1 "mixed-test-parens.cpp2"
5+
#include <vector>
6+
7+
template<bool>
8+
auto f(auto, auto) -> void { }
9+
10+
[[nodiscard]] auto main() -> int;
11+
12+
//=== Cpp2 definitions ==========================================================
13+
14+
#line 5 "mixed-test-parens.cpp2"
15+
16+
[[nodiscard]] auto main() -> int{
17+
std::vector<int> v { 1, 2, 3 };
18+
std::cout << (1 + 2) * (3 + v[0]);
19+
f<(1 > 2)>(3, 4);
20+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mixed-test-parens.cpp2... ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks)
2+

source/cppfront.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,15 @@ class cppfront
631631
// special value - hack for now to note single-anon-return type kind in this function_returns working list
632632
std::vector<std::string> function_requires_conditions;
633633

634+
std::vector<bool> need_expression_list_parens = { true };
635+
auto push_need_expression_list_parens( bool b ) -> void { need_expression_list_parens.push_back(b); }
636+
auto pop_need_expression_list_parens() -> void { assert(std::ssize(need_expression_list_parens) > 1);
637+
need_expression_list_parens.pop_back(); }
638+
auto should_add_expression_list_parens() -> bool { assert(!need_expression_list_parens.empty());
639+
return need_expression_list_parens.back(); }
640+
auto consumed_expression_list_parens() -> void { if( std::ssize(need_expression_list_parens) > 1 )
641+
need_expression_list_parens.back() = false; }
642+
634643
public:
635644
//-----------------------------------------------------------------------
636645
// Constructor
@@ -1677,7 +1686,9 @@ class cppfront
16771686
// Then tack on any additional arguments
16781687
if (!n.ops[1].expr_list->expressions.empty()) {
16791688
printer.print_cpp2(", ", n.position());
1689+
push_need_expression_list_parens(false);
16801690
emit(*n.ops[1].expr_list);
1691+
pop_need_expression_list_parens();
16811692
}
16821693
printer.print_cpp2(")", n.position());
16831694

@@ -1773,7 +1784,9 @@ class cppfront
17731784
if (i->expr_list) {
17741785
auto text = std::vector<text_with_pos>{};
17751786
printer.emit_to_text_chunks(&text);
1787+
push_need_expression_list_parens(false);
17761788
emit(*i->expr_list);
1789+
pop_need_expression_list_parens();
17771790
printer.emit_to_text_chunks();
17781791
for (auto&& e: text) {
17791792
suffix.push_back(e);
@@ -1971,6 +1984,10 @@ class cppfront
19711984
//
19721985
auto emit(expression_list_node const& n) -> void
19731986
{
1987+
if (should_add_expression_list_parens() && !n.expressions.empty()) {
1988+
printer.print_cpp2("(", n.position());
1989+
}
1990+
19741991
auto first = true;
19751992
for (auto const& x : n.expressions) {
19761993
if (!first) {
@@ -2000,6 +2017,12 @@ class cppfront
20002017
printer.print_cpp2(")", n.position());
20012018
}
20022019
}
2020+
2021+
if (should_add_expression_list_parens() && !n.expressions.empty()) {
2022+
printer.print_cpp2(")", n.position());
2023+
}
2024+
// We want to consume only one of these
2025+
consumed_expression_list_parens();
20032026
}
20042027

20052028

@@ -2519,16 +2542,17 @@ class cppfront
25192542
printer.print_cpp2( " ", n.position());
25202543
assert(n.identifier);
25212544
emit(*n.identifier);
2522-
//printer.print_cpp2( *n.identifier->identifier, n.position() );
25232545

25242546
// If there's an initializer, emit it
25252547
if (n.initializer)
25262548
{
25272549
printer.add_pad_in_this_line(-100);
25282550
printer.print_cpp2( " { ", n.position() );
25292551

2552+
push_need_expression_list_parens(false);
25302553
assert( n.initializer );
25312554
emit( *n.initializer, false );
2555+
pop_need_expression_list_parens();
25322556

25332557
printer.print_cpp2( " }", n.position() );
25342558
}

source/parse.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,11 @@ auto to_string_view(passing_style pass) -> std::string_view {
255255

256256
struct expression_list_node
257257
{
258-
source_position open_paren = {}; // TODO: these should probably be in primary_expression_node
258+
source_position open_paren = {};
259259
source_position close_paren = {};
260260

261261
struct term {
262-
passing_style pass = {}; // for `out`
262+
passing_style pass = {};
263263
std::unique_ptr<expression_node> expr;
264264
};
265265
std::vector< term > expressions;
@@ -269,10 +269,6 @@ struct expression_list_node
269269
// Make sure this got set
270270
assert (open_paren != source_position());
271271
return open_paren;
272-
273-
// TODO this could be removed now that we're tracking position via open_paren
274-
//assert (std::ssize(expressions) > 0 && expressions.front().expr);
275-
//return expressions.front().expr->position();
276272
}
277273

278274
auto visit(auto& v, int depth) -> void
@@ -1765,8 +1761,8 @@ class parser
17651761
//G template-argument-list , template-argument
17661762
//G
17671763
//G template-argument:
1768-
//G expression
17691764
//G id-expression
1765+
//G expression
17701766
//G
17711767
auto unqualified_id() -> std::unique_ptr<unqualified_id_node>
17721768
{
@@ -2481,7 +2477,6 @@ class parser
24812477
next();
24822478
auto s = std::unique_ptr<statement_node>();
24832479

2484-
24852480
while (curr().type() != lexeme::RightBrace) {
24862481
auto s = statement(true);
24872482
if (!s) {

0 commit comments

Comments
 (0)