Skip to content

Commit 9221682

Browse files
committed
feat: allow exporting declarations
1 parent 08806e3 commit 9221682

File tree

3 files changed

+81
-35
lines changed

3 files changed

+81
-35
lines changed

source/cppfront.cpp

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class positional_printer
197197
std::vector<comment> const* pcomments = {}; // Cpp2 comments data
198198
source const* psource = {};
199199
parser const* pparser = {};
200-
200+
201201
source_position curr_pos = {}; // current (line,col) in output
202202
lineno_t generated_pos_line = {}; // current line in generated output
203203
int last_line_indentation = {};
@@ -1226,7 +1226,7 @@ class cppfront
12261226

12271227
//---------------------------------------------------------------------
12281228
// Do lowered file prolog
1229-
//
1229+
//
12301230
// Only emit extra lines if we actually have Cpp2, because
12311231
// we want pure-Cpp1 files to pass through with zero changes
12321232
if (source.has_cpp2())
@@ -1284,7 +1284,7 @@ class cppfront
12841284
}
12851285
}
12861286

1287-
1287+
12881288
//---------------------------------------------------------------------
12891289
// Do phase1_type_defs_func_decls
12901290
//
@@ -1641,7 +1641,7 @@ class cppfront
16411641
{
16421642
add_move = false;
16431643
}
1644-
1644+
16451645
if (
16461646
emitting_move_that_function
16471647
&& *n.identifier == "that"
@@ -2253,7 +2253,7 @@ class cppfront
22532253
return;
22542254
} else if (
22552255
is_literal(tok->type()) || n.expression->expr->is_result_a_temporary_variable()
2256-
)
2256+
)
22572257
{
22582258
errors.emplace_back(
22592259
n.position(),
@@ -2545,7 +2545,7 @@ class cppfront
25452545
)
25462546
-> bool
25472547
{
2548-
if (!fun_node) {
2548+
if (!fun_node) {
25492549
return false;
25502550
}
25512551
if (addr_cnt > deref_cnt) {
@@ -2572,11 +2572,11 @@ class cppfront
25722572
)
25732573
-> bool
25742574
{
2575-
if (!type_id_node) {
2575+
if (!type_id_node) {
25762576
return false;
25772577
}
25782578
if (addr_cnt > deref_cnt) {
2579-
return true;
2579+
return true;
25802580
}
25812581

25822582
if ( type_id_node->dereference_of ) {
@@ -2753,7 +2753,7 @@ class cppfront
27532753
{
27542754
auto& unqual = std::get<id_expression_node::unqualified>(id->id);
27552755
assert(unqual);
2756-
// TODO: Generalize this:
2756+
// TODO: Generalize this:
27572757
// - we don't recognize pointer types from Cpp1
27582758
// - we don't deduce pointer types from parameter_declaration_list_node
27592759
if ( is_pointer_declaration(unqual->identifier) ) {
@@ -4817,7 +4817,7 @@ class cppfront
48174817
}
48184818

48194819
// If this is a generated declaration (negative source line number),
4820-
// add a line break before
4820+
// add a line break before
48214821
if (
48224822
printer.get_phase() == printer.phase2_func_defs
48234823
&& n.position().lineno < 1
@@ -4860,6 +4860,8 @@ class cppfront
48604860
else {
48614861
printer.print_cpp2("public: ", n.position());
48624862
}
4863+
} else if (n.is_export()) {
4864+
printer.print_cpp2(to_string(n.access) + " ", n.position());
48634865
}
48644866

48654867
// Emit template parameters if any
@@ -5014,11 +5016,32 @@ class cppfront
50145016
}
50155017
}
50165018

5019+
// Emit export on forward declaration.
5020+
if (
5021+
n.is_export()
5022+
&& n.parent_is_namespace()
5023+
)
5024+
{
5025+
if (
5026+
printer.get_phase() == printer.phase0_type_decls
5027+
|| (
5028+
printer.get_phase() == printer.phase1_type_defs_func_decls
5029+
&& !n.is_type() // Done in phase 0.
5030+
)
5031+
)
5032+
{
5033+
printer.print_cpp2(to_string(n.access) + " ", n.position());
5034+
}
5035+
}
50175036
// In class definitions, emit the explicit access specifier if there
50185037
// is one, or default to private for data and public for functions
5019-
if (printer.get_phase() == printer.phase1_type_defs_func_decls)
5038+
else if (printer.get_phase() == printer.phase1_type_defs_func_decls)
50205039
{
5021-
if (!n.is_default_access()) {
5040+
if (
5041+
!n.is_default_access()
5042+
&& !n.is_export()
5043+
)
5044+
{
50225045
assert (is_in_type);
50235046
printer.print_cpp2(to_string(n.access) + ": ", n.position());
50245047
}
@@ -5453,7 +5476,7 @@ class cppfront
54535476
// A2) This is '(out this, move that)'
54545477
// and no '(inout this, move that)' was written by the user
54555478
// (*) and no '(inout this, that)' was written by the user (*)
5456-
//
5479+
//
54575480
// (*) This third test is to tie-break M2 and A2 in favor of M2. Both M2 and A2
54585481
// can generate a missing '(inout this, move that)', and if we have both
54595482
// options then we should prefer to use M2 (generate move assignment from

source/parse.h

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ struct postfix_expression_node
721721
if (ops.empty()) {
722722
return false;
723723
} else {
724-
return (ops.front().op->type() == lexeme::Ampersand
724+
return (ops.front().op->type() == lexeme::Ampersand
725725
|| ops.front().op->type() == lexeme::Tilde);
726726
}
727727
}
@@ -2225,7 +2225,7 @@ struct alias_node
22252225
};
22262226

22272227

2228-
enum class accessibility { default_ = 0, public_, protected_, private_ };
2228+
enum class accessibility { default_ = 0, public_, protected_, private_, export_ };
22292229

22302230
auto to_string(accessibility a)
22312231
-> std::string
@@ -2234,6 +2234,7 @@ auto to_string(accessibility a)
22342234
break;case accessibility::public_ : return "public";
22352235
break;case accessibility::protected_: return "protected";
22362236
break;case accessibility::private_ : return "private";
2237+
break;case accessibility::export_ : return "export";
22372238
break;default: assert(a == accessibility::default_);
22382239
}
22392240
return "default";
@@ -2358,6 +2359,12 @@ struct declaration_node
23582359
return access == accessibility::private_;
23592360
}
23602361

2362+
auto is_export() const
2363+
-> bool
2364+
{
2365+
return access == accessibility::export_;
2366+
}
2367+
23612368
auto is_default_access() const
23622369
-> bool
23632370
{
@@ -3993,7 +4000,7 @@ class parser
39934000
// || curr().type() == lexeme::LeftBrace
39944001
)
39954002
{
3996-
bool inside_initializer = (
4003+
bool inside_initializer = (
39974004
peek(-1) && peek(-1)->type() == lexeme::Assignment
39984005
);
39994006
auto open_paren = &curr();
@@ -4015,12 +4022,12 @@ class parser
40154022
next();
40164023
if (
40174024
curr().type() != lexeme::Semicolon
4018-
&& curr().type() != lexeme::RightParen
4019-
&& curr().type() != lexeme::RightBracket
4025+
&& curr().type() != lexeme::RightParen
4026+
&& curr().type() != lexeme::RightBracket
40204027
&& curr().type() != lexeme::Comma
40214028
) {
40224029
expr_list->inside_initializer = false;
4023-
}
4030+
}
40244031
n->expr = std::move(expr_list);
40254032
return n;
40264033
}
@@ -4374,7 +4381,7 @@ class parser
43744381
//G shift-expression '<<' additive-expression
43754382
//G shift-expression '>>' additive-expression
43764383
//G
4377-
auto shift_expression(bool allow_angle_operators = true)
4384+
auto shift_expression(bool allow_angle_operators = true)
43784385
-> auto
43794386
{
43804387
if (allow_angle_operators) {
@@ -4409,7 +4416,7 @@ class parser
44094416
//G shift-expression
44104417
//G compare-expression '<=>' shift-expression
44114418
//G
4412-
auto compare_expression(bool allow_angle_operators = true)
4419+
auto compare_expression(bool allow_angle_operators = true)
44134420
-> auto
44144421
{
44154422
return binary_expression<compare_expression_node> (
@@ -4425,7 +4432,7 @@ class parser
44254432
//G relational-expression '<=' compare-expression
44264433
//G relational-expression '>=' compare-expression
44274434
//G
4428-
auto relational_expression(bool allow_angle_operators = true)
4435+
auto relational_expression(bool allow_angle_operators = true)
44294436
-> auto
44304437
{
44314438
if (allow_angle_operators) {
@@ -4457,7 +4464,7 @@ class parser
44574464
//G equality-expression '==' relational-expression
44584465
//G equality-expression '!=' relational-expression
44594466
//G
4460-
auto equality_expression(bool allow_angle_operators = true)
4467+
auto equality_expression(bool allow_angle_operators = true)
44614468
-> auto
44624469
{
44634470
return binary_expression<equality_expression_node> (
@@ -4470,7 +4477,7 @@ class parser
44704477
//G equality-expression
44714478
//G bit-and-expression '&' equality-expression
44724479
//G
4473-
auto bit_and_expression(bool allow_angle_operators = true)
4480+
auto bit_and_expression(bool allow_angle_operators = true)
44744481
-> auto
44754482
{
44764483
return binary_expression<bit_and_expression_node> (
@@ -4483,7 +4490,7 @@ class parser
44834490
//G bit-and-expression
44844491
//G bit-xor-expression '^' bit-and-expression
44854492
//G
4486-
auto bit_xor_expression(bool allow_angle_operators = true)
4493+
auto bit_xor_expression(bool allow_angle_operators = true)
44874494
-> auto
44884495
{
44894496
return binary_expression<bit_xor_expression_node> (
@@ -4496,7 +4503,7 @@ class parser
44964503
//G bit-xor-expression
44974504
//G bit-or-expression '|' bit-xor-expression
44984505
//G
4499-
auto bit_or_expression(bool allow_angle_operators = true)
4506+
auto bit_or_expression(bool allow_angle_operators = true)
45004507
-> auto
45014508
{
45024509
return binary_expression<bit_or_expression_node> (
@@ -4509,7 +4516,7 @@ class parser
45094516
//G bit-or-expression
45104517
//G logical-and-expression '&&' bit-or-expression
45114518
//G
4512-
auto logical_and_expression(bool allow_angle_operators = true)
4519+
auto logical_and_expression(bool allow_angle_operators = true)
45134520
-> auto
45144521
{
45154522
return binary_expression<logical_and_expression_node> (
@@ -4524,7 +4531,7 @@ class parser
45244531
//G logical-and-expression
45254532
//G logical-or-expression '||' logical-and-expression
45264533
//G
4527-
auto logical_or_expression(bool allow_angle_operators = true)
4534+
auto logical_or_expression(bool allow_angle_operators = true)
45284535
-> auto
45294536
{
45304537
return binary_expression<logical_or_expression_node> (
@@ -4842,7 +4849,7 @@ class parser
48424849

48434850
n->open_angle = curr().position();
48444851
next();
4845-
4852+
48464853
auto term = unqualified_id_node::term{};
48474854

48484855
do {
@@ -6413,7 +6420,7 @@ class parser
64136420
}
64146421
assert (n->is_type());
64156422
}
6416-
6423+
64176424
// Or a function type, declaring a function - and tell the function whether it's in a user-defined type
64186425
else if (auto t = function_type(n.get(), named))
64196426
{
@@ -6561,11 +6568,11 @@ class parser
65616568
)
65626569
{
65636570
auto& type = std::get<declaration_node::an_object>(n->type);
6564-
// object initialized by the address of the curr() object
6571+
// object initialized by the address of the curr() object
65656572
if (peek(1)->type() == lexeme::Ampersand) {
65666573
type->address_of = &curr();
65676574
}
6568-
// object initialized by (potentially multiple) dereference of the curr() object
6575+
// object initialized by (potentially multiple) dereference of the curr() object
65696576
else if (peek(1)->type() == lexeme::Multiply) {
65706577
type->dereference_of = &curr();
65716578
for (int i = 1; peek(i)->type() == lexeme::Multiply; ++i)
@@ -6770,7 +6777,7 @@ class parser
67706777
return {};
67716778
}
67726779
if (
6773-
t->is_wildcard()
6780+
t->is_wildcard()
67746781
|| ( t->get_token() && t->get_token()->to_string(true) == "auto" )
67756782
) {
67766783
errors.emplace_back(
@@ -6878,6 +6885,10 @@ class parser
68786885
access = accessibility::private_;
68796886
next();
68806887
}
6888+
else if (curr() == "export") {
6889+
access = accessibility::export_;
6890+
next();
6891+
}
68816892

68826893
// If they wrote an access-specifier, see if they put a ':'
68836894
// after it out of Cpp1 habit (there's no colon in Cpp2)

source/sema.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,19 @@ class sema
12161216
}
12171217

12181218
if (
1219-
n.access != accessibility::default_
1219+
n.is_export()
1220+
&& !n.parent_is_namespace()
1221+
)
1222+
{
1223+
errors.emplace_back(
1224+
n.position(),
1225+
"an export declaration is only allowed at namespace scope"
1226+
);
1227+
return false;
1228+
}
1229+
else if (
1230+
!n.is_export()
1231+
&& !n.is_default_access()
12201232
&& !n.parent_is_type()
12211233
)
12221234
{
@@ -1564,7 +1576,7 @@ class sema
15641576
// Skip type scope (member) variables
15651577
&& !(n.parent_is_type() && n.is_object())
15661578
// Skip unnamed variables
1567-
&& n.identifier
1579+
&& n.identifier
15681580
// Skip non-out parameters
15691581
&& (
15701582
!inside_parameter_list

0 commit comments

Comments
 (0)