diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index a4d0d062accc..c91cc049215f 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -1015,5 +1015,51 @@ HIRCompileBase::unit_expression (location_t locus) return Backend::constructor_expression (unit_type, false, {}, -1, locus); } +bool +HIRCompileBase::is_lvalue (const_tree ref) +{ + const enum tree_code code = TREE_CODE (ref); + + switch (code) + { + case REALPART_EXPR: + case IMAGPART_EXPR: + case COMPONENT_REF: + return is_lvalue (TREE_OPERAND (ref, 0)); + + case COMPOUND_LITERAL_EXPR: + case STRING_CST: + case CONST_DECL: + case INTEGER_CST: + return true; + + case MEM_REF: + case TARGET_MEM_REF: + /* MEM_REFs can appear from -fgimple parsing or folding, so allow them + here as well. */ + case INDIRECT_REF: + case ARRAY_REF: + case VAR_DECL: + case PARM_DECL: + case RESULT_DECL: + case ERROR_MARK: + return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE); + + case BIND_EXPR: + return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case POINTER_PLUS_EXPR: + case POINTER_DIFF_EXPR: + case MULT_HIGHPART_EXPR: + case TRUNC_DIV_EXPR: + return false; + default: + return false; + } +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 3c50535552f5..6cb7a5c82f78 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -30,6 +30,7 @@ class HIRCompileBase virtual ~HIRCompileBase () {} static tree address_expression (tree expr, location_t locus); + bool is_lvalue (const_tree ref); protected: HIRCompileBase (Context *ctx) : ctx (ctx) {} diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 7323413bfce2..18e97b853d60 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -964,6 +964,17 @@ CompileExpr::visit (HIR::AssignmentExpr &expr) auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx); auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx); + bool validl_value = is_lvalue (lvalue); + + if (!validl_value + || expr.get_lhs ().get_expression_type () + == HIR::Expr::ExprType::Operator) + { + rust_error_at (expr.get_lhs ().get_locus (), ErrorCode::E0770, + "invalid left-hand side of assignment"); + return; + } + // assignments are coercion sites so lets convert the rvalue if necessary TyTy::BaseType *expected = nullptr; TyTy::BaseType *actual = nullptr; diff --git a/gcc/testsuite/rust/compile/issue-3297.rs b/gcc/testsuite/rust/compile/issue-3297.rs new file mode 100644 index 000000000000..10ddc86d98ba --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3297.rs @@ -0,0 +1,4 @@ +pub fn main() { + let mut x = 42; + x + 1= 2; // { dg-error "invalid left-hand side of assignment" } +} \ No newline at end of file