Skip to content

Commit 8cb1fd1

Browse files
committed
Add support for pointer deduce type
Add regression tests for deduced pointers
1 parent bd15d7c commit 8cb1fd1

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// workaround for bug where get_declaration_of is skipping first symbol
2+
bun: () = {}
3+
4+
fun: (inout i:int) -> *int = {
5+
return i&;
6+
}
7+
8+
main: (argc : int, argv : **char) -> int = {
9+
a: int = 2;
10+
pa: *int = a&;
11+
ppa: **int = pa&;
12+
13+
pa = 0; // caught
14+
15+
pa2:= ppa*;
16+
pa2 = 0; // caught
17+
18+
pa3 := a&;
19+
pa3 = 0; // caught
20+
pa3 += 2; // caught
21+
22+
ppa2 := pa2&;
23+
pa4 := ppa2*;
24+
pa4 = 0; // caught
25+
26+
pppa := ppa&;
27+
pa5 := pppa**;
28+
pa5 = 0; // caught
29+
30+
return a*pa**ppa**; // 8
31+
}

source/cppfront.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,32 @@ class cppfront
15551555
}
15561556

15571557

1558+
//-----------------------------------------------------------------------
1559+
//
1560+
auto is_it_pointer_declaration(declaration_sym const* decl, int deref_cnt = 0, int addr_cnt = 0) -> bool {
1561+
if (!decl || !decl->declaration)
1562+
return false;
1563+
if (addr_cnt>deref_cnt)
1564+
return true;
1565+
1566+
if (decl->declaration->dereference) {
1567+
auto deref = sema.get_declaration_of(*decl->declaration->dereference);
1568+
return is_it_pointer_declaration(deref, deref_cnt+decl->declaration->dereference_cnt, addr_cnt);
1569+
} else if (decl->declaration->address_of) {
1570+
auto addr = sema.get_declaration_of(*decl->declaration->address_of);
1571+
return is_it_pointer_declaration(addr, deref_cnt, addr_cnt+1);
1572+
}
1573+
1574+
int pointer_declarators_cnt = 0;
1575+
if (auto* obj_id_expr = std::get_if<declaration_node::object>(&decl->declaration->type)) {
1576+
if (auto* unqual = std::get_if<id_expression_node::unqualified>(&(*obj_id_expr)->id)){
1577+
pointer_declarators_cnt = std::ssize((*unqual)->pointer_declarators);
1578+
}
1579+
}
1580+
1581+
return (pointer_declarators_cnt + addr_cnt - deref_cnt) > 0;
1582+
};
1583+
15581584
//-----------------------------------------------------------------------
15591585
//
15601586
auto emit(postfix_expression_node& n, bool for_lambda_capture = false) -> void
@@ -1588,7 +1614,7 @@ class cppfront
15881614

15891615
// TODO: Generalize this -- for now we detect only multi-level cases of the form "p: ***int = ...;"
15901616
// We don't recognize pointer types that are deduced or from Cpp1
1591-
if (!unqual->pointer_declarators.empty() || is_pointer) {
1617+
if (is_it_pointer_declaration(decl) || !unqual->pointer_declarators.empty() || is_pointer) {
15921618
if (n.ops.empty()) {
15931619
last_postfix_expr_was_pointer = true;
15941620
}

source/parse.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,10 @@ struct declaration_node
847847
source_position pos;
848848
std::unique_ptr<unqualified_id_node> identifier;
849849

850+
token const* dereference = nullptr;
851+
int dereference_cnt = 0;
852+
token const* address_of = nullptr;
853+
850854
enum active { function, object };
851855
std::variant<
852856
std::unique_ptr<function_type_node>,
@@ -2876,6 +2880,19 @@ class parser
28762880
}
28772881
}
28782882

2883+
if (deduced_type) {
2884+
if (peek(1)->type() == lexeme::Ampersand) {
2885+
n->address_of = &curr();
2886+
}
2887+
else if (peek(1)->type() == lexeme::Multiply) {
2888+
n->dereference = &curr();
2889+
n->dereference_cnt = 1;
2890+
while(peek(n->dereference_cnt+1)->type() == lexeme::Multiply) {
2891+
n->dereference_cnt += 1;
2892+
}
2893+
}
2894+
}
2895+
28792896
if (!(n->initializer = statement(semicolon_required, n->equal_sign))) {
28802897
error("ill-formed initializer");
28812898
next();

0 commit comments

Comments
 (0)