Skip to content

Commit e1b57cf

Browse files
committed
Move const/* declarators to _type-id_, support multilevel */const
Next will be teaching `as` to be able to take a _type-id_ so that `x as *Derived` work, but that'll be a later commit...
1 parent 8386329 commit e1b57cf

File tree

5 files changed

+64
-59
lines changed

5 files changed

+64
-59
lines changed

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

Lines changed: 2 additions & 2 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<char const*> msg) -> void;
1919

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

@@ -34,7 +34,7 @@ auto try_pointer_stuff() -> void{
3434
// to show -n
3535
}
3636

37-
auto call_my_framework(cpp2::in<const char *> msg) -> void{
37+
auto call_my_framework(cpp2::in<char const*> 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
@@ -30,7 +30,7 @@ auto print(cpp2::in<std::string> msg, auto const& x) -> void {
3030

3131
auto print(cpp2::in<std::string> msg, cpp2::in<bool> b) -> void
3232
{
33-
cpp2::deferred_init<const char*> bmsg;
33+
cpp2::deferred_init<char const*> bmsg;
3434
if (b) { bmsg.construct("true");}
3535
else { bmsg.construct("false");}
3636
std::cout << msg << std::move(bmsg.value()) << "\n";

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{
4444
}
4545

4646
auto print(cpp2::in<std::string> msg, cpp2::in<bool> b) -> void{
47-
cpp2::deferred_init<const char*> bmsg;
47+
cpp2::deferred_init<char const*> bmsg;
4848
if (b) { bmsg.construct("true");}
4949
else { bmsg.construct("false");}
5050
std::cout << std::setw(40) << msg << std::move(bmsg.value()) << "\n";

source/cppfront.cpp

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,13 +1186,13 @@ class cppfront
11861186
//
11871187
auto emit(type_id_node const& n) -> void
11881188
{
1189-
if (n.const_qualifier) {
1190-
emit(*n.const_qualifier);
1191-
printer.print_cpp2(" ", n.const_qualifier->position());
1192-
}
1193-
11941189
try_emit<type_id_node::qualified >(n.id);
11951190
try_emit<type_id_node::unqualified>(n.id, false, false);
1191+
1192+
for (auto i = n.pc_qualifiers.rbegin(); i != n.pc_qualifiers.rend(); ++i) {
1193+
if ((**i) == "const") { printer.print_cpp2(" ", n.position()); }
1194+
emit(**i);
1195+
}
11961196
}
11971197

11981198

@@ -1665,27 +1665,29 @@ class cppfront
16651665
auto decl = sema.get_local_declaration_of(*unqual->identifier);
16661666
// TODO: Generalize this -- for now we detect only cases of the form "p: *int = ...;"
16671667
// We don't recognize pointer types that are deduced, multi-level, or from Cpp1
1668-
if (decl && decl->declaration && decl->declaration->pointer_declarator) {
1669-
if (n.ops.empty()) {
1670-
last_postfix_expr_was_pointer = true;
1671-
}
1672-
else
1673-
{
1674-
if (n.ops.front().op->type() == lexeme::PlusPlus ||
1675-
n.ops.front().op->type() == lexeme::MinusMinus ||
1676-
n.ops.front().op->type() == lexeme::LeftBracket
1677-
) {
1678-
errors.emplace_back(
1679-
n.ops.front().op->position(),
1680-
n.ops.front().op->to_string(true) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
1681-
);
1682-
violates_bounds_safety = true;
1668+
if (decl) {
1669+
if (auto t = std::get_if<declaration_node::object>(&decl->declaration->type); t && (*t)->is_pointer_qualified()) {
1670+
if (n.ops.empty()) {
1671+
last_postfix_expr_was_pointer = true;
16831672
}
1684-
else if (n.ops.front().op->type() == lexeme::Tilde) {
1685-
errors.emplace_back(
1686-
n.ops.front().op->position(),
1687-
n.ops.front().op->to_string(true) + " - pointer bitwise manipulation is illegal - use std::bit_cast to convert to raw bytes first"
1688-
);
1673+
else
1674+
{
1675+
if (n.ops.front().op->type() == lexeme::PlusPlus ||
1676+
n.ops.front().op->type() == lexeme::MinusMinus ||
1677+
n.ops.front().op->type() == lexeme::LeftBracket
1678+
) {
1679+
errors.emplace_back(
1680+
n.ops.front().op->position(),
1681+
n.ops.front().op->to_string(true) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
1682+
);
1683+
violates_bounds_safety = true;
1684+
}
1685+
else if (n.ops.front().op->type() == lexeme::Tilde) {
1686+
errors.emplace_back(
1687+
n.ops.front().op->position(),
1688+
n.ops.front().op->to_string(true) + " - pointer bitwise manipulation is illegal - use std::bit_cast to convert to raw bytes first"
1689+
);
1690+
}
16891691
}
16901692
}
16911693
}
@@ -2333,10 +2335,6 @@ class cppfront
23332335
}
23342336
else {
23352337
emit( type_id );
2336-
if (n.declaration->pointer_declarator) {
2337-
printer.print_cpp2(" ", n.declaration->pointer_declarator->position());
2338-
emit(*n.declaration->pointer_declarator);
2339-
}
23402338
}
23412339

23422340
// Then any suffix
@@ -2725,9 +2723,6 @@ class cppfront
27252723
}
27262724
printer.preempt_position(n.position());
27272725
emit( *type );
2728-
if (n.pointer_declarator) {
2729-
printer.print_cpp2("*", n.position());
2730-
}
27312726
// one pointer is enough for now, pointer-to-function fun can be later
27322727
if (!n.initializer) {
27332728
printer.print_cpp2( ">", n.position() );

source/parse.h

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ struct type_id_node
507507
{
508508
source_position pos;
509509

510-
token const* const_qualifier = {}; // optional
510+
std::vector<token const*> pc_qualifiers;
511511

512512
enum active { empty=0, qualified, unqualified };
513513
std::variant<
@@ -516,6 +516,15 @@ struct type_id_node
516516
std::unique_ptr<unqualified_id_node>
517517
> id;
518518

519+
auto is_pointer_qualified() -> bool {
520+
for (auto q : pc_qualifiers) {
521+
if (q->type() == lexeme::Multiply) {
522+
return true;
523+
}
524+
}
525+
return false;
526+
}
527+
519528
auto template_args_count() -> int {
520529
if (id.index() == unqualified) {
521530
return std::get<unqualified>(id)->template_args_count();
@@ -540,8 +549,8 @@ struct type_id_node
540549
auto visit(auto& v, int depth) -> void
541550
{
542551
v.start(*this, depth);
543-
if (const_qualifier) {
544-
v.start(*const_qualifier, depth+1);
552+
for (auto q : pc_qualifiers) {
553+
v.start(*q, depth+1);
545554
}
546555
try_visit<qualified >(id, v, depth);
547556
try_visit<unqualified>(id, v, depth);
@@ -957,8 +966,6 @@ struct declaration_node
957966
source_position pos;
958967
std::unique_ptr<unqualified_id_node> identifier;
959968

960-
token const* pointer_declarator = nullptr;
961-
962969
enum active : std::uint8_t { function, object };
963970
std::variant<
964971
std::unique_ptr<function_type_node>,
@@ -1710,9 +1717,9 @@ class parser
17101717

17111718
//G is-as-expression:
17121719
//G prefix-expression
1713-
//GTODO is-as-expression is-expression-constraint
1714-
//GTODO is-as-expression as-type-cast
1715-
//GTODO type-id is-type-constraint
1720+
//G type-id is-type-constraint
1721+
//G is-as-expression is-expression-constraint
1722+
//GTODO is-as-expression as-type-cast
17161723
//G
17171724
auto is_as_expression() {
17181725
return binary_expression<is_as_expression_node> (
@@ -1994,15 +2001,27 @@ class parser
19942001

19952002

19962003
//G type-id:
1997-
//G const-opt unqualified-id
1998-
//G const-opt qualified-id
2004+
//G type-qualifier-seq-opt qualified-id
2005+
//G type-qualifier-seq-opt unqualified-id
2006+
//G
2007+
//G type-qualifier-seq:
2008+
//G type-qualifier
2009+
//G type-qualifier-seq type-qualifier
2010+
//G
2011+
//G type-qualifier:
2012+
//G const
2013+
//G *
19992014
//G
20002015
auto type_id() -> std::unique_ptr<type_id_node>
20012016
{
20022017
auto n = std::make_unique<type_id_node>();
20032018

2004-
if (curr().type() == lexeme::Keyword && curr() == "const") {
2005-
n->const_qualifier = &curr();
2019+
while (
2020+
(curr().type() == lexeme::Keyword && curr() == "const") ||
2021+
curr().type() == lexeme::Multiply
2022+
)
2023+
{
2024+
n->pc_qualifiers.push_back( &curr() );
20062025
next();
20072026
}
20082027

@@ -2034,6 +2053,7 @@ class parser
20342053
//G template-argument-list , template-argument
20352054
//G
20362055
//G template-argument:
2056+
//G # note: < > << >> are not allowed in expressions until new ( is opened
20372057
//G expression
20382058
//G id-expression
20392059
//G
@@ -3065,16 +3085,6 @@ class parser
30653085
assert (n->type.index() == declaration_node::function);
30663086
}
30673087

3068-
// Or a pointer to a type, declaring a pointer object
3069-
else if (curr().type() == lexeme::Multiply) {
3070-
n->pointer_declarator = &curr();
3071-
next();
3072-
if (auto t = type_id()) {
3073-
n->type = std::move(t);
3074-
assert (n->type.index() == declaration_node::object);
3075-
}
3076-
}
3077-
30783088
// Or just a type, declaring a non-pointer object
30793089
else if (auto t = type_id()) {
30803090
if (auto id = t->get_token(); id && *id == "namespace") {
@@ -3125,7 +3135,7 @@ class parser
31253135
n->equal_sign = curr().position();
31263136
next();
31273137

3128-
if (n->pointer_declarator) {
3138+
if (auto t = std::get_if<declaration_node::object>(&n->type); t && (*t)->is_pointer_qualified()) {
31293139
if (curr() == "nullptr" ||
31303140
isdigit(std::string_view(curr())[0]) ||
31313141
(curr() == "(" && peek(1) && *peek(1) == ")")

0 commit comments

Comments
 (0)