mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
add error message for invalid assignment
This commit is contained in:
parent
beae932e0f
commit
f60e7348d5
4 changed files with 136 additions and 28 deletions
|
|
@ -2406,6 +2406,7 @@ struct ScopeDecls {
|
||||||
enum LVal {
|
enum LVal {
|
||||||
LValNone,
|
LValNone,
|
||||||
LValPtr,
|
LValPtr,
|
||||||
|
LValAssign,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This scope comes from a block expression in user code.
|
// This scope comes from a block expression in user code.
|
||||||
|
|
|
||||||
129
src/ir.cpp
129
src/ir.cpp
|
|
@ -5527,7 +5527,7 @@ static IrInstSrc *ir_gen_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
|
static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
|
||||||
IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
|
IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr);
|
||||||
if (lvalue == irb->codegen->invalid_inst_src)
|
if (lvalue == irb->codegen->invalid_inst_src)
|
||||||
return irb->codegen->invalid_inst_src;
|
return irb->codegen->invalid_inst_src;
|
||||||
|
|
||||||
|
|
@ -5546,7 +5546,7 @@ static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node)
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstSrc *ir_gen_assign_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
|
static IrInstSrc *ir_gen_assign_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
|
||||||
IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
|
IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr);
|
||||||
if (lvalue == irb->codegen->invalid_inst_src)
|
if (lvalue == irb->codegen->invalid_inst_src)
|
||||||
return lvalue;
|
return lvalue;
|
||||||
IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
|
IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
|
||||||
|
|
@ -5559,7 +5559,7 @@ static IrInstSrc *ir_gen_assign_merge_err_sets(IrBuilderSrc *irb, Scope *scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
static IrInstSrc *ir_gen_assign_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
|
static IrInstSrc *ir_gen_assign_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) {
|
||||||
IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr);
|
IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr);
|
||||||
if (lvalue == irb->codegen->invalid_inst_src)
|
if (lvalue == irb->codegen->invalid_inst_src)
|
||||||
return lvalue;
|
return lvalue;
|
||||||
IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
|
IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue);
|
||||||
|
|
@ -5908,7 +5908,7 @@ static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node,
|
||||||
Buf *variable_name = node->data.symbol_expr.symbol;
|
Buf *variable_name = node->data.symbol_expr.symbol;
|
||||||
|
|
||||||
if (buf_eql_str(variable_name, "_")) {
|
if (buf_eql_str(variable_name, "_")) {
|
||||||
if (lval == LValPtr) {
|
if (lval == LValAssign) {
|
||||||
IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, node);
|
IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, node);
|
||||||
const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>();
|
const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>();
|
||||||
const_instruction->value->type = get_pointer_to_type(irb->codegen,
|
const_instruction->value->type = get_pointer_to_type(irb->codegen,
|
||||||
|
|
@ -5933,7 +5933,7 @@ static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node,
|
||||||
assert(err == ErrorPrimitiveTypeNotFound);
|
assert(err == ErrorPrimitiveTypeNotFound);
|
||||||
} else {
|
} else {
|
||||||
IrInstSrc *value = ir_build_const_type(irb, scope, node, primitive_type);
|
IrInstSrc *value = ir_build_const_type(irb, scope, node, primitive_type);
|
||||||
if (lval == LValPtr) {
|
if (lval == LValPtr || lval == LValAssign) {
|
||||||
return ir_build_ref_src(irb, scope, node, value);
|
return ir_build_ref_src(irb, scope, node, value);
|
||||||
} else {
|
} else {
|
||||||
return ir_expr_wrap(irb, scope, value, result_loc);
|
return ir_expr_wrap(irb, scope, value, result_loc);
|
||||||
|
|
@ -5944,7 +5944,7 @@ static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node,
|
||||||
ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope);
|
ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope);
|
||||||
if (var) {
|
if (var) {
|
||||||
IrInstSrc *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope);
|
IrInstSrc *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope);
|
||||||
if (lval == LValPtr) {
|
if (lval == LValPtr || lval == LValAssign) {
|
||||||
return var_ptr;
|
return var_ptr;
|
||||||
} else {
|
} else {
|
||||||
return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc);
|
return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc);
|
||||||
|
|
@ -5954,7 +5954,7 @@ static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node,
|
||||||
Tld *tld = find_decl(irb->codegen, scope, variable_name);
|
Tld *tld = find_decl(irb->codegen, scope, variable_name);
|
||||||
if (tld) {
|
if (tld) {
|
||||||
IrInstSrc *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval);
|
IrInstSrc *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval);
|
||||||
if (lval == LValPtr) {
|
if (lval == LValPtr || lval == LValAssign) {
|
||||||
return decl_ref;
|
return decl_ref;
|
||||||
} else {
|
} else {
|
||||||
return ir_expr_wrap(irb, scope, decl_ref, result_loc);
|
return ir_expr_wrap(irb, scope, decl_ref, result_loc);
|
||||||
|
|
@ -5995,7 +5995,7 @@ static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode *
|
||||||
|
|
||||||
IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction,
|
IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction,
|
||||||
subscript_instruction, true, PtrLenSingle, nullptr);
|
subscript_instruction, true, PtrLenSingle, nullptr);
|
||||||
if (lval == LValPtr)
|
if (lval == LValPtr || lval == LValAssign)
|
||||||
return ptr_instruction;
|
return ptr_instruction;
|
||||||
|
|
||||||
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
|
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
|
||||||
|
|
@ -6754,7 +6754,7 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
|
||||||
IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node,
|
IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node,
|
||||||
arg0_value, arg1_value, false);
|
arg0_value, arg1_value, false);
|
||||||
|
|
||||||
if (lval == LValPtr)
|
if (lval == LValPtr || lval == LValAssign)
|
||||||
return ptr_instruction;
|
return ptr_instruction;
|
||||||
|
|
||||||
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
|
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
|
||||||
|
|
@ -7479,6 +7479,7 @@ static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(lval != LValAssign);
|
||||||
if (lval == LValPtr) {
|
if (lval == LValPtr) {
|
||||||
// We needed a pointer to a value, but we got a value. So we create
|
// We needed a pointer to a value, but we got a value. So we create
|
||||||
// an instruction which just makes a pointer of it.
|
// an instruction which just makes a pointer of it.
|
||||||
|
|
@ -9962,7 +9963,7 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope
|
||||||
IrInstSrc *ptr_instruction = ir_gen_field_access(irb, scope, node);
|
IrInstSrc *ptr_instruction = ir_gen_field_access(irb, scope, node);
|
||||||
if (ptr_instruction == irb->codegen->invalid_inst_src)
|
if (ptr_instruction == irb->codegen->invalid_inst_src)
|
||||||
return ptr_instruction;
|
return ptr_instruction;
|
||||||
if (lval == LValPtr)
|
if (lval == LValPtr || lval == LValAssign)
|
||||||
return ptr_instruction;
|
return ptr_instruction;
|
||||||
|
|
||||||
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
|
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction);
|
||||||
|
|
@ -9970,7 +9971,12 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope
|
||||||
}
|
}
|
||||||
case NodeTypePtrDeref: {
|
case NodeTypePtrDeref: {
|
||||||
AstNode *expr_node = node->data.ptr_deref_expr.target;
|
AstNode *expr_node = node->data.ptr_deref_expr.target;
|
||||||
IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr);
|
|
||||||
|
LVal child_lval = lval;
|
||||||
|
if (child_lval == LValAssign)
|
||||||
|
child_lval = LValPtr;
|
||||||
|
|
||||||
|
IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, child_lval, nullptr);
|
||||||
if (value == irb->codegen->invalid_inst_src)
|
if (value == irb->codegen->invalid_inst_src)
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
|
|
@ -9988,7 +9994,7 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope
|
||||||
return irb->codegen->invalid_inst_src;
|
return irb->codegen->invalid_inst_src;
|
||||||
|
|
||||||
IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true, false);
|
IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true, false);
|
||||||
if (lval == LValPtr)
|
if (lval == LValPtr || lval == LValAssign)
|
||||||
return unwrapped_ptr;
|
return unwrapped_ptr;
|
||||||
|
|
||||||
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
|
IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
|
||||||
|
|
@ -10068,6 +10074,97 @@ static ResultLoc *no_result_loc(void) {
|
||||||
static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval,
|
static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval,
|
||||||
ResultLoc *result_loc)
|
ResultLoc *result_loc)
|
||||||
{
|
{
|
||||||
|
if (lval == LValAssign) {
|
||||||
|
switch (node->type) {
|
||||||
|
case NodeTypeStructValueField:
|
||||||
|
case NodeTypeParamDecl:
|
||||||
|
case NodeTypeUsingNamespace:
|
||||||
|
case NodeTypeSwitchProng:
|
||||||
|
case NodeTypeSwitchRange:
|
||||||
|
case NodeTypeStructField:
|
||||||
|
case NodeTypeErrorSetField:
|
||||||
|
case NodeTypeFnDef:
|
||||||
|
case NodeTypeTestDecl:
|
||||||
|
zig_unreachable();
|
||||||
|
|
||||||
|
// cannot be assigned to
|
||||||
|
case NodeTypeBlock:
|
||||||
|
case NodeTypeGroupedExpr:
|
||||||
|
case NodeTypeBinOpExpr:
|
||||||
|
case NodeTypeIntLiteral:
|
||||||
|
case NodeTypeFloatLiteral:
|
||||||
|
case NodeTypeCharLiteral:
|
||||||
|
case NodeTypeIfBoolExpr:
|
||||||
|
case NodeTypeContainerInitExpr:
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
|
case NodeTypeWhileExpr:
|
||||||
|
case NodeTypeForExpr:
|
||||||
|
case NodeTypeReturnExpr:
|
||||||
|
case NodeTypeBoolLiteral:
|
||||||
|
case NodeTypeArrayType:
|
||||||
|
case NodeTypePointerType:
|
||||||
|
case NodeTypeAnyFrameType:
|
||||||
|
case NodeTypeStringLiteral:
|
||||||
|
case NodeTypeUndefinedLiteral:
|
||||||
|
case NodeTypeAsmExpr:
|
||||||
|
case NodeTypeNullLiteral:
|
||||||
|
case NodeTypeIfErrorExpr:
|
||||||
|
case NodeTypeIfOptional:
|
||||||
|
case NodeTypeSwitchExpr:
|
||||||
|
case NodeTypeCompTime:
|
||||||
|
case NodeTypeNoAsync:
|
||||||
|
case NodeTypeErrorType:
|
||||||
|
case NodeTypeBreak:
|
||||||
|
case NodeTypeContinue:
|
||||||
|
case NodeTypeUnreachable:
|
||||||
|
case NodeTypeDefer:
|
||||||
|
case NodeTypeSliceExpr:
|
||||||
|
case NodeTypeCatchExpr:
|
||||||
|
case NodeTypeContainerDecl:
|
||||||
|
case NodeTypeFnProto:
|
||||||
|
case NodeTypeErrorSetDecl:
|
||||||
|
case NodeTypeResume:
|
||||||
|
case NodeTypeAwaitExpr:
|
||||||
|
case NodeTypeSuspend:
|
||||||
|
case NodeTypeEnumLiteral:
|
||||||
|
case NodeTypeInferredArrayType:
|
||||||
|
case NodeTypeVarFieldType:
|
||||||
|
case NodeTypePrefixOpExpr:
|
||||||
|
add_node_error(irb->codegen, node,
|
||||||
|
buf_sprintf("invalid left-hand side to assignment"));
|
||||||
|
return irb->codegen->invalid_inst_src;
|
||||||
|
|
||||||
|
// @field can be assigned to
|
||||||
|
case NodeTypeFnCallExpr:
|
||||||
|
if (node->data.fn_call_expr.modifier == CallModifierBuiltin) {
|
||||||
|
AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
|
||||||
|
Buf *name = fn_ref_expr->data.symbol_expr.symbol;
|
||||||
|
auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
|
||||||
|
|
||||||
|
if (!entry) {
|
||||||
|
add_node_error(irb->codegen, node,
|
||||||
|
buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
|
||||||
|
return irb->codegen->invalid_inst_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->value->id == BuiltinFnIdField) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_node_error(irb->codegen, node,
|
||||||
|
buf_sprintf("invalid left-hand side to assignment"));
|
||||||
|
return irb->codegen->invalid_inst_src;
|
||||||
|
|
||||||
|
|
||||||
|
// can be assigned to
|
||||||
|
case NodeTypeUnwrapOptional:
|
||||||
|
case NodeTypePtrDeref:
|
||||||
|
case NodeTypeFieldAccessExpr:
|
||||||
|
case NodeTypeArrayAccessExpr:
|
||||||
|
case NodeTypeSymbol:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result_loc == nullptr) {
|
if (result_loc == nullptr) {
|
||||||
// Create a result location indicating there is none - but if one gets created
|
// Create a result location indicating there is none - but if one gets created
|
||||||
// it will be properly distributed.
|
// it will be properly distributed.
|
||||||
|
|
@ -20581,7 +20678,7 @@ static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *in
|
||||||
return ira->codegen->invalid_inst_gen;
|
return ira->codegen->invalid_inst_gen;
|
||||||
|
|
||||||
// If the result needs to be an lvalue, type check it
|
// If the result needs to be an lvalue, type check it
|
||||||
if (instruction->lval == LValPtr && result->value->type->id != ZigTypeIdPointer) {
|
if (instruction->lval != LValNone && result->value->type->id != ZigTypeIdPointer) {
|
||||||
ir_add_error(ira, &instruction->base.base,
|
ir_add_error(ira, &instruction->base.base,
|
||||||
buf_sprintf("attempt to dereference non-pointer type '%s'", buf_ptr(&result->value->type->name)));
|
buf_sprintf("attempt to dereference non-pointer type '%s'", buf_ptr(&result->value->type->name)));
|
||||||
return ira->codegen->invalid_inst_gen;
|
return ira->codegen->invalid_inst_gen;
|
||||||
|
|
@ -21175,7 +21272,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
} else if (return_type->data.pointer.explicit_alignment != 0) {
|
} else if (return_type->data.pointer.explicit_alignment != 0) {
|
||||||
uint32_t chosen_align;
|
uint32_t chosen_align;
|
||||||
if ((err = compute_elem_align(ira, return_type->data.pointer.child_type,
|
if ((err = compute_elem_align(ira, return_type->data.pointer.child_type,
|
||||||
return_type->data.pointer.explicit_alignment, index, &chosen_align)))
|
return_type->data.pointer.explicit_alignment, index, &chosen_align)))
|
||||||
{
|
{
|
||||||
return ira->codegen->invalid_inst_gen;
|
return ira->codegen->invalid_inst_gen;
|
||||||
|
|
@ -23348,7 +23445,7 @@ static IrInstGen *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstSrcRef *ref_i
|
||||||
IrInstGen *value = ref_instruction->value->child;
|
IrInstGen *value = ref_instruction->value->child;
|
||||||
if (type_is_invalid(value->value->type))
|
if (type_is_invalid(value->value->type))
|
||||||
return ira->codegen->invalid_inst_gen;
|
return ira->codegen->invalid_inst_gen;
|
||||||
|
|
||||||
bool is_const = false;
|
bool is_const = false;
|
||||||
bool is_volatile = false;
|
bool is_volatile = false;
|
||||||
|
|
||||||
|
|
@ -28878,7 +28975,7 @@ static IrInstGen *ir_analyze_instruction_decl_ref(IrAnalyze *ira, IrInstSrcDeclR
|
||||||
return ira->codegen->invalid_inst_gen;
|
return ira->codegen->invalid_inst_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instruction->lval == LValPtr) {
|
if (instruction->lval == LValPtr || instruction->lval == LValAssign) {
|
||||||
return ref_instruction;
|
return ref_instruction;
|
||||||
} else {
|
} else {
|
||||||
return ir_get_deref(ira, &instruction->base.base, ref_instruction, nullptr);
|
return ir_get_deref(ira, &instruction->base.base, ref_instruction, nullptr);
|
||||||
|
|
|
||||||
|
|
@ -2175,7 +2175,7 @@ static void ir_print_ptr_type(IrPrintSrc *irp, IrInstSrcPtrType *instruction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ir_print_decl_ref(IrPrintSrc *irp, IrInstSrcDeclRef *instruction) {
|
static void ir_print_decl_ref(IrPrintSrc *irp, IrInstSrcDeclRef *instruction) {
|
||||||
const char *ptr_str = (instruction->lval == LValPtr) ? "ptr " : "";
|
const char *ptr_str = (instruction->lval != LValNone) ? "ptr " : "";
|
||||||
fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name));
|
fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,24 @@ const tests = @import("tests.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
|
cases.addTest("invalid assignments",
|
||||||
|
\\export fn entry1() void {
|
||||||
|
\\ var a: []const u8 = "foo";
|
||||||
|
\\ a[0..2] = "bar";
|
||||||
|
\\}
|
||||||
|
\\export fn entry2() void {
|
||||||
|
\\ var a: u8 = 2;
|
||||||
|
\\ a + 2 = 3;
|
||||||
|
\\}
|
||||||
|
\\export fn entry4() void {
|
||||||
|
\\ 2 + 2 = 3;
|
||||||
|
\\}
|
||||||
|
, &[_][]const u8{
|
||||||
|
"tmp.zig:3:6: error: invalid left-hand side to assignment",
|
||||||
|
"tmp.zig:7:7: error: invalid left-hand side to assignment",
|
||||||
|
"tmp.zig:10:7: error: invalid left-hand side to assignment",
|
||||||
|
});
|
||||||
|
|
||||||
cases.addTest("reassign to array parameter",
|
cases.addTest("reassign to array parameter",
|
||||||
\\fn reassign(a: [3]f32) void {
|
\\fn reassign(a: [3]f32) void {
|
||||||
\\ a = [3]f32{4, 5, 6};
|
\\ a = [3]f32{4, 5, 6};
|
||||||
|
|
@ -10,7 +28,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\ reassign(.{1, 2, 3});
|
\\ reassign(.{1, 2, 3});
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:2:15: error: cannot assign to constant"
|
"tmp.zig:2:15: error: cannot assign to constant",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.addTest("reassign to slice parameter",
|
cases.addTest("reassign to slice parameter",
|
||||||
|
|
@ -21,7 +39,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\ reassign("foo");
|
\\ reassign("foo");
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:2:10: error: cannot assign to constant"
|
"tmp.zig:2:10: error: cannot assign to constant",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.addTest("reassign to struct parameter",
|
cases.addTest("reassign to struct parameter",
|
||||||
|
|
@ -35,7 +53,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
\\ reassign(S{.x = 3});
|
\\ reassign(S{.x = 3});
|
||||||
\\}
|
\\}
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
"tmp.zig:5:10: error: cannot assign to constant"
|
"tmp.zig:5:10: error: cannot assign to constant",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.addTest("reference to const data",
|
cases.addTest("reference to const data",
|
||||||
|
|
@ -3862,14 +3880,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||||
"tmp.zig:1:9: error: parameter of type 'noreturn' not allowed",
|
"tmp.zig:1:9: error: parameter of type 'noreturn' not allowed",
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.add("bad assignment target",
|
|
||||||
\\export fn f() void {
|
|
||||||
\\ 3 = 3;
|
|
||||||
\\}
|
|
||||||
, &[_][]const u8{
|
|
||||||
"tmp.zig:2:9: error: cannot assign to constant",
|
|
||||||
});
|
|
||||||
|
|
||||||
cases.add("assign to constant variable",
|
cases.add("assign to constant variable",
|
||||||
\\export fn f() void {
|
\\export fn f() void {
|
||||||
\\ const a = 3;
|
\\ const a = 3;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue