diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 7323413bfce2..1a3ba1961e03 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -958,12 +958,71 @@ CompileExpr::visit (HIR::LiteralExpr &expr) } } +bool +lvalue_p (const_tree ref) +{ + const enum tree_code code = TREE_CODE (ref); + + switch (code) + { + case REALPART_EXPR: + case IMAGPART_EXPR: + case COMPONENT_REF: + return lvalue_p (TREE_OPERAND (ref, 0)); + + case C_MAYBE_CONST_EXPR: + return lvalue_p (TREE_OPERAND (ref, 1)); + + 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: + rust_debug ("unknown"); + return false; + } +} + void CompileExpr::visit (HIR::AssignmentExpr &expr) { auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx); auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx); + if (!lvalue_p (lvalue) + || expr.get_lhs ().get_expression_type () + == HIR::Expr::ExprType::Operator) + { + rust_error_at (expr.get_lhs ().get_locus (), + "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-3287.rs b/gcc/testsuite/rust/compile/issue-3287.rs new file mode 100644 index 000000000000..c1ea9f63af64 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3287.rs @@ -0,0 +1,12 @@ +extern "C" { + fn printf(s: *const i8, ...); +} + +pub fn main() { + unsafe { + let mut x = 42; + x + 1= 2; // { dg-error "invalid left-hand side of assignment" } + let format = "Result: %d\n\0" as *const str as *const i8; + printf(format, x); + } +} \ No newline at end of file