Skip to content

Commit 6031b28

Browse files
hsutterzaucy
authored andcommitted
Allow else if, closes hsutter#366
Also, reject `=` assignment expressions in `if` conditions. They're already disallowed in loop conditions, and it's an oversight that they were not already disallowed in `if` conditions... the `if` condition is supposed to take *logical-or-expression* (the conditional expression production) like the loop conditions do.
1 parent 300682d commit 6031b28

10 files changed

+123
-19
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
main: (args) = {
2+
p : *int;
3+
4+
a := 1;
5+
b := 2;
6+
c := 3;
7+
d := 4;
8+
9+
if args.size() == 3 {
10+
p = a&;
11+
} else if true {
12+
if args.size() == 2 {
13+
p = c&;
14+
} else if b > 0 {
15+
p = a&;
16+
}
17+
else {
18+
p = d&;
19+
}
20+
} else {
21+
p = c&;
22+
}
23+
24+
std::cout << p* << std::endl;
25+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

regression-tests/test-results/clang-12/pure2-initialization-safety-with-else-if.cpp.output

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

regression-tests/test-results/gcc-10/pure2-initialization-safety-with-else-if.cpp.output

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-initialization-safety-with-else-if.cpp
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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-initialization-safety-with-else-if.cpp2"
14+
auto main(int const argc_, char const* const* const argv_) -> int;
15+
16+
17+
//=== Cpp2 function definitions =================================================
18+
19+
#line 1 "pure2-initialization-safety-with-else-if.cpp2"
20+
auto main(int const argc_, char const* const* const argv_) -> int{
21+
auto args = cpp2::make_args(argc_, argv_);
22+
#line 2 "pure2-initialization-safety-with-else-if.cpp2"
23+
cpp2::deferred_init<int*> p;
24+
25+
auto a {1};
26+
auto b {2};
27+
auto c {3};
28+
auto d {4};
29+
30+
if (CPP2_UFCS_0(size, args)==3) {
31+
p.construct(&a);
32+
}else {if (true) {
33+
if (CPP2_UFCS_0(size, args)==2) {
34+
p.construct(&c);
35+
}else {if (cpp2::cmp_greater(std::move(b),0)) {
36+
p.construct(&a);
37+
}
38+
else {
39+
p.construct(&d);
40+
}}
41+
}else {
42+
p.construct(&c);
43+
}}
44+
45+
std::cout << *cpp2::assert_not_null(std::move(p.value())) << std::endl;
46+
}
47+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-initialization-safety-with-else-if.cpp2... ok (all Cpp2, passes safety checks)
2+

source/parse.h

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,13 +1160,13 @@ struct compound_statement_node
11601160

11611161
struct selection_statement_node
11621162
{
1163-
bool is_constexpr = false;
1164-
token const* identifier = {};
1165-
source_position else_pos;
1166-
std::unique_ptr<expression_node> expression;
1167-
std::unique_ptr<compound_statement_node> true_branch;
1168-
std::unique_ptr<compound_statement_node> false_branch;
1169-
bool has_source_false_branch = false;
1163+
bool is_constexpr = false;
1164+
token const* identifier = {};
1165+
source_position else_pos;
1166+
std::unique_ptr<logical_or_expression_node> expression;
1167+
std::unique_ptr<compound_statement_node> true_branch;
1168+
std::unique_ptr<compound_statement_node> false_branch;
1169+
bool has_source_false_branch = false;
11701170

11711171
auto position() const
11721172
-> source_position
@@ -4596,8 +4596,8 @@ class parser
45964596

45974597

45984598
//G selection-statement:
4599-
//G 'if' 'constexpr'? expression compound-statement
4600-
//G 'if' 'constexpr'? expression compound-statement 'else' compound-statement
4599+
//G 'if' 'constexpr'? logical-or-expression compound-statement
4600+
//G 'if' 'constexpr'? logical-or-expression compound-statement 'else' compound-statement
46014601
//G
46024602
auto selection_statement()
46034603
-> std::unique_ptr<selection_statement_node>
@@ -4622,7 +4622,7 @@ class parser
46224622
next();
46234623
}
46244624

4625-
if (auto e = expression()) {
4625+
if (auto e = logical_or_expression()) {
46264626
n->expression = std::move(e);
46274627
}
46284628
else {
@@ -4657,12 +4657,16 @@ class parser
46574657
n->else_pos = curr().position();
46584658
next();
46594659

4660-
if (curr().type() != lexeme::LeftBrace) {
4660+
if (
4661+
curr().type() != lexeme::LeftBrace
4662+
&& curr() != "if"
4663+
)
4664+
{
46614665
error("an else branch body must be enclosed with { }");
46624666
return {};
46634667
}
46644668

4665-
if (auto s = compound_statement()) {
4669+
if (auto s = compound_statement( source_position{}, true )) {
46664670
n->false_branch = std::move(s);
46674671
n->has_source_false_branch = true;
46684672
}
@@ -5181,16 +5185,25 @@ class parser
51815185
//G statement-seq statement
51825186
//G
51835187
auto compound_statement(
5184-
source_position equal_sign = source_position{}
5188+
source_position equal_sign = source_position{},
5189+
bool allow_single_unbraced_statement = false
51855190
)
51865191
-> std::unique_ptr<compound_statement_node>
51875192
{
5188-
if (curr().type() != lexeme::LeftBrace) {
5193+
bool is_braced = curr().type() == lexeme::LeftBrace;
5194+
if (
5195+
!is_braced
5196+
&& !allow_single_unbraced_statement
5197+
)
5198+
{
51895199
return {};
51905200
}
51915201

51925202
auto n = std::make_unique<compound_statement_node>();
5193-
if (peek(1)) {
5203+
if (!is_braced) {
5204+
n->body_indent = curr().position().colno-1;
5205+
}
5206+
else if (peek(1)) {
51945207
n->body_indent = peek(1)->position().colno-1;
51955208
}
51965209

@@ -5207,9 +5220,19 @@ class parser
52075220
else {
52085221
n->open_brace = curr().position();
52095222
}
5210-
next();
52115223

5212-
while (curr().type() != lexeme::RightBrace) {
5224+
if (is_braced) {
5225+
next();
5226+
}
5227+
5228+
while (
5229+
curr().type() != lexeme::RightBrace
5230+
&& (
5231+
is_braced
5232+
|| std::ssize(n->statements) < 1
5233+
)
5234+
)
5235+
{
52135236
if (
52145237
(
52155238
is_literal(curr().type())
@@ -5229,8 +5252,11 @@ class parser
52295252
n->statements.push_back( std::move(s) );
52305253
}
52315254

5232-
n->close_brace = curr().position();
5233-
next();
5255+
if (is_braced) {
5256+
assert(curr().type() == lexeme::RightBrace);
5257+
n->close_brace = curr().position();
5258+
next();
5259+
}
52345260
return n;
52355261
}
52365262

0 commit comments

Comments
 (0)