Skip to content

Commit bad1903

Browse files
committed
Disallow forward return of in or move parameter, addresses #248 comment
Addresses #248 (comment)
1 parent 937383f commit bad1903

File tree

2 files changed

+92
-10
lines changed

2 files changed

+92
-10
lines changed

source/cppfront.cpp

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2057,19 +2057,42 @@ class cppfront
20572057
//
20582058
if (n.expression)
20592059
{
2060-
auto tok = n.expression->expr->get_postfix_expression_node()->expr->get_token();
2061-
if (
2060+
assert(!current_functions.empty());
2061+
2062+
// If we're doing a forward return
2063+
if (auto tok = n.expression->expr->get_postfix_expression_node()->expr->get_token();
20622064
tok
2063-
&& sema.get_declaration_of(*tok)
20642065
&& !function_returns.empty()
20652066
&& function_returns.back().pass == passing_style::forward
20662067
)
20672068
{
2068-
errors.emplace_back(
2069-
n.position(),
2070-
"a 'forward' return type cannot return a local variable"
2071-
);
2072-
return;
2069+
// Ensure we're not returning a local or an in/move parameter
2070+
auto is_parameter_name = current_functions.back().decl->has_parameter_named(*tok);
2071+
if (
2072+
is_parameter_name
2073+
&& (
2074+
current_functions.back().decl->has_in_parameter_named(*tok)
2075+
|| current_functions.back().decl->has_move_parameter_named(*tok)
2076+
)
2077+
)
2078+
{
2079+
errors.emplace_back(
2080+
n.position(),
2081+
"a 'forward' return type cannot return an 'in' or 'move' parameter"
2082+
);
2083+
return;
2084+
}
2085+
else if (
2086+
!is_parameter_name
2087+
&& sema.get_declaration_of(*tok)
2088+
)
2089+
{
2090+
errors.emplace_back(
2091+
n.position(),
2092+
"a 'forward' return type cannot return a local variable"
2093+
);
2094+
return;
2095+
}
20732096
}
20742097

20752098
emit(*n.expression);

source/parse.h

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,13 +1415,27 @@ struct function_type_node
14151415
return returns.index() != empty;
14161416
}
14171417

1418-
auto has_out_parameter_named(std::string_view s) const
1418+
auto has_parameter_named(std::string_view s) const
1419+
-> bool
1420+
{
1421+
for (auto& param : parameters->parameters) {
1422+
if (param->has_name(s)) {
1423+
return true;
1424+
}
1425+
}
1426+
return false;
1427+
}
1428+
1429+
auto has_parameter_with_name_and_pass(
1430+
std::string_view s,
1431+
passing_style pass
1432+
) const
14191433
-> bool
14201434
{
14211435
for (auto& param : parameters->parameters) {
14221436
if (
14231437
param->has_name(s)
1424-
&& param->pass == passing_style::out
1438+
&& param->pass == pass
14251439
)
14261440
{
14271441
return true;
@@ -1430,6 +1444,24 @@ struct function_type_node
14301444
return false;
14311445
}
14321446

1447+
auto has_in_parameter_named(std::string_view s) const
1448+
-> bool
1449+
{
1450+
return has_parameter_with_name_and_pass(s, passing_style::in);
1451+
}
1452+
1453+
auto has_out_parameter_named(std::string_view s) const
1454+
-> bool
1455+
{
1456+
return has_parameter_with_name_and_pass(s, passing_style::out);
1457+
}
1458+
1459+
auto has_move_parameter_named(std::string_view s) const
1460+
-> bool
1461+
{
1462+
return has_parameter_with_name_and_pass(s, passing_style::move);
1463+
}
1464+
14331465
// Internals
14341466
//
14351467
auto position() const
@@ -1571,6 +1603,24 @@ struct declaration_node
15711603
;
15721604
}
15731605

1606+
auto has_parameter_named(std::string_view s) const
1607+
-> bool
1608+
{
1609+
if (!is_function()) {
1610+
return false;
1611+
}
1612+
return std::get<a_function>(type)->has_parameter_named(s);
1613+
}
1614+
1615+
auto has_in_parameter_named(std::string_view s) const
1616+
-> bool
1617+
{
1618+
if (!is_function()) {
1619+
return false;
1620+
}
1621+
return std::get<a_function>(type)->has_in_parameter_named(s);
1622+
}
1623+
15741624
auto has_out_parameter_named(std::string_view s) const
15751625
-> bool
15761626
{
@@ -1580,6 +1630,15 @@ struct declaration_node
15801630
return std::get<a_function>(type)->has_out_parameter_named(s);
15811631
}
15821632

1633+
auto has_move_parameter_named(std::string_view s) const
1634+
-> bool
1635+
{
1636+
if (!is_function()) {
1637+
return false;
1638+
}
1639+
return std::get<a_function>(type)->has_move_parameter_named(s);
1640+
}
1641+
15831642
auto is_function () const -> bool
15841643
{ return type.index() == a_function; }
15851644
auto is_object () const -> bool

0 commit comments

Comments
 (0)