@@ -555,7 +555,7 @@ class cppfront
555
555
556
556
bool source_loaded = true ;
557
557
bool last_postfix_expr_was_pointer = false ;
558
- bool bounds_safety_violation = false ;
558
+ bool violates_bounds_safety = false ;
559
559
bool suppress_move_from_last_use = false ;
560
560
561
561
// For lowering
@@ -643,8 +643,14 @@ class cppfront
643
643
catch (std::runtime_error& e) {
644
644
errors.emplace_back (
645
645
source_position (-1 , -1 ),
646
- " unexpected text or end-of-file - see previous errors \n "
646
+ e. what ()
647
647
);
648
+ if (violates_lifetime_safety) {
649
+ errors.emplace_back (
650
+ source_position (-1 , -1 ),
651
+ " program violates lifetime safety guarantee - see previous errors"
652
+ );
653
+ }
648
654
}
649
655
}
650
656
}
@@ -1142,12 +1148,6 @@ class cppfront
1142
1148
assert (n.expr );
1143
1149
last_postfix_expr_was_pointer = false ;
1144
1150
1145
- // Simple case: If there are no .ops, just emit the expression
1146
- if (n.ops .empty ()) {
1147
- emit (*n.expr );
1148
- return ;
1149
- }
1150
-
1151
1151
// Check that this isn't pointer arithmentic
1152
1152
// (initial partial implementation)
1153
1153
if (n.expr ->expr .index () == primary_expression_node::id_expression)
@@ -1163,23 +1163,32 @@ class cppfront
1163
1163
// We don't recognize pointer types that are deduced, multi-level, or from Cpp1
1164
1164
if (decl && decl->declaration && decl->declaration ->pointer_declarator ) {
1165
1165
last_postfix_expr_was_pointer = true ;
1166
- if (n.ops .front ().op ->type () == lexeme::PlusPlus || n.ops .front ().op ->type () == lexeme::MinusMinus) {
1167
- errors.emplace_back (
1168
- n.ops .front ().op ->position (),
1169
- n.ops .front ().op ->to_string (true ) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
1170
- );
1171
- bounds_safety_violation = true ;
1172
- }
1173
- else if (n.ops .front ().op ->type () == lexeme::Tilde) {
1174
- errors.emplace_back (
1175
- n.ops .front ().op ->position (),
1176
- n.ops .front ().op ->to_string (true ) + " - pointer bitwise manipulation is illegal - use std::bit_cast to convert to raw bytes first"
1177
- );
1166
+ if (!n.ops .empty ())
1167
+ {
1168
+ if (n.ops .front ().op ->type () == lexeme::PlusPlus || n.ops .front ().op ->type () == lexeme::MinusMinus) {
1169
+ errors.emplace_back (
1170
+ n.ops .front ().op ->position (),
1171
+ n.ops .front ().op ->to_string (true ) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
1172
+ );
1173
+ violates_bounds_safety = true ;
1174
+ }
1175
+ else if (n.ops .front ().op ->type () == lexeme::Tilde) {
1176
+ errors.emplace_back (
1177
+ n.ops .front ().op ->position (),
1178
+ n.ops .front ().op ->to_string (true ) + " - pointer bitwise manipulation is illegal - use std::bit_cast to convert to raw bytes first"
1179
+ );
1180
+ }
1178
1181
}
1179
1182
}
1180
1183
}
1181
1184
}
1182
1185
1186
+ // Simple case: If there are no .ops, just emit the expression
1187
+ if (n.ops .empty ()) {
1188
+ emit (*n.expr );
1189
+ return ;
1190
+ }
1191
+
1183
1192
// Check to see if it's just a function call,
1184
1193
// and if so use this path to convert it to UFCS
1185
1194
if (std::ssize (n.ops ) == 1 &&
@@ -1351,18 +1360,6 @@ class cppfront
1351
1360
{
1352
1361
assert (n.expr );
1353
1362
1354
- // Check that this isn't pointer arithmentic
1355
- // (initial partial implementation)
1356
- if (!n.terms .empty () && (*n.terms .front ().op == " +" || *n.terms .front ().op == " -" )) {
1357
- if (last_postfix_expr_was_pointer) {
1358
- errors.emplace_back (
1359
- n.terms .front ().op ->position (),
1360
- n.terms .front ().op ->to_string (true ) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
1361
- );
1362
- bounds_safety_violation = true ;
1363
- }
1364
- }
1365
-
1366
1363
// Handle is/as expressions
1367
1364
// For now, hack in just a single 'as'-cast
1368
1365
// TODO: Generalize
@@ -1393,6 +1390,36 @@ class cppfront
1393
1390
emit (*n.expr );
1394
1391
suppress_move_from_last_use = false ;
1395
1392
1393
+ // Check that this isn't an illegal pointer operation
1394
+ // (initial partial implementation)
1395
+ if (!n.terms .empty () && last_postfix_expr_was_pointer)
1396
+ {
1397
+ auto rhs_post = n.get_second_postfix_expression_node ();
1398
+ assert (rhs_post && rhs_post->expr );
1399
+ auto rhs_tok = rhs_post->expr ->get_token ();
1400
+ if (is_assignment_operator (n.terms .front ().op ->type ()) && rhs_tok &&
1401
+ (*rhs_tok == " nullptr" || is_digit (((std::string_view)*rhs_tok)[0 ]))
1402
+ )
1403
+ {
1404
+ errors.emplace_back (
1405
+ n.terms .front ().op ->position (),
1406
+ n.terms .front ().op ->to_string (true ) + " - pointer assignment from null or integer is illegal"
1407
+ );
1408
+ violates_lifetime_safety = true ;
1409
+ }
1410
+ else if (
1411
+ *n.terms .front ().op == " +" || *n.terms .front ().op == " +=" ||
1412
+ *n.terms .front ().op == " -" || *n.terms .front ().op == " -="
1413
+ )
1414
+ {
1415
+ errors.emplace_back (
1416
+ n.terms .front ().op ->position (),
1417
+ n.terms .front ().op ->to_string (true ) + " - pointer arithmetic is illegal - use std::span or gsl::span instead"
1418
+ );
1419
+ violates_bounds_safety = true ;
1420
+ }
1421
+ }
1422
+
1396
1423
for (auto const & x : n.terms ) {
1397
1424
assert (x.op );
1398
1425
assert (x.expr );
@@ -1936,7 +1963,10 @@ class cppfront
1936
1963
for (auto && error : errors) {
1937
1964
error.print (std::cerr, strip_path (sourcefile));
1938
1965
}
1939
- if (bounds_safety_violation) {
1966
+ if (violates_lifetime_safety) {
1967
+ std::cerr << " program violates lifetime safety guarantee - see previous errors\n " ;
1968
+ }
1969
+ if (violates_bounds_safety) {
1940
1970
std::cerr << " program violates bounds safety guarantee - see previous errors\n " ;
1941
1971
}
1942
1972
}
0 commit comments