Skip to content

Commit d8b5e18

Browse files
committed
Support using at namespace and type scope, closes #803
Note: `using` at global scope is still categorized as Cpp1 code, so it works as expected (because the syntaxes are the same) but requires not using `-pure-cpp2` at the moment
1 parent d608eb5 commit d8b5e18

File tree

3 files changed

+94
-41
lines changed

3 files changed

+94
-41
lines changed

source/parse.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3968,12 +3968,30 @@ auto statement_node::position() const
39683968
return s->position();
39693969
}
39703970

3971+
break;case using_: {
3972+
auto const& s = std::get<using_>(statement);
3973+
assert (s);
3974+
return s->position();
3975+
}
3976+
39713977
break;case contract: {
39723978
auto const& s = std::get<contract>(statement);
39733979
assert (s);
39743980
return s->position();
39753981
}
39763982

3983+
break;case inspect: {
3984+
auto const& s = std::get<inspect>(statement);
3985+
assert (s);
3986+
return s->position();
3987+
}
3988+
3989+
break;case jump: {
3990+
auto const& s = std::get<jump>(statement);
3991+
assert (s);
3992+
return s->position();
3993+
}
3994+
39773995
break;default:
39783996
assert (!"illegal statement_node state");
39793997
return { 0, 0 };

source/sema.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,10 +1487,14 @@ class sema
14871487
auto compound_stmt = n.initializer->get_if<compound_statement_node>();
14881488
assert (compound_stmt);
14891489
for (auto& stmt : compound_stmt->statements) {
1490-
if (!stmt->is_declaration()) {
1490+
if (
1491+
!stmt->is_declaration()
1492+
&& !stmt->is_using()
1493+
)
1494+
{
14911495
errors.emplace_back(
14921496
stmt->position(),
1493-
"a user-defined type body must contain only declarations, not other code"
1497+
"a user-defined type body must contain only declarations or 'using' statements, not other code"
14941498
);
14951499
return false;
14961500
}

source/to_cpp1.h

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5316,30 +5316,29 @@ class cppfront
53165316

53175317
for (auto& stmt : compound_stmt->statements)
53185318
{
5319-
if (!stmt->is_declaration()) {
5320-
// We will already have emitted an error for this in sema.check
5321-
return;
5322-
}
5323-
auto& decl = std::get<statement_node::declaration>(stmt->statement);
5324-
assert(decl);
5325-
assert(decl->name());
5326-
5327-
auto emit_as_base =
5328-
decl->get_decl_if_type_scope_object_name_before_a_base_type(*decl->name());
5329-
5330-
if (emit_as_base) {
5331-
printer.print_extra(
5332-
"\nstruct "
5333-
+ print_to_string(*decl->parent_declaration->name())
5334-
+ "_"
5335-
+ decl->name()->to_string()
5336-
+ "_as_base { "
5337-
+ print_to_string( *decl->get_object_type() )
5338-
+ " "
5339-
+ decl->name()->to_string()
5340-
+ "; };"
5341-
);
5342-
found = true;
5319+
if (stmt->is_declaration())
5320+
{
5321+
auto& decl = std::get<statement_node::declaration>(stmt->statement);
5322+
assert(decl);
5323+
assert(decl->name());
5324+
5325+
auto emit_as_base =
5326+
decl->get_decl_if_type_scope_object_name_before_a_base_type(*decl->name());
5327+
5328+
if (emit_as_base) {
5329+
printer.print_extra(
5330+
"\nstruct "
5331+
+ print_to_string(*decl->parent_declaration->name())
5332+
+ "_"
5333+
+ decl->name()->to_string()
5334+
+ "_as_base { "
5335+
+ print_to_string( *decl->get_object_type() )
5336+
+ " "
5337+
+ decl->name()->to_string()
5338+
+ "; };"
5339+
);
5340+
found = true;
5341+
}
53435342
}
53445343
}
53455344

@@ -5438,21 +5437,51 @@ class cppfront
54385437
}
54395438

54405439
// Type definition
5441-
54425440
auto separator = std::string{":"};
54435441
auto started_body = false;
5442+
auto saved_for_body = std::vector<std::pair<std::string, source_position>>{};
54445443
auto found_constructor = false;
54455444
auto found_that_constructor = false;
54465445
assert(compound_stmt);
54475446

5447+
auto start_body = [&]{
5448+
if (!started_body) {
5449+
printer.print_cpp2(" {", compound_stmt->position());
5450+
started_body = true;
5451+
for (auto& [line, pos] : saved_for_body) {
5452+
printer.print_cpp2(line + "\n", pos);
5453+
}
5454+
}
5455+
};
5456+
54485457
for (auto& stmt : compound_stmt->statements)
54495458
{
54505459
assert(stmt);
5451-
if (!stmt->is_declaration()) {
5460+
if (
5461+
!stmt->is_declaration()
5462+
&& !stmt->is_using()
5463+
)
5464+
{
54525465
// We will already have emitted an error for this in sema.check
54535466
return;
54545467
}
54555468

5469+
// If it's a using statement, save it up if we haven't started the body yet
5470+
5471+
if (stmt->is_using()) {
5472+
auto& use = std::get<statement_node::using_>(stmt->statement);
5473+
assert(use);
5474+
if (started_body) {
5475+
emit(*use);
5476+
}
5477+
else {
5478+
saved_for_body.emplace_back( print_to_string(*use), use->position() );
5479+
}
5480+
continue;
5481+
}
5482+
5483+
// Else it's a declaration...
5484+
54565485
auto& decl = std::get<statement_node::declaration>(stmt->statement);
54575486
assert(decl);
54585487

@@ -5507,21 +5536,16 @@ class cppfront
55075536
else
55085537
{
55095538
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5510-
if (!started_body) {
5511-
printer.print_cpp2(" {", compound_stmt->position());
5512-
started_body = true;
5513-
}
5539+
start_body();
55145540
}
55155541
emit(*decl);
55165542
}
55175543
}
55185544

5519-
// Ensure we emit the { even if there are only bases in the type
55205545
if (printer.get_phase() == printer.phase1_type_defs_func_decls)
55215546
{
5522-
if (!started_body) {
5523-
printer.print_cpp2(" {", compound_stmt->position());
5524-
}
5547+
// Ensure we emit the { even if there are only bases in the type
5548+
start_body();
55255549

55265550
auto id = print_to_string(*n.identifier);
55275551
auto indent = static_cast<size_t>(
@@ -5583,16 +5607,23 @@ class cppfront
55835607
assert(compound_stmt);
55845608
for (auto& stmt : compound_stmt->statements) {
55855609
assert(stmt);
5586-
if (!stmt->is_declaration()) {
5610+
if (stmt->is_declaration()) {
5611+
auto& decl = std::get<statement_node::declaration>(stmt->statement);
5612+
assert(decl);
5613+
emit(*decl);
5614+
}
5615+
else if (stmt->is_using()) {
5616+
auto& use = std::get<statement_node::using_>(stmt->statement);
5617+
assert(use);
5618+
emit(*use);
5619+
}
5620+
else {
55875621
errors.emplace_back(
55885622
stmt->position(),
5589-
"a namespace scope must contain only declarations, not other code"
5623+
"a namespace scope must contain only declarations or 'using' statements, not other code"
55905624
);
55915625
return;
55925626
}
5593-
auto& decl = std::get<statement_node::declaration>(stmt->statement);
5594-
assert(decl);
5595-
emit(*decl);
55965627
}
55975628

55985629
printer.print_cpp2("}\n", compound_stmt->close_brace);

0 commit comments

Comments
 (0)