@@ -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