Skip to content

Commit 81e08cf

Browse files
authored
Add diagnostics for returning a temporary (#384)
1 parent 908d522 commit 81e08cf

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
fun1: () -> forward _ = { return global / 1; } // error: a 'forward' return type cannot return a temporary variable
2+
fun4: () -> forward _ = { return global << 1; } // error: a 'forward' return type cannot return a temporary variable
3+
fun5: () -> forward _ = { return global <=> 1; } // error: a 'forward' return type cannot return a temporary variable
4+
fun6: () -> forward _ = { return global < 1; } // error: a 'forward' return type cannot return a temporary variable
5+
fun7: () -> forward _ = { return global <= 1; } // error: a 'forward' return type cannot return a temporary variable
6+
fun9: () -> forward _ = { return global >> 1; } // error: a 'forward' return type cannot return a temporary variable
7+
fun10: () -> forward _ = { return global >= 1; } // error: a 'forward' return type cannot return a temporary variable
8+
fun11: () -> forward _ = { return global > 1; } // error: a 'forward' return type cannot return a temporary variable
9+
fun14: () -> forward _ = { return global + 1; } // error: a 'forward' return type cannot return a temporary variable
10+
fun15: () -> forward _ = { return global - 1; } // error: a 'forward' return type cannot return a temporary variable
11+
fun20: () -> forward _ = { return global || 1; } // error: a 'forward' return type cannot return a temporary variable
12+
fun22: () -> forward _ = { return global | 1; } // error: a 'forward' return type cannot return a temporary variable
13+
fun24: () -> forward _ = { return global && 1; } // error: a 'forward' return type cannot return a temporary variable
14+
fun26: () -> forward _ = { return global * 1; } // error: a 'forward' return type cannot return a temporary variable
15+
fun28: () -> forward _ = { return global % 1; } // error: a 'forward' return type cannot return a temporary variable
16+
fun30: () -> forward _ = { return global & 1; } // error: a 'forward' return type cannot return a temporary variable
17+
fun32: () -> forward _ = { return global ^ 1; } // error: a 'forward' return type cannot return a temporary variable
18+
fun35: () -> forward _ = { return global == 1; } // error: a 'forward' return type cannot return a temporary variable
19+
fun37: () -> forward _ = { return global != 1; } // error: a 'forward' return type cannot return a temporary variable
20+
fun38: () -> forward _ = { return !ptr_g; } // error: a 'forward' return type cannot return a temporary variable
21+
fun42: () -> forward _ = { return global&; } // error: a 'forward' return type cannot return a temporary variable
22+
fun43: () -> forward _ = { return ptr_g~; } // error: a 'forward' return type cannot return a temporary variable
23+
24+
fun2: () -> forward _ = { return global /= 1; }
25+
fun3: () -> forward _ = { return global <<= 1; }
26+
fun8: () -> forward _ = { return global >>= 1; }
27+
fun12: () -> forward _ = { return global++; }
28+
fun13: () -> forward _ = { return global += 1; }
29+
fun16: () -> forward _ = { return global -= 1; }
30+
fun17: () -> forward _ = { return ptr_g*.x; }
31+
fun18: () -> forward _ = { return global--; }
32+
fun21: () -> forward _ = { return global |= 1; }
33+
fun25: () -> forward _ = { return global *= 1; }
34+
fun27: () -> forward _ = { return global %= 1; }
35+
fun29: () -> forward _ = { return global &= 1; }
36+
fun31: () -> forward _ = { return global ^= 1; }
37+
fun36: () -> forward _ = { return global = 1; }
38+
fun39: () -> forward _ = { return g.x; }
39+
fun41: () -> forward _ = { return ptr_g*; }
40+
41+
// fun19: () -> forward _ = { return global ||= 1; } // not supported
42+
// fun23: () -> forward _ = { return global &&= 1; } // not supported
43+
// fun33: () -> forward _ = { return global ~= 1; } // not supported
44+
// fun34: () -> forward _ = { return global ~ 1; } // not supported
45+
// fun40: () -> forward _ = { return ptr_g ? ptr_g* : g; } // not supported
46+
47+
global: i32 = 42;
48+
t: type = {
49+
public x : int = 42;
50+
}
51+
52+
g: t = ();
53+
ptr_g: *t = g&;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
pure2-forward-return-diagnostics-error.cpp2...
2+
pure2-forward-return-diagnostics-error.cpp2(1,28): error: a 'forward' return type cannot return a temporary variable
3+
pure2-forward-return-diagnostics-error.cpp2(2,28): error: a 'forward' return type cannot return a temporary variable
4+
pure2-forward-return-diagnostics-error.cpp2(3,28): error: a 'forward' return type cannot return a temporary variable
5+
pure2-forward-return-diagnostics-error.cpp2(4,28): error: a 'forward' return type cannot return a temporary variable
6+
pure2-forward-return-diagnostics-error.cpp2(5,28): error: a 'forward' return type cannot return a temporary variable
7+
pure2-forward-return-diagnostics-error.cpp2(6,28): error: a 'forward' return type cannot return a temporary variable
8+
pure2-forward-return-diagnostics-error.cpp2(7,28): error: a 'forward' return type cannot return a temporary variable
9+
pure2-forward-return-diagnostics-error.cpp2(8,28): error: a 'forward' return type cannot return a temporary variable
10+
pure2-forward-return-diagnostics-error.cpp2(9,28): error: a 'forward' return type cannot return a temporary variable
11+
pure2-forward-return-diagnostics-error.cpp2(10,28): error: a 'forward' return type cannot return a temporary variable
12+
pure2-forward-return-diagnostics-error.cpp2(11,28): error: a 'forward' return type cannot return a temporary variable
13+
pure2-forward-return-diagnostics-error.cpp2(12,28): error: a 'forward' return type cannot return a temporary variable
14+
pure2-forward-return-diagnostics-error.cpp2(13,28): error: a 'forward' return type cannot return a temporary variable
15+
pure2-forward-return-diagnostics-error.cpp2(14,28): error: a 'forward' return type cannot return a temporary variable
16+
pure2-forward-return-diagnostics-error.cpp2(15,28): error: a 'forward' return type cannot return a temporary variable
17+
pure2-forward-return-diagnostics-error.cpp2(16,28): error: a 'forward' return type cannot return a temporary variable
18+
pure2-forward-return-diagnostics-error.cpp2(17,28): error: a 'forward' return type cannot return a temporary variable
19+
pure2-forward-return-diagnostics-error.cpp2(18,28): error: a 'forward' return type cannot return a temporary variable
20+
pure2-forward-return-diagnostics-error.cpp2(19,28): error: a 'forward' return type cannot return a temporary variable
21+
pure2-forward-return-diagnostics-error.cpp2(20,28): error: a 'forward' return type cannot return a temporary variable
22+
pure2-forward-return-diagnostics-error.cpp2(21,28): error: a 'forward' return type cannot return a temporary variable
23+
pure2-forward-return-diagnostics-error.cpp2(22,28): error: a 'forward' return type cannot return a temporary variable
24+

source/cppfront.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,6 +2189,15 @@ class cppfront
21892189
"a 'forward' return type cannot return a local variable"
21902190
);
21912191
return;
2192+
} else if (
2193+
is_literal(tok->type()) || n.expression->expr->is_result_a_temporary_variable()
2194+
)
2195+
{
2196+
errors.emplace_back(
2197+
n.position(),
2198+
"a 'forward' return type cannot return a temporary variable"
2199+
);
2200+
return;
21922201
}
21932202
}
21942203

source/parse.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ struct prefix_expression_node
195195
return expr.get();
196196
}
197197

198+
auto is_result_a_temporary_variable() const -> bool;
199+
198200
auto position() const -> source_position;
199201
auto visit(auto& v, int depth) -> void;
200202
};
@@ -257,6 +259,20 @@ struct binary_expression_node
257259
return { nullptr, nullptr };
258260
}
259261

262+
auto is_result_a_temporary_variable() const -> bool {
263+
if constexpr (std::string_view(Name.value) == "assignment") {
264+
assert(expr);
265+
return expr->is_result_a_temporary_variable();
266+
} else {
267+
if (terms.empty()) {
268+
assert(expr);
269+
return expr->is_result_a_temporary_variable();
270+
} else {
271+
return true;
272+
}
273+
}
274+
}
275+
260276
auto position() const
261277
-> source_position
262278
{
@@ -470,6 +486,15 @@ struct postfix_expression_node
470486
auto get_first_token_ignoring_this() const
471487
-> token const*;
472488

489+
auto is_result_a_temporary_variable() const -> bool {
490+
if (ops.empty()) {
491+
return false;
492+
} else {
493+
return (ops.front().op->type() == lexeme::Ampersand
494+
|| ops.front().op->type() == lexeme::Tilde);
495+
}
496+
}
497+
473498
// Internals
474499
//
475500
auto position() const -> source_position
@@ -481,6 +506,14 @@ struct postfix_expression_node
481506
auto visit(auto& v, int depth) -> void;
482507
};
483508

509+
auto prefix_expression_node::is_result_a_temporary_variable() const -> bool {
510+
if (ops.empty()) {
511+
return expr->is_result_a_temporary_variable();
512+
} else {
513+
return true;
514+
}
515+
}
516+
484517

485518
auto expression_node::get_lhs_rhs_if_simple_assignment() const
486519
-> assignment_expression_lhs_rhs
@@ -807,6 +840,15 @@ struct is_as_expression_node
807840
return expr->get_postfix_expression_node();
808841
}
809842

843+
auto is_result_a_temporary_variable() const -> bool {
844+
if (ops.empty()) {
845+
assert(expr);
846+
return expr->is_result_a_temporary_variable();
847+
} else {
848+
return true;
849+
}
850+
}
851+
810852
auto position() const
811853
-> source_position
812854
{

0 commit comments

Comments
 (0)