Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions regression-tests/pure2-forward-return-diagnostics-error.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
fun1: () -> forward _ = { return global / 1; } // error: a 'forward' return type cannot return a temporary variable
fun4: () -> forward _ = { return global << 1; } // error: a 'forward' return type cannot return a temporary variable
fun5: () -> forward _ = { return global <=> 1; } // error: a 'forward' return type cannot return a temporary variable
fun6: () -> forward _ = { return global < 1; } // error: a 'forward' return type cannot return a temporary variable
fun7: () -> forward _ = { return global <= 1; } // error: a 'forward' return type cannot return a temporary variable
fun9: () -> forward _ = { return global >> 1; } // error: a 'forward' return type cannot return a temporary variable
fun10: () -> forward _ = { return global >= 1; } // error: a 'forward' return type cannot return a temporary variable
fun11: () -> forward _ = { return global > 1; } // error: a 'forward' return type cannot return a temporary variable
fun14: () -> forward _ = { return global + 1; } // error: a 'forward' return type cannot return a temporary variable
fun15: () -> forward _ = { return global - 1; } // error: a 'forward' return type cannot return a temporary variable
fun20: () -> forward _ = { return global || 1; } // error: a 'forward' return type cannot return a temporary variable
fun22: () -> forward _ = { return global | 1; } // error: a 'forward' return type cannot return a temporary variable
fun24: () -> forward _ = { return global && 1; } // error: a 'forward' return type cannot return a temporary variable
fun26: () -> forward _ = { return global * 1; } // error: a 'forward' return type cannot return a temporary variable
fun28: () -> forward _ = { return global % 1; } // error: a 'forward' return type cannot return a temporary variable
fun30: () -> forward _ = { return global & 1; } // error: a 'forward' return type cannot return a temporary variable
fun32: () -> forward _ = { return global ^ 1; } // error: a 'forward' return type cannot return a temporary variable
fun35: () -> forward _ = { return global == 1; } // error: a 'forward' return type cannot return a temporary variable
fun37: () -> forward _ = { return global != 1; } // error: a 'forward' return type cannot return a temporary variable
fun38: () -> forward _ = { return !ptr_g; } // error: a 'forward' return type cannot return a temporary variable
fun42: () -> forward _ = { return global&; } // error: a 'forward' return type cannot return a temporary variable
fun43: () -> forward _ = { return ptr_g~; } // error: a 'forward' return type cannot return a temporary variable

fun2: () -> forward _ = { return global /= 1; }
fun3: () -> forward _ = { return global <<= 1; }
fun8: () -> forward _ = { return global >>= 1; }
fun12: () -> forward _ = { return global++; }
fun13: () -> forward _ = { return global += 1; }
fun16: () -> forward _ = { return global -= 1; }
fun17: () -> forward _ = { return ptr_g*.x; }
fun18: () -> forward _ = { return global--; }
fun21: () -> forward _ = { return global |= 1; }
fun25: () -> forward _ = { return global *= 1; }
fun27: () -> forward _ = { return global %= 1; }
fun29: () -> forward _ = { return global &= 1; }
fun31: () -> forward _ = { return global ^= 1; }
fun36: () -> forward _ = { return global = 1; }
fun39: () -> forward _ = { return g.x; }
fun41: () -> forward _ = { return ptr_g*; }

// fun19: () -> forward _ = { return global ||= 1; } // not supported
// fun23: () -> forward _ = { return global &&= 1; } // not supported
// fun33: () -> forward _ = { return global ~= 1; } // not supported
// fun34: () -> forward _ = { return global ~ 1; } // not supported
// fun40: () -> forward _ = { return ptr_g ? ptr_g* : g; } // not supported

global: i32 = 42;
t: type = {
public x : int = 42;
}

g: t = ();
ptr_g: *t = g&;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pure2-forward-return-diagnostics-error.cpp2...
pure2-forward-return-diagnostics-error.cpp2(1,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(2,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(3,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(4,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(5,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(6,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(7,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(8,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(9,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(10,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(11,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(12,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(13,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(14,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(15,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(16,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(17,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(18,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(19,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(20,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(21,28): error: a 'forward' return type cannot return a temporary variable
pure2-forward-return-diagnostics-error.cpp2(22,28): error: a 'forward' return type cannot return a temporary variable

9 changes: 9 additions & 0 deletions source/cppfront.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2206,6 +2206,15 @@ class cppfront
"a 'forward' return type cannot return a local variable"
);
return;
} else if (
is_literal(tok->type()) || n.expression->expr->is_result_a_temporary_variable()
)
{
errors.emplace_back(
n.position(),
"a 'forward' return type cannot return a temporary variable"
);
return;
}
}

Expand Down
42 changes: 42 additions & 0 deletions source/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ struct prefix_expression_node
return expr.get();
}

auto is_result_a_temporary_variable() const -> bool;

auto position() const -> source_position;
auto visit(auto& v, int depth) -> void;
};
Expand Down Expand Up @@ -257,6 +259,20 @@ struct binary_expression_node
return { nullptr, nullptr };
}

auto is_result_a_temporary_variable() const -> bool {
if constexpr (std::string_view(Name.value) == "assignment") {
assert(expr);
return expr->is_result_a_temporary_variable();
} else {
if (terms.empty()) {
assert(expr);
return expr->is_result_a_temporary_variable();
} else {
return true;
}
}
}

auto position() const
-> source_position
{
Expand Down Expand Up @@ -470,6 +486,15 @@ struct postfix_expression_node
auto get_first_token_ignoring_this() const
-> token const*;

auto is_result_a_temporary_variable() const -> bool {
if (ops.empty()) {
return false;
} else {
return (ops.front().op->type() == lexeme::Ampersand
|| ops.front().op->type() == lexeme::Tilde);
}
}

// Internals
//
auto position() const -> source_position
Expand All @@ -481,6 +506,14 @@ struct postfix_expression_node
auto visit(auto& v, int depth) -> void;
};

auto prefix_expression_node::is_result_a_temporary_variable() const -> bool {
if (ops.empty()) {
return expr->is_result_a_temporary_variable();
} else {
return true;
}
}


auto expression_node::get_lhs_rhs_if_simple_assignment() const
-> assignment_expression_lhs_rhs
Expand Down Expand Up @@ -807,6 +840,15 @@ struct is_as_expression_node
return expr->get_postfix_expression_node();
}

auto is_result_a_temporary_variable() const -> bool {
if (ops.empty()) {
assert(expr);
return expr->is_result_a_temporary_variable();
} else {
return true;
}
}

auto position() const
-> source_position
{
Expand Down