Skip to content

Commit 5a2b31c

Browse files
committed
Added _type-id_ production, closes #132
Time to quit lazily reusing _id-expression_ as also a _type-id_, which is why _id-expression_ used to allow a `const` qualifier (and really shouldn't). Now we correctly reject statements like `const x = 1;`.
1 parent f7da573 commit 5a2b31c

File tree

2 files changed

+105
-33
lines changed

2 files changed

+105
-33
lines changed

source/cppfront.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,11 +1063,6 @@ class cppfront
10631063
printer.print_cpp2("CPP2_FORWARD(", n.position());
10641064
}
10651065

1066-
if (n.const_qualifier) {
1067-
emit(*n.const_qualifier);
1068-
printer.print_cpp2(" ", n.const_qualifier->position());
1069-
}
1070-
10711066
assert(n.identifier);
10721067
emit(*n.identifier);
10731068

@@ -1141,6 +1136,20 @@ class cppfront
11411136
}
11421137

11431138

1139+
//-----------------------------------------------------------------------
1140+
//
1141+
auto emit(type_id_node const& n) -> void
1142+
{
1143+
if (n.const_qualifier) {
1144+
emit(*n.const_qualifier);
1145+
printer.print_cpp2(" ", n.const_qualifier->position());
1146+
}
1147+
1148+
try_emit<type_id_node::qualified >(n.id);
1149+
try_emit<type_id_node::unqualified>(n.id, false, false);
1150+
}
1151+
1152+
11441153
//-----------------------------------------------------------------------
11451154
//
11461155
auto emit(id_expression_node const& n, bool is_local_name = true) -> void
@@ -2111,9 +2120,9 @@ class cppfront
21112120
assert( n.declaration );
21122121
assert( n.declaration->is(declaration_node::object) );
21132122

2114-
auto const& id_expr = *std::get<declaration_node::object>(n.declaration->type);
2123+
auto const& type_id = *std::get<declaration_node::object>(n.declaration->type);
21152124

2116-
auto unqid = std::get_if<id_expression_node::unqualified>(&id_expr.id);
2125+
auto unqid = std::get_if<type_id_node::unqualified>(&type_id.id);
21172126
auto is_wildcard = unqid && *(*unqid)->identifier == "_";
21182127

21192128
// First any prefix
@@ -2148,13 +2157,13 @@ class cppfront
21482157
req += *name;
21492158
req += "), ";
21502159
printer.emit_to_string(&req);
2151-
emit( id_expr );
2160+
emit( type_id );
21522161
printer.emit_to_string();
21532162
req += ">";
21542163
function_requires_conditions.push_back(req);
21552164
}
21562165
else {
2157-
emit( id_expr );
2166+
emit( type_id );
21582167
if (n.declaration->pointer_declarator) {
21592168
printer.print_cpp2(" ", n.declaration->pointer_declarator->position());
21602169
emit(*n.declaration->pointer_declarator);
@@ -2526,7 +2535,7 @@ class cppfront
25262535
auto& type = std::get<declaration_node::object>(n.type);
25272536

25282537
// Emit "auto" for deduced types (of course)
2529-
if (type->id.index() == id_expression_node::empty) {
2538+
if (type->id.index() == type_id_node::empty) {
25302539
assert(n.initializer);
25312540
printer.print_cpp2("auto", n.position());
25322541
}

source/parse.h

Lines changed: 86 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,6 @@ auto prefix_expression_node::visit(auto& v, int depth) -> void
362362

363363
struct unqualified_id_node
364364
{
365-
token const* const_qualifier = {}; // optional
366365
token const* identifier = {}; // required
367366

368367
enum active { empty=0, expression, id_expression };
@@ -398,9 +397,6 @@ struct unqualified_id_node
398397
auto visit(auto& v, int depth) -> void
399398
{
400399
v.start(*this, depth);
401-
if (const_qualifier) {
402-
v.start(*const_qualifier, depth+1);
403-
}
404400
assert (identifier);
405401
v.start(*identifier, depth+1);
406402

@@ -454,6 +450,44 @@ struct qualified_id_node
454450
}
455451
};
456452

453+
struct type_id_node
454+
{
455+
source_position pos;
456+
457+
token const* const_qualifier = {}; // optional
458+
459+
enum active { empty=0, qualified, unqualified };
460+
std::variant<
461+
std::monostate,
462+
std::unique_ptr<qualified_id_node>,
463+
std::unique_ptr<unqualified_id_node>
464+
> id;
465+
466+
auto get_token() -> token const* {
467+
if (id.index() == unqualified) {
468+
return std::get<unqualified>(id)->get_token();
469+
}
470+
// else
471+
return {};
472+
}
473+
474+
auto position() const -> source_position
475+
{
476+
return pos;
477+
}
478+
479+
auto visit(auto& v, int depth) -> void
480+
{
481+
v.start(*this, depth);
482+
if (const_qualifier) {
483+
v.start(*const_qualifier, depth+1);
484+
}
485+
try_visit<qualified >(id, v, depth);
486+
try_visit<unqualified>(id, v, depth);
487+
v.end(*this, depth);
488+
}
489+
};
490+
457491
struct id_expression_node
458492
{
459493
source_position pos;
@@ -622,7 +656,7 @@ struct inspect_expression_node
622656
bool is_constexpr = false;
623657
token const* identifier;
624658
std::unique_ptr<expression_node> expression;
625-
std::unique_ptr<id_expression_node> result_type;
659+
std::unique_ptr<type_id_node> result_type;
626660
source_position open_brace;
627661
source_position close_brace;
628662

@@ -851,7 +885,7 @@ struct declaration_node
851885
enum active { function, object };
852886
std::variant<
853887
std::unique_ptr<function_type_node>,
854-
std::unique_ptr<id_expression_node>
888+
std::unique_ptr<type_id_node>
855889
> type;
856890

857891
source_position equal_sign = {};
@@ -1752,9 +1786,38 @@ class parser
17521786
}
17531787

17541788

1789+
//G type-id:
1790+
//G const-opt unqualified-id
1791+
//G const-opt qualified-id
1792+
//G
1793+
auto type_id() -> std::unique_ptr<type_id_node>
1794+
{
1795+
auto n = std::make_unique<type_id_node>();
1796+
1797+
if (curr().type() == lexeme::Keyword && curr() == "const") {
1798+
n->const_qualifier = &curr();
1799+
next();
1800+
}
1801+
1802+
if (auto id = qualified_id()) {
1803+
n->pos = id->position();
1804+
n->id = std::move(id);
1805+
assert (n->id.index() == id_expression_node::qualified);
1806+
return n;
1807+
}
1808+
if (auto id = unqualified_id()) {
1809+
n->pos = id->position();
1810+
n->id = std::move(id);
1811+
assert (n->id.index() == id_expression_node::unqualified);
1812+
return n;
1813+
}
1814+
return {};
1815+
}
1816+
1817+
17551818
//G unqualified-id:
1756-
//G const-opt identifier
1757-
//G const-opt template-id
1819+
//G identifier
1820+
//G template-id
17581821
//GTODO operator-function-id
17591822
//G
17601823
//G template-id:
@@ -1778,11 +1841,6 @@ class parser
17781841

17791842
auto n = std::make_unique<unqualified_id_node>();
17801843

1781-
if (curr().type() == lexeme::Keyword && curr() == "const") {
1782-
n->const_qualifier = &curr();
1783-
next();
1784-
}
1785-
17861844
n->identifier = &curr();
17871845
next();
17881846

@@ -2262,7 +2320,7 @@ class parser
22622320

22632321
//G inspect-expression:
22642322
//G inspect constexpr-opt expression { alternative-seq-opt }
2265-
//G inspect constexpr-opt expression -> id-expression { alternative-seq-opt }
2323+
//G inspect constexpr-opt expression -> type-id { alternative-seq-opt }
22662324
//G
22672325
//G alternative-seq:
22682326
//G alternative
@@ -2312,12 +2370,12 @@ class parser
23122370
return {};
23132371
}
23142372

2315-
auto id = id_expression();
2316-
if (!id) {
2373+
auto type = type_id();
2374+
if (!type) {
23172375
error("expected a valid inspect return type after ->");
23182376
return {};
23192377
}
2320-
n->result_type = std::move(id);
2378+
n->result_type = std::move(type);
23212379
}
23222380
else if (is_expression) {
23232381
error("an inspect expression must have an explicit '-> result_type'");
@@ -2778,8 +2836,8 @@ class parser
27782836

27792837
//G unnamed-declaration:
27802838
//G : function-type = statement
2781-
//G : id-expression-opt = statement
2782-
//G : id-expression
2839+
//G : type-id-opt = statement
2840+
//G : type-id
27832841
//G
27842842
auto unnamed_declaration(source_position pos, bool semicolon_required = true, bool captures_allowed = false) -> std::unique_ptr<declaration_node>
27852843
{
@@ -2814,22 +2872,22 @@ class parser
28142872
else if (curr().type() == lexeme::Multiply) {
28152873
n->pointer_declarator = &curr();
28162874
next();
2817-
if (auto t = id_expression()) {
2875+
if (auto t = type_id()) {
28182876
n->type = std::move(t);
28192877
assert (n->type.index() == declaration_node::object);
28202878
}
28212879
}
28222880

28232881
// Or just a type, declaring a non-pointer object
2824-
else if (auto t = id_expression()) {
2882+
else if (auto t = type_id()) {
28252883
n->type = std::move(t);
28262884
assert (n->type.index() == declaration_node::object);
28272885
}
28282886

28292887
// Or nothing, declaring an object of deduced type,
2830-
// which we'll represent using an empty id-expression
2888+
// which we'll represent using an empty type-id
28312889
else {
2832-
n->type = std::make_unique<id_expression_node>();
2890+
n->type = std::make_unique<type_id_node>();
28332891
assert (n->type.index() == declaration_node::object);
28342892
deduced_type = true;
28352893
}
@@ -3059,6 +3117,11 @@ class parse_tree_printer : printing_visitor
30593117
o << pre(indent) << "qualified-id\n";
30603118
}
30613119

3120+
auto start(type_id_node const& n, int indent) -> void
3121+
{
3122+
o << pre(indent) << "type-id\n";
3123+
}
3124+
30623125
auto start(id_expression_node const& n, int indent) -> void
30633126
{
30643127
o << pre(indent) << "id-expression\n";

0 commit comments

Comments
 (0)