fix regression on struct field with undefined type
This commit is contained in:
parent
73a7747a9c
commit
d316f70450
|
@ -961,18 +961,14 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
|
|||
return entry;
|
||||
}
|
||||
|
||||
ConstExprValue *analyze_const_value_allow_lazy(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
|
||||
Buf *type_name, bool allow_lazy)
|
||||
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
|
||||
Buf *type_name, UndefAllowed undef)
|
||||
{
|
||||
size_t backward_branch_count = 0;
|
||||
size_t backward_branch_quota = default_backward_branch_quota;
|
||||
return ir_eval_const_value(g, scope, node, type_entry,
|
||||
&backward_branch_count, &backward_branch_quota,
|
||||
nullptr, nullptr, node, type_name, nullptr, nullptr, allow_lazy);
|
||||
}
|
||||
|
||||
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {
|
||||
return analyze_const_value_allow_lazy(g, scope, node, type_entry, type_name, false);
|
||||
nullptr, nullptr, node, type_name, nullptr, nullptr, undef);
|
||||
}
|
||||
|
||||
static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type,
|
||||
|
@ -1162,22 +1158,12 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons
|
|||
}
|
||||
|
||||
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
|
||||
ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
|
||||
ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type,
|
||||
nullptr, UndefBad);
|
||||
if (type_is_invalid(result->type))
|
||||
return g->builtin_types.entry_invalid;
|
||||
|
||||
assert(result->special != ConstValSpecialRuntime);
|
||||
// Reject undefined as valid `type` type even though the specification
|
||||
// allows it to be casted to anything.
|
||||
// See also ir_resolve_type()
|
||||
if (result->special == ConstValSpecialUndef) {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("expected type 'type', found '%s'",
|
||||
buf_ptr(&g->builtin_types.entry_undef->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
assert(result->data.x_type != nullptr);
|
||||
src_assert(result->special == ConstValSpecialStatic, node);
|
||||
src_assert(result->data.x_type != nullptr, node);
|
||||
return result->data.x_type;
|
||||
}
|
||||
|
||||
|
@ -1225,7 +1211,8 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
|
|||
}
|
||||
|
||||
static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
|
||||
ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
|
||||
ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g),
|
||||
nullptr, UndefBad);
|
||||
if (type_is_invalid(align_result->type))
|
||||
return false;
|
||||
|
||||
|
@ -1247,7 +1234,7 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
|
|||
ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, 0, 0, 0, false);
|
||||
ZigType *str_type = get_slice_type(g, ptr_type);
|
||||
ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
|
||||
ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr, UndefBad);
|
||||
if (type_is_invalid(result_val->type))
|
||||
return false;
|
||||
|
||||
|
@ -2261,7 +2248,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
|||
|
||||
if (tag_value != nullptr) {
|
||||
// A user-specified value is available
|
||||
ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
|
||||
ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
|
||||
nullptr, UndefBad);
|
||||
if (type_is_invalid(result->type)) {
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
continue;
|
||||
|
@ -2377,8 +2365,8 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
|
|||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
ConstExprValue *field_type_val = analyze_const_value_allow_lazy(g, scope,
|
||||
field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, true);
|
||||
ConstExprValue *field_type_val = analyze_const_value(g, scope,
|
||||
field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
|
||||
if (type_is_invalid(field_type_val->type)) {
|
||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
|
@ -2660,8 +2648,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
|||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
} else {
|
||||
ConstExprValue *field_type_val = analyze_const_value_allow_lazy(g, scope,
|
||||
field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, true);
|
||||
ConstExprValue *field_type_val = analyze_const_value(g, scope,
|
||||
field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef);
|
||||
if (type_is_invalid(field_type_val->type)) {
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
|
@ -2726,7 +2714,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
|||
// In a second pass we will fill in the unspecified ones.
|
||||
if (tag_value != nullptr) {
|
||||
ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
|
||||
ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
|
||||
ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
|
||||
nullptr, UndefBad);
|
||||
if (type_is_invalid(result->type)) {
|
||||
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
|
@ -2929,7 +2918,7 @@ void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
|
|||
fake_decl->data.symbol_expr.symbol = tld_fn->base.name;
|
||||
|
||||
// call this for the side effects of casting to panic_fn_type
|
||||
analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
|
||||
analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr, UndefBad);
|
||||
}
|
||||
|
||||
ZigType *get_test_fn_type(CodeGen *g) {
|
||||
|
@ -3075,7 +3064,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
|
|||
static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
|
||||
assert(tld_comptime->base.source_node->type == NodeTypeCompTime);
|
||||
AstNode *expr_node = tld_comptime->base.source_node->data.comptime_expr.expr;
|
||||
analyze_const_value(g, tld_comptime->base.parent_scope, expr_node, g->builtin_types.entry_void, nullptr);
|
||||
analyze_const_value(g, tld_comptime->base.parent_scope, expr_node, g->builtin_types.entry_void,
|
||||
nullptr, UndefBad);
|
||||
}
|
||||
|
||||
static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
|
||||
|
@ -3443,8 +3433,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
|
|||
if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {
|
||||
implicit_type = explicit_type;
|
||||
} else if (var_decl->expr) {
|
||||
init_value = analyze_const_value_allow_lazy(g, tld_var->base.parent_scope, var_decl->expr, explicit_type,
|
||||
var_decl->symbol, allow_lazy);
|
||||
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type,
|
||||
var_decl->symbol, allow_lazy ? LazyOk : UndefOk);
|
||||
assert(init_value);
|
||||
implicit_type = init_value->type;
|
||||
|
||||
|
@ -3599,7 +3589,8 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
|
|||
using_namespace->base.resolution = TldResolutionResolving;
|
||||
assert(using_namespace->base.source_node->type == NodeTypeUsingNamespace);
|
||||
ConstExprValue *result = analyze_const_value(g, &dest_decls_scope->base,
|
||||
using_namespace->base.source_node->data.using_namespace.expr, g->builtin_types.entry_type, nullptr);
|
||||
using_namespace->base.source_node->data.using_namespace.expr, g->builtin_types.entry_type,
|
||||
nullptr, UndefBad);
|
||||
using_namespace->using_namespace_value = result;
|
||||
|
||||
if (type_is_invalid(result->type)) {
|
||||
|
|
|
@ -240,9 +240,8 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
|
|||
|
||||
void src_assert(bool ok, AstNode *source_node);
|
||||
bool is_container(ZigType *type_entry);
|
||||
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
|
||||
ConstExprValue *analyze_const_value_allow_lazy(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
|
||||
Buf *type_name, bool allow_lazy);
|
||||
ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
|
||||
Buf *type_name, UndefAllowed undef);
|
||||
|
||||
void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
|
||||
bool fn_is_async(ZigFn *fn);
|
||||
|
|
24
src/ir.cpp
24
src/ir.cpp
|
@ -398,7 +398,7 @@ static void ir_ref_var(ZigVar *var) {
|
|||
ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) {
|
||||
ConstExprValue *result = ir_eval_const_value(ira->codegen, scope, node, ira->codegen->builtin_types.entry_type,
|
||||
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, nullptr,
|
||||
node, nullptr, ira->new_irb.exec, nullptr, false);
|
||||
node, nullptr, ira->new_irb.exec, nullptr, UndefBad);
|
||||
|
||||
if (type_is_invalid(result->type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
@ -10734,14 +10734,14 @@ static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode
|
|||
buf_sprintf("unable to evaluate constant expression"));
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
case ConstValSpecialUndef:
|
||||
if (undef_allowed == UndefOk)
|
||||
if (undef_allowed == UndefOk || undef_allowed == LazyOk)
|
||||
return ErrorNone;
|
||||
|
||||
exec_add_error_node(codegen, exec, source_node,
|
||||
buf_sprintf("use of undefined value here causes undefined behavior"));
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
case ConstValSpecialLazy:
|
||||
if (undef_allowed == LazyOk)
|
||||
if (undef_allowed == LazyOk || undef_allowed == LazyOkNoUndef)
|
||||
return ErrorNone;
|
||||
|
||||
if ((err = ir_resolve_lazy(codegen, source_node, val)))
|
||||
|
@ -10765,7 +10765,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
|
|||
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
|
||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy)
|
||||
IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed)
|
||||
{
|
||||
Error err;
|
||||
|
||||
|
@ -10819,11 +10819,8 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
|
|||
|
||||
ConstExprValue *result = ir_exec_const_result(codegen, analyzed_executable);
|
||||
|
||||
if (!allow_lazy) {
|
||||
if ((err = ir_resolve_lazy(codegen, node, result))) {
|
||||
return &codegen->invalid_instruction->value;
|
||||
}
|
||||
}
|
||||
if ((err = ir_resolve_const_val(codegen, analyzed_executable, node, result, undef_allowed)))
|
||||
return &codegen->invalid_instruction->value;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -15578,7 +15575,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
|
|||
AstNode *body_node = fn_entry->body_node;
|
||||
result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
|
||||
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
|
||||
nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node, false);
|
||||
nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node,
|
||||
UndefOk);
|
||||
|
||||
if (inferred_err_set_type != nullptr) {
|
||||
inferred_err_set_type->data.error_set.infer_fn = nullptr;
|
||||
|
@ -15776,7 +15774,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
|
|||
fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
|
||||
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
|
||||
nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec,
|
||||
nullptr, false);
|
||||
nullptr, UndefBad);
|
||||
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
|
||||
impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
|
||||
copy_const_val(&const_instruction->base.value, align_result, true);
|
||||
|
@ -19129,7 +19127,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
|
|||
Scope *analyze_scope = &get_container_scope(container_type)->base;
|
||||
// memoize it
|
||||
field->init_val = analyze_const_value(ira->codegen, analyze_scope, init_node,
|
||||
field->type_entry, nullptr);
|
||||
field->type_entry, nullptr, UndefOk);
|
||||
}
|
||||
if (type_is_invalid(field->init_val->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
@ -20640,7 +20638,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
|
|||
ZigType *void_type = ira->codegen->builtin_types.entry_void;
|
||||
ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
|
||||
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
|
||||
&cimport_scope->buf, block_node, nullptr, nullptr, nullptr, false);
|
||||
&cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad);
|
||||
if (type_is_invalid(cimport_result->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
|
|||
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
|
||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy);
|
||||
IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
|
||||
|
||||
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val);
|
||||
|
||||
|
|
|
@ -404,7 +404,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
|||
\\ const foo: Foo = undefined;
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:2:8: error: expected type 'type', found '(undefined)'",
|
||||
"tmp.zig:2:8: error: use of undefined value here causes undefined behavior",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
|
Loading…
Reference in New Issue
Block a user