Skip to content

Commit 43cdf3e

Browse files
committed
Disallow retuning a local for a -> forward return, addresses #248
1 parent 413de0e commit 43cdf3e

File tree

1 file changed

+41
-10
lines changed

1 file changed

+41
-10
lines changed

source/cppfront.cpp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -846,8 +846,20 @@ class cppfront
846846
bool in_parameter_list = false;
847847

848848
std::string function_return_name;
849-
std::vector<parameter_declaration_list_node*> function_returns;
850-
parameter_declaration_list_node single_anon;
849+
struct function_return {
850+
parameter_declaration_list_node* param_list;
851+
passing_style pass;
852+
853+
function_return(
854+
parameter_declaration_list_node* param_list_,
855+
passing_style pass_ = passing_style::invalid
856+
)
857+
: param_list{param_list_}
858+
, pass{pass_}
859+
{ }
860+
};
861+
std::vector<function_return> function_returns;
862+
parameter_declaration_list_node single_anon;
851863
// special value - hack for now to note single-anon-return type kind in this function_returns working list
852864
std::vector<std::string> function_requires_conditions;
853865

@@ -1858,11 +1870,27 @@ class cppfront
18581870

18591871
// Return with expression == single anonymous return type
18601872
//
1861-
if (n.expression) {
1873+
if (n.expression)
1874+
{
1875+
auto tok = n.expression->expr->get_postfix_expression_node()->expr->get_token();
1876+
if (
1877+
tok
1878+
&& sema.get_declaration_of(*tok)
1879+
&& !function_returns.empty()
1880+
&& function_returns.back().pass == passing_style::forward
1881+
)
1882+
{
1883+
errors.emplace_back(
1884+
n.position(),
1885+
"a 'forward' return type cannot return a local variable"
1886+
);
1887+
return;
1888+
}
1889+
18621890
emit(*n.expression);
18631891
if (
18641892
function_returns.empty()
1865-
|| function_returns.back() != &single_anon
1893+
|| function_returns.back().param_list != &single_anon
18661894
)
18671895
{
18681896
errors.emplace_back(
@@ -1875,7 +1903,7 @@ class cppfront
18751903

18761904
else if (
18771905
!function_returns.empty()
1878-
&& function_returns.back() == &single_anon
1906+
&& function_returns.back().param_list == &single_anon
18791907
)
18801908
{
18811909
errors.emplace_back(
@@ -1888,12 +1916,12 @@ class cppfront
18881916
//
18891917
else if (
18901918
!function_returns.empty()
1891-
&& function_returns.back()
1919+
&& function_returns.back().param_list
18921920
)
18931921
{
18941922
//auto stmt = function_return_name + " { "; // we shouldn't need this with { } init
18951923
auto stmt = std::string(" { ");
1896-
auto& parameters = function_returns.back()->parameters;
1924+
auto& parameters = function_returns.back().param_list->parameters;
18971925
for (bool first = true; auto& param : parameters) {
18981926
if (!first) {
18991927
stmt += ", ";
@@ -4000,13 +4028,16 @@ class cppfront
40004028

40014029
if (func->returns.index() == function_type_node::list) {
40024030
auto& r = std::get<function_type_node::list>(func->returns);
4003-
function_returns.push_back(r.get());
4031+
function_returns.emplace_back(r.get());
40044032
}
40054033
else if (func->returns.index() == function_type_node::id) {
4006-
function_returns.push_back(&single_anon); // use special value as a note
4034+
function_returns.emplace_back(
4035+
&single_anon, // use special value as a note
4036+
std::get<function_type_node::id>(func->returns).pass
4037+
);
40074038
}
40084039
else {
4009-
function_returns.push_back(nullptr); // no return type at all
4040+
function_returns.emplace_back(nullptr); // no return type at all
40104041
}
40114042

40124043
// Function body

0 commit comments

Comments
 (0)