Skip to content

Commit 05a40f9

Browse files
committed
Add support of multi-level pointers
1 parent b1754db commit 05a40f9

File tree

4 files changed

+34
-29
lines changed

4 files changed

+34
-29
lines changed

regression-tests/test-results/mixed-lifetime-safety-and-null-contracts.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ auto null_from_cpp1() -> int* { return nullptr; }
1515

1616
auto try_pointer_stuff() -> void;
1717
#line 21 "mixed-lifetime-safety-and-null-contracts.cpp2"
18-
auto call_my_framework(cpp2::in<const char *> msg) -> void;
18+
auto call_my_framework(cpp2::in<const char*> msg) -> void;
1919

2020
//=== Cpp2 definitions ==========================================================
2121

@@ -29,12 +29,12 @@ auto call_my_framework(cpp2::in<const char *> msg) -> void;
2929
#line 14 "mixed-lifetime-safety-and-null-contracts.cpp2"
3030

3131
auto try_pointer_stuff() -> void{
32-
int* p { null_from_cpp1() };
32+
int * p { null_from_cpp1() };
3333
*p = 42; // deliberate null dereference
3434
// to show -n
3535
}
3636

37-
auto call_my_framework(cpp2::in<const char *> msg) -> void {
37+
auto call_my_framework(cpp2::in<const char*> msg) -> void {
3838
std::cout
3939
<< "sending error to my framework... ["
4040
<< msg << "]\n"; }

regression-tests/test-results/mixed-type-safety-1.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ auto print(cpp2::in<std::string> msg, cpp2::in<bool> b) -> void
4444
print( "1 is int? ", cpp2::is<int>(1));
4545

4646
auto c { cpp2_new<Circle>() }; // safe by construction
47-
Shape* s { CPP2_UFCS_0(get, c) }; // safe by Lifetime
47+
Shape * s { CPP2_UFCS_0(get, c) }; // safe by Lifetime
4848
print("\ns* is Shape? ", cpp2::is<Shape>(*s));
4949
print( "s* is Circle? ", cpp2::is<Circle>(*s));
5050
print( "s* is Square? ", cpp2::is<Square>(*s));

source/cppfront.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,10 @@ class cppfront
10711071
assert(n.identifier);
10721072
emit(*n.identifier);
10731073

1074+
for (auto _ : n.pointer_declarators) {
1075+
printer.print_cpp2("*", n.position());
1076+
}
1077+
10741078
if (!n.template_args.empty()) {
10751079
printer.print_cpp2("<", n.open_angle);
10761080
auto first = true;
@@ -1572,9 +1576,19 @@ class cppfront
15721576
auto& unqual = std::get<id_expression_node::unqualified>(id->id);
15731577
assert(unqual);
15741578
auto decl = sema.get_declaration_of(*unqual->identifier);
1575-
// TODO: Generalize this -- for now we detect only cases of the form "p: *int = ...;"
1576-
// We don't recognize pointer types that are deduced, multi-level, or from Cpp1
1577-
if (decl && decl->declaration && decl->declaration->pointer_declarator) {
1579+
1580+
bool is_pointer = false;
1581+
if (decl && decl->declaration) {
1582+
if (auto* obj_id_expr = std::get_if<declaration_node::object>(&decl->declaration->type)) {
1583+
if (auto* unqual = std::get_if<id_expression_node::unqualified>(&(*obj_id_expr)->id)){
1584+
is_pointer = !(*unqual)->pointer_declarators.empty();
1585+
}
1586+
}
1587+
}
1588+
1589+
// TODO: Generalize this -- for now we detect only multi-level cases of the form "p: ***int = ...;"
1590+
// We don't recognize pointer types that are deduced or from Cpp1
1591+
if (!unqual->pointer_declarators.empty() || is_pointer) {
15781592
if (n.ops.empty()) {
15791593
last_postfix_expr_was_pointer = true;
15801594
}
@@ -2155,10 +2169,6 @@ class cppfront
21552169
}
21562170
else {
21572171
emit( id_expr );
2158-
if (n.declaration->pointer_declarator) {
2159-
printer.print_cpp2(" ", n.declaration->pointer_declarator->position());
2160-
emit(*n.declaration->pointer_declarator);
2161-
}
21622172
}
21632173

21642174
// Then any suffix
@@ -2538,9 +2548,6 @@ class cppfront
25382548
}
25392549
printer.preempt_position(n.position());
25402550
emit( *type );
2541-
if (n.pointer_declarator) {
2542-
printer.print_cpp2("*", n.position());
2543-
}
25442551
// one pointer is enough for now, pointer-to-function fun can be later
25452552
if (!n.initializer) {
25462553
printer.print_cpp2( ">", n.position() );

source/parse.h

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ struct unqualified_id_node
364364
{
365365
token const* const_qualifier = {}; // optional
366366
token const* identifier = {}; // required
367+
std::vector<token const*> pointer_declarators = {}; // optional
367368

368369
enum active { empty=0, expression, id_expression };
369370

@@ -846,8 +847,6 @@ struct declaration_node
846847
source_position pos;
847848
std::unique_ptr<unqualified_id_node> identifier;
848849

849-
token const* pointer_declarator = nullptr;
850-
851850
enum active { function, object };
852851
std::variant<
853852
std::unique_ptr<function_type_node>,
@@ -1771,13 +1770,19 @@ class parser
17711770
{
17721771
// Handle the identifier
17731772
if (curr().type() != lexeme::Identifier &&
1774-
curr().type() != lexeme::Keyword) // 'const', and fundamental types that are keywords
1773+
curr().type() != lexeme::Keyword && // 'const', and fundamental types that are keywords
1774+
curr().type() != lexeme::Multiply ) // pointer declarators
17751775
{
17761776
return {};
17771777
}
17781778

17791779
auto n = std::make_unique<unqualified_id_node>();
17801780

1781+
while (curr().type() == lexeme::Multiply) {
1782+
n->pointer_declarators.push_back(&curr());
1783+
next();
1784+
}
1785+
17811786
if (curr().type() == lexeme::Keyword && curr() == "const") {
17821787
n->const_qualifier = &curr();
17831788
next();
@@ -2784,6 +2789,7 @@ class parser
27842789
auto unnamed_declaration(source_position pos, bool semicolon_required = true, bool captures_allowed = false) -> std::unique_ptr<declaration_node>
27852790
{
27862791
auto deduced_type = false;
2792+
auto pointer_declaration = false;
27872793

27882794
// The next token must be :
27892795
if (curr().type() != lexeme::Colon) {
@@ -2809,19 +2815,11 @@ class parser
28092815
n->type = std::move(t);
28102816
assert (n->type.index() == declaration_node::function);
28112817
}
2812-
2813-
// Or a pointer to a type, declaring a pointer object
2814-
else if (curr().type() == lexeme::Multiply) {
2815-
n->pointer_declarator = &curr();
2816-
next();
2817-
if (auto t = id_expression()) {
2818-
n->type = std::move(t);
2819-
assert (n->type.index() == declaration_node::object);
2820-
}
2821-
}
2822-
28232818
// Or just a type, declaring a non-pointer object
28242819
else if (auto t = id_expression()) {
2820+
if(auto* unqual = std::get_if<id_expression_node::unqualified>(&t->id)) {
2821+
pointer_declaration = !(*unqual)->pointer_declarators.empty();
2822+
}
28252823
n->type = std::move(t);
28262824
assert (n->type.index() == declaration_node::object);
28272825
}
@@ -2866,7 +2864,7 @@ class parser
28662864
n->equal_sign = curr().position();
28672865
next();
28682866

2869-
if (n->pointer_declarator) {
2867+
if (pointer_declaration) {
28702868
if (curr() == "nullptr" ||
28712869
isdigit(std::string_view(curr())[0]) ||
28722870
(curr() == "(" && peek(1) && *peek(1) == ")")

0 commit comments

Comments
 (0)