Skip to content

Commit 1e99b0d

Browse files
committed
Move pointer_declarators to unqualified_id_node for pointer handling
Pointer declarators moved to the place where also const declarator is. unqualified_id_node is analyzed by cppfront when emiting postfix_expression_node and cppfront decide if there is illegal pointer action. Thanks to relocating pointer_declarators this change introduce deduction of pointer types also from functions - if function or variable is defined in cpp2 then cppfront has all information to deduce the proper type during compilation.
1 parent 31b03db commit 1e99b0d

File tree

2 files changed

+82
-39
lines changed

2 files changed

+82
-39
lines changed

source/cppfront.cpp

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,21 +1554,54 @@ class cppfront
15541554

15551555
//-----------------------------------------------------------------------
15561556
//
1557-
auto is_it_pointer_declaration(declaration_sym const* decl, int deref_cnt = 0, int addr_cnt = 0) -> bool {
1558-
if (!decl || !decl->declaration)
1557+
auto is_it_pointer_declaration(const std::unique_ptr<unqualified_id_node>& unqual, int deref_cnt = 0, int addr_cnt = 0) -> bool {
1558+
if (!unqual)
15591559
return false;
1560-
if (addr_cnt>deref_cnt)
1560+
if (!unqual->pointer_declarators.empty())
15611561
return true;
1562+
auto decl = sema.get_declaration_of(*unqual->identifier, true);
1563+
1564+
if (!decl || !decl->declaration)
1565+
return false;
1566+
1567+
if (auto* fun = std::get_if<declaration_node::function>(&decl->declaration->type)) {
1568+
if (auto* ret_id_expr = std::get_if<function_type_node::id>(&(*fun)->returns)) {
1569+
if (auto* unqual = std::get_if<id_expression_node::unqualified>(&(*ret_id_expr)->id)){
1570+
return is_it_pointer_declaration(*unqual, deref_cnt, addr_cnt);
1571+
}
1572+
}
1573+
}
1574+
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+
return is_it_pointer_declaration(*unqual, deref_cnt, addr_cnt);
1578+
}
1579+
}
1580+
1581+
if (decl->initializer && decl->initializer->suspicious_initialization) {
1582+
auto init_decl = sema.get_declaration_of(*decl->initializer->suspicious_initialization, true);
1583+
if (init_decl && init_decl->declaration) {
1584+
if (auto* fun = std::get_if<declaration_node::function>(&init_decl->declaration->type)) {
1585+
if (auto* ret_id_expr = std::get_if<function_type_node::id>(&(*fun)->returns)) {
1586+
if (auto* unqual = std::get_if<id_expression_node::unqualified>(&(*ret_id_expr)->id)){
1587+
return is_it_pointer_declaration(*unqual, deref_cnt, addr_cnt);
1588+
}
1589+
}
1590+
}
1591+
}
1592+
}
15621593

15631594
if (decl->declaration->dereference) {
1564-
auto deref = sema.get_declaration_of(*decl->declaration->dereference);
1565-
return is_it_pointer_declaration(deref, deref_cnt+decl->declaration->dereference_cnt, addr_cnt);
1595+
auto deref = sema.get_declaration_of(*decl->declaration->dereference, true);
1596+
assert(deref && deref->declaration);
1597+
return is_it_pointer_declaration(deref->declaration->identifier, deref_cnt+decl->declaration->dereference_cnt, addr_cnt);
15661598
} else if (decl->declaration->address_of) {
1567-
auto addr = sema.get_declaration_of(*decl->declaration->address_of);
1568-
return is_it_pointer_declaration(addr, deref_cnt, addr_cnt+1);
1599+
auto addr = sema.get_declaration_of(*decl->declaration->address_of, true);
1600+
assert(addr && addr->declaration);
1601+
return is_it_pointer_declaration(addr->declaration->identifier, deref_cnt, addr_cnt+1);
15691602
}
15701603

1571-
return (std::ssize(decl->declaration->pointer_declarators) + addr_cnt - deref_cnt) > 0;
1604+
return ((decl->declaration->identifier ? std::ssize(decl->declaration->identifier->pointer_declarators) : 0) + addr_cnt - deref_cnt) > 0;
15721605
};
15731606

15741607
//-----------------------------------------------------------------------
@@ -1596,26 +1629,32 @@ class cppfront
15961629

15971630
// if initialized by something suspicious (that we have no information about) we need to add cpp1 safety checks
15981631
add_safetycheck = !decl && needs_safetycheck;
1599-
if (is_it_pointer_declaration(decl)) {
1632+
if (is_it_pointer_declaration(unqual)) {
16001633
if (n.ops.empty()) {
16011634
last_postfix_expr_was_pointer = true;
16021635
}
16031636
else
16041637
{
1605-
if (n.ops.front().op->type() == lexeme::PlusPlus ||
1606-
n.ops.front().op->type() == lexeme::MinusMinus ||
1607-
n.ops.front().op->type() == lexeme::LeftBracket
1608-
) {
1638+
auto op = [&](){
1639+
if (n.ops.size() >= 2 && n.ops[0].op->type() == lexeme::LeftParen) {
1640+
return n.ops[1].op;
1641+
} else {
1642+
return n.ops.front().op;
1643+
}
1644+
}();
1645+
if (op->type() == lexeme::PlusPlus ||
1646+
op->type() == lexeme::MinusMinus ||
1647+
op->type() == lexeme::LeftBracket) {
16091648
errors.emplace_back(
1610-
n.ops.front().op->position(),
1611-
n.ops.front().op->to_string(true) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
1649+
op->position(),
1650+
op->to_string(true) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
16121651
);
16131652
violates_bounds_safety = true;
16141653
}
1615-
else if (n.ops.front().op->type() == lexeme::Tilde) {
1654+
else if (op->type() == lexeme::Tilde) {
16161655
errors.emplace_back(
1617-
n.ops.front().op->position(),
1618-
n.ops.front().op->to_string(true) + " - pointer bitwise manipulation is illegal - use std::bit_cast to convert to raw bytes first"
1656+
op->position(),
1657+
op->to_string(true) + " - pointer bitwise manipulation is illegal - use std::bit_cast to convert to raw bytes first"
16191658
);
16201659
}
16211660
}
@@ -2187,9 +2226,11 @@ class cppfront
21872226
}
21882227
else {
21892228
emit( id_expr );
2190-
for (const auto pointer_declarator : n.declaration->pointer_declarators) {
2191-
printer.print_cpp2(" ", pointer_declarator->position());
2192-
emit(*pointer_declarator);
2229+
if (unqid) {
2230+
for (const auto pointer_declarator : (*unqid)->pointer_declarators) {
2231+
printer.print_cpp2(" ", pointer_declarator->position());
2232+
emit(*pointer_declarator);
2233+
}
21932234
}
21942235
}
21952236

@@ -2370,6 +2411,12 @@ class cppfront
23702411
auto& r = std::get<function_type_node::id>(n.returns);
23712412
assert(r);
23722413
emit(*r);
2414+
if (auto* id = std::get_if<id_expression_node::unqualified>(&r->id)) {
2415+
assert(*id);
2416+
for (auto _ : (*id)->pointer_declarators) {
2417+
printer.print_cpp2("*", n.position());
2418+
}
2419+
}
23732420
}
23742421

23752422
else {
@@ -2570,8 +2617,11 @@ class cppfront
25702617
}
25712618
printer.preempt_position(n.position());
25722619
emit( *type );
2573-
for (auto _ : n.pointer_declarators) {
2574-
printer.print_cpp2("*", n.position());
2620+
if (auto* id = std::get_if<id_expression_node::unqualified>(&type->id)) {
2621+
assert(*id);
2622+
for (auto _ : (*id)->pointer_declarators) {
2623+
printer.print_cpp2("*", n.position());
2624+
}
25752625
}
25762626
// one pointer is enough for now, pointer-to-function fun can be later
25772627
if (!n.initializer) {

source/parse.h

Lines changed: 9 additions & 16 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

@@ -847,7 +848,6 @@ struct declaration_node
847848
source_position pos;
848849
std::unique_ptr<unqualified_id_node> identifier;
849850

850-
std::vector<token const*> pointer_declarators;
851851
token const* dereference = nullptr;
852852
int dereference_cnt = 0;
853853
token const* address_of = nullptr;
@@ -1775,13 +1775,19 @@ class parser
17751775
{
17761776
// Handle the identifier
17771777
if (curr().type() != lexeme::Identifier &&
1778-
curr().type() != lexeme::Keyword) // 'const', and fundamental types that are keywords
1778+
curr().type() != lexeme::Keyword && // 'const', and fundamental types that are keywords
1779+
curr().type() != lexeme::Multiply ) // pointer declarators
17791780
{
17801781
return {};
17811782
}
17821783

17831784
auto n = std::make_unique<unqualified_id_node>();
17841785

1786+
while (curr().type() == lexeme::Multiply) {
1787+
n->pointer_declarators.push_back(&curr());
1788+
next();
1789+
}
1790+
17851791
if (curr().type() == lexeme::Keyword && curr() == "const") {
17861792
n->const_qualifier = &curr();
17871793
next();
@@ -2813,19 +2819,6 @@ class parser
28132819
n->type = std::move(t);
28142820
assert (n->type.index() == declaration_node::function);
28152821
}
2816-
2817-
// Or a pointer to a type, declaring a pointer object
2818-
else if (curr().type() == lexeme::Multiply) {
2819-
while (curr().type() == lexeme::Multiply) {
2820-
n->pointer_declarators.push_back(&curr());
2821-
next();
2822-
}
2823-
if (auto t = id_expression()) {
2824-
n->type = std::move(t);
2825-
assert (n->type.index() == declaration_node::object);
2826-
}
2827-
}
2828-
28292822
// Or just a type, declaring a non-pointer object
28302823
else if (auto t = id_expression()) {
28312824
n->type = std::move(t);
@@ -2872,7 +2865,7 @@ class parser
28722865
n->equal_sign = curr().position();
28732866
next();
28742867

2875-
if (!n->pointer_declarators.empty()) {
2868+
if (n->identifier && !n->identifier->pointer_declarators.empty()) {
28762869
if (curr() == "nullptr" ||
28772870
isdigit(std::string_view(curr())[0]) ||
28782871
(curr() == "(" && peek(1) && *peek(1) == ")")

0 commit comments

Comments
 (0)