aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-08-27 13:02:31 -0400
committerGitHub <noreply@github.com>2019-08-27 13:02:31 -0400
commit35a374efe034ae5ed9aafc06bbc581044e7325de (patch)
tree41f0fdd7555532dab92e38fb8afc58aa96ccdf61 /src/analyze.cpp
parent326b7b794b01a1194df3785e497460bada756c29 (diff)
parentd9ed55f017bdd23054cd1d7f50ac1da517b5a5e4 (diff)
downloadzig-35a374efe034ae5ed9aafc06bbc581044e7325de.tar.gz
zig-35a374efe034ae5ed9aafc06bbc581044e7325de.zip
Merge pull request #3115 from ziglang/fix-field-alignment-kludge
fix field alignment kludge by implementing lazy values
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp1153
1 files changed, 698 insertions, 455 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 35c598ab97..e0223dd9f7 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -20,7 +20,7 @@
static const size_t default_backward_branch_quota = 1000;
-static Error resolve_struct_type(CodeGen *g, ZigType *struct_type);
+static Error ATTRIBUTE_MUST_USE resolve_struct_type(CodeGen *g, ZigType *struct_type);
static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);
static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type);
@@ -59,13 +59,15 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) {
root_struct->source_code, root_struct->line_offsets, msg);
g->errors.append(err);
+ g->trace_err = err;
return err;
}
-ErrorMsg *add_node_error(CodeGen *g, const AstNode *node, Buf *msg) {
+ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
Token fake_token;
fake_token.start_line = node->line;
fake_token.start_column = node->column;
+ node->already_traced_this_node = true;
return add_token_error(g, node->owner, &fake_token, msg);
}
@@ -271,6 +273,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
return type_entry->data.structure.resolve_status >= status;
case ZigTypeIdUnion:
return type_entry->data.unionation.resolve_status >= status;
+ case ZigTypeIdEnum:
+ return type_entry->data.enumeration.resolve_status >= status;
case ZigTypeIdFnFrame:
switch (status) {
case ResolveStatusInvalid:
@@ -285,32 +289,28 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
case ResolveStatusLLVMFull:
return type_entry->llvm_type != nullptr;
}
- case ZigTypeIdEnum:
+ case ZigTypeIdOpaque:
+ return status < ResolveStatusSizeKnown;
+ case ZigTypeIdPointer:
switch (status) {
- case ResolveStatusUnstarted:
- return true;
case ResolveStatusInvalid:
zig_unreachable();
+ case ResolveStatusUnstarted:
+ return true;
case ResolveStatusZeroBitsKnown:
- return type_entry->data.enumeration.zero_bits_known;
case ResolveStatusAlignmentKnown:
- return type_entry->data.enumeration.zero_bits_known;
case ResolveStatusSizeKnown:
- return type_entry->data.enumeration.complete;
+ return type_entry->abi_size != SIZE_MAX;
case ResolveStatusLLVMFwdDecl:
case ResolveStatusLLVMFull:
- return type_entry->llvm_di_type != nullptr;
+ return type_entry->llvm_type != nullptr;
}
- zig_unreachable();
- case ZigTypeIdOpaque:
- return status < ResolveStatusSizeKnown;
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdUnreachable:
case ZigTypeIdInt:
case ZigTypeIdFloat:
- case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
@@ -460,8 +460,6 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
}
}
- assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));
-
ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
const char *star_str = ptr_len_to_star_str(ptr_len);
@@ -491,17 +489,21 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
buf_ptr(&child_type->name));
}
- assert(child_type->id != ZigTypeIdInvalid);
-
- if (type_has_bits(child_type)) {
- entry->abi_size = g->builtin_types.entry_usize->abi_size;
- entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
- entry->abi_align = g->builtin_types.entry_usize->abi_align;
+ if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
+ if (type_has_bits(child_type)) {
+ entry->abi_size = g->builtin_types.entry_usize->abi_size;
+ entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
+ entry->abi_align = g->builtin_types.entry_usize->abi_align;
+ } else {
+ assert(byte_alignment == 0);
+ entry->abi_size = 0;
+ entry->size_in_bits = 0;
+ entry->abi_align = 0;
+ }
} else {
- assert(byte_alignment == 0);
- entry->abi_size = 0;
- entry->size_in_bits = 0;
- entry->abi_align = 0;
+ entry->abi_size = SIZE_MAX;
+ entry->size_in_bits = SIZE_MAX;
+ entry->abi_align = UINT32_MAX;
}
entry->data.pointer.ptr_len = ptr_len;
@@ -865,7 +867,7 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
return table_entry->value;
}
if (fn_type_id->return_type != nullptr) {
- if ((err = ensure_complete_type(g, fn_type_id->return_type)))
+ if ((err = type_resolve(g, fn_type_id->return_type, ResolveStatusSizeKnown)))
return g->builtin_types.entry_invalid;
assert(fn_type_id->return_type->id != ZigTypeIdOpaque);
} else {
@@ -960,31 +962,209 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
return entry;
}
-ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {
+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);
+ nullptr, nullptr, node, type_name, nullptr, nullptr, undef);
}
-ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
- ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
- if (type_is_invalid(result->type))
- return g->builtin_types.entry_invalid;
+static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type,
+ ConstExprValue *parent_type_val, bool *is_zero_bits)
+{
+ Error err;
+ if (type_val->special != ConstValSpecialLazy) {
+ assert(type_val->special == ConstValSpecialStatic);
+ if ((type_val->data.x_type->id == ZigTypeIdStruct &&
+ type_val->data.x_type->data.structure.resolve_loop_flag_zero_bits) ||
+ (type_val->data.x_type->id == ZigTypeIdUnion &&
+ type_val->data.x_type->data.unionation.resolve_loop_flag_zero_bits) ||
+ type_val->data.x_type->id == ZigTypeIdPointer)
+ {
+ // Does a struct/union which contains a pointer field to itself have bits? Yes.
+ *is_zero_bits = false;
+ return ErrorNone;
+ }
+ if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown)))
+ return err;
+ *is_zero_bits = (type_val->data.x_type->abi_size == 0);
+ return ErrorNone;
+ }
+ switch (type_val->data.x_lazy->id) {
+ case LazyValueIdInvalid:
+ case LazyValueIdAlignOf:
+ zig_unreachable();
+ case LazyValueIdPtrType: {
+ LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
- 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;
+ if (parent_type_val == &lazy_ptr_type->elem_type->value) {
+ // Does a struct which contains a pointer field to itself have bits? Yes.
+ *is_zero_bits = false;
+ return ErrorNone;
+ } else {
+ if (parent_type_val == nullptr) {
+ parent_type_val = type_val;
+ }
+ return type_val_resolve_zero_bits(g, &lazy_ptr_type->elem_type->value, parent_type,
+ parent_type_val, is_zero_bits);
+ }
+ }
+ case LazyValueIdOptType:
+ case LazyValueIdSliceType:
+ *is_zero_bits = false;
+ return ErrorNone;
+ case LazyValueIdFnType: {
+ LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
+ *is_zero_bits = lazy_fn_type->is_generic;
+ return ErrorNone;
+ }
+ }
+ zig_unreachable();
+}
+
+Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
+ if (type_val->special != ConstValSpecialLazy) {
+ assert(type_val->special == ConstValSpecialStatic);
+ *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
+ return ErrorNone;
+ }
+ switch (type_val->data.x_lazy->id) {
+ case LazyValueIdInvalid:
+ case LazyValueIdAlignOf:
+ zig_unreachable();
+ case LazyValueIdSliceType:
+ case LazyValueIdPtrType:
+ case LazyValueIdFnType:
+ case LazyValueIdOptType:
+ *is_opaque_type = false;
+ return ErrorNone;
}
+ zig_unreachable();
+}
- assert(result->data.x_type != nullptr);
+static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val) {
+ if (type_val->special != ConstValSpecialLazy) {
+ return type_requires_comptime(g, type_val->data.x_type);
+ }
+ switch (type_val->data.x_lazy->id) {
+ case LazyValueIdInvalid:
+ case LazyValueIdAlignOf:
+ zig_unreachable();
+ case LazyValueIdSliceType: {
+ LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
+ if (type_is_invalid(lazy_slice_type->elem_type))
+ return ReqCompTimeInvalid;
+ return type_requires_comptime(g, lazy_slice_type->elem_type);
+ }
+ case LazyValueIdPtrType: {
+ LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
+ return type_val_resolve_requires_comptime(g, &lazy_ptr_type->elem_type->value);
+ }
+ case LazyValueIdOptType: {
+ LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
+ return type_val_resolve_requires_comptime(g, &lazy_opt_type->payload_type->value);
+ }
+ case LazyValueIdFnType: {
+ LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
+ if (lazy_fn_type->is_generic)
+ return ReqCompTimeYes;
+ switch (type_val_resolve_requires_comptime(g, &lazy_fn_type->return_type->value)) {
+ case ReqCompTimeInvalid:
+ return ReqCompTimeInvalid;
+ case ReqCompTimeYes:
+ return ReqCompTimeYes;
+ case ReqCompTimeNo:
+ break;
+ }
+ size_t param_count = lazy_fn_type->proto_node->data.fn_proto.params.length;
+ for (size_t i = 0; i < param_count; i += 1) {
+ AstNode *param_node = lazy_fn_type->proto_node->data.fn_proto.params.at(i);
+ bool param_is_var_args = param_node->data.param_decl.is_var_args;
+ if (param_is_var_args) break;
+ switch (type_val_resolve_requires_comptime(g, &lazy_fn_type->param_types[i]->value)) {
+ case ReqCompTimeInvalid:
+ return ReqCompTimeInvalid;
+ case ReqCompTimeYes:
+ return ReqCompTimeYes;
+ case ReqCompTimeNo:
+ break;
+ }
+ }
+ return ReqCompTimeNo;
+ }
+ }
+ zig_unreachable();
+}
+
+Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t *abi_align) {
+ Error err;
+ if (type_val->special != ConstValSpecialLazy) {
+ assert(type_val->special == ConstValSpecialStatic);
+ ZigType *ty = type_val->data.x_type;
+ if (ty->id == ZigTypeIdPointer) {
+ *abi_align = g->builtin_types.entry_usize->abi_align;
+ return ErrorNone;
+ }
+ if ((err = type_resolve(g, ty, ResolveStatusAlignmentKnown)))
+ return err;
+ *abi_align = ty->abi_align;
+ return ErrorNone;
+ }
+ switch (type_val->data.x_lazy->id) {
+ case LazyValueIdInvalid:
+ case LazyValueIdAlignOf:
+ zig_unreachable();
+ case LazyValueIdSliceType:
+ case LazyValueIdPtrType:
+ case LazyValueIdFnType:
+ *abi_align = g->builtin_types.entry_usize->abi_align;
+ return ErrorNone;
+ case LazyValueIdOptType: {
+ LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
+ return type_val_resolve_abi_align(g, &lazy_opt_type->payload_type->value, abi_align);
+ }
+ }
+ zig_unreachable();
+}
+
+static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ConstExprValue *type_val) {
+ if (type_val->special != ConstValSpecialLazy) {
+ return type_has_one_possible_value(g, type_val->data.x_type);
+ }
+ switch (type_val->data.x_lazy->id) {
+ case LazyValueIdInvalid:
+ case LazyValueIdAlignOf:
+ zig_unreachable();
+ case LazyValueIdSliceType: // it has the len field
+ case LazyValueIdOptType: // it has the optional bit
+ case LazyValueIdFnType:
+ return OnePossibleValueNo;
+ case LazyValueIdPtrType: {
+ Error err;
+ bool zero_bits;
+ if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, nullptr, &zero_bits))) {
+ return OnePossibleValueInvalid;
+ }
+ if (zero_bits) {
+ return OnePossibleValueYes;
+ } else {
+ return OnePossibleValueNo;
+ }
+ }
+ }
+ zig_unreachable();
+}
+
+ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
+ 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;
+ src_assert(result->special == ConstValSpecialStatic, node);
+ src_assert(result->data.x_type != nullptr, node);
return result->data.x_type;
}
@@ -1032,7 +1212,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;
@@ -1054,7 +1235,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;
@@ -1404,7 +1585,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
add_node_error(g, proto_node,
buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
return g->builtin_types.entry_invalid;
- //return get_generic_fn_type(g, &fn_type_id);
}
ZigType *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type);
@@ -1423,14 +1603,17 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
}
if (!calling_convention_allows_zig_types(fn_type_id.cc) &&
- fn_type_id.return_type->id != ZigTypeIdVoid &&
- !type_allowed_in_extern(g, fn_type_id.return_type))
+ fn_type_id.return_type->id != ZigTypeIdVoid)
{
- add_node_error(g, fn_proto->return_type,
- buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
- buf_ptr(&fn_type_id.return_type->name),
- calling_convention_name(fn_type_id.cc)));
- return g->builtin_types.entry_invalid;
+ if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))
+ return g->builtin_types.entry_invalid;
+ if (!type_allowed_in_extern(g, fn_type_id.return_type)) {
+ add_node_error(g, fn_proto->return_type,
+ buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
+ buf_ptr(&fn_type_id.return_type->name),
+ calling_convention_name(fn_type_id.cc)));
+ return g->builtin_types.entry_invalid;
+ }
}
switch (fn_type_id.return_type->id) {
@@ -1490,7 +1673,7 @@ bool type_is_invalid(ZigType *type_entry) {
case ZigTypeIdUnion:
return type_entry->data.unionation.resolve_status == ResolveStatusInvalid;
case ZigTypeIdEnum:
- return type_entry->data.enumeration.is_invalid;
+ return type_entry->data.enumeration.resolve_status == ResolveStatusInvalid;
default:
return false;
}
@@ -1599,12 +1782,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
AstNode *decl_node = struct_type->data.structure.decl_node;
- if (struct_type->data.structure.resolve_loop_flag) {
+ if (struct_type->data.structure.resolve_loop_flag_other) {
if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
- ErrorMsg *msg = add_node_error(g, decl_node,
- buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
- emit_error_notes_for_ref_stack(g, msg);
+ add_node_error(g, decl_node,
+ buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
}
return ErrorSemanticAnalyzeFail;
}
@@ -1615,18 +1797,42 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
size_t field_count = struct_type->data.structure.src_field_count;
bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
- struct_type->data.structure.resolve_loop_flag = true;
+ struct_type->data.structure.resolve_loop_flag_other = true;
uint32_t *host_int_bytes = packed ? allocate<uint32_t>(struct_type->data.structure.gen_field_count) : nullptr;
- // Resolve sizes of all the field types. Done before the offset loop because the offset
- // loop has to look ahead.
+ // Resolve types for fields and then resolve sizes of all the field types.
+ // This is done before the offset loop because the offset loop has to look ahead.
for (size_t i = 0; i < field_count; i += 1) {
+ AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
TypeStructField *field = &struct_type->data.structure.fields[i];
+
+ if ((err = ir_resolve_lazy(g, field_source_node, field->type_val))) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ return err;
+ }
+ field->type_entry = field->type_val->data.x_type;
+
if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ return err;
+ }
+
+ if (struct_type->data.structure.layout == ContainerLayoutExtern &&
+ !type_allowed_in_extern(g, field->type_entry))
+ {
+ add_node_error(g, field_source_node,
+ buf_sprintf("extern structs cannot contain fields of type '%s'",
+ buf_ptr(&field->type_entry->name)));
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
+ } else if (packed) {
+ if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field->type_entry, field_source_node))) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ return err;
+ }
}
+
}
size_t packed_bits_offset = 0;
@@ -1690,9 +1896,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
break;
}
}
- size_t next_abi_align = (next_src_field_index == field_count) ?
- abi_align : struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align;
- next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_abi_align);
+ size_t next_align = (next_src_field_index == field_count) ?
+ abi_align : struct_type->data.structure.fields[next_src_field_index].align;
+ next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_align);
size_in_bits = next_offset * 8;
}
}
@@ -1708,7 +1914,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
struct_type->size_in_bits = size_in_bits;
struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
- struct_type->data.structure.resolve_loop_flag = false;
+ struct_type->data.structure.resolve_loop_flag_other = false;
struct_type->data.structure.host_int_bytes = host_int_bytes;
return ErrorNone;
@@ -1728,22 +1934,21 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown)
return ErrorNone;
- if (union_type->data.unionation.resolve_loop_flag) {
- if (!union_type->data.unionation.reported_infinite_err) {
- AstNode *decl_node = union_type->data.unionation.decl_node;
- union_type->data.unionation.reported_infinite_err = true;
+ AstNode *decl_node = union_type->data.structure.decl_node;
+
+ if (union_type->data.unionation.resolve_loop_flag_other) {
+ if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
- ErrorMsg *msg = add_node_error(g, decl_node,
- buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name)));
- emit_error_notes_for_ref_stack(g, msg);
+ add_node_error(g, decl_node,
+ buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
}
return ErrorSemanticAnalyzeFail;
}
// set temporary flag
- union_type->data.unionation.resolve_loop_flag = true;
+ union_type->data.unionation.resolve_loop_flag_other = true;
- ZigType *most_aligned_union_member = nullptr;
+ TypeUnionField *most_aligned_union_member = nullptr;
uint32_t field_count = union_type->data.unionation.src_field_count;
bool packed = union_type->data.unionation.layout == ContainerLayoutPacked;
@@ -1752,34 +1957,40 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
if (field->gen_index == UINT32_MAX)
continue;
- size_t this_field_align;
- if (packed) {
- // TODO: https://github.com/ziglang/zig/issues/1512
- this_field_align = 1;
- // This is the same hack as resolve_struct_alignment. See the comment there.
- } else if (field->type_entry == nullptr) {
- this_field_align = g->builtin_types.entry_usize->abi_align;
- } else {
+ AstNode *align_expr = field->decl_node->data.struct_field.align_expr;
+ if (align_expr != nullptr) {
+ if (!analyze_const_align(g, &union_type->data.unionation.decls_scope->base, align_expr,
+ &field->align))
+ {
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ return err;
+ }
+ add_node_error(g, field->decl_node,
+ buf_create_from_str("TODO implement field alignment syntax for unions. https://github.com/ziglang/zig/issues/3125"));
+ } else if (packed) {
+ field->align = 1;
+ } else if (field->type_entry != nullptr) {
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
- return ErrorSemanticAnalyzeFail;
+ return err;
+ }
+ field->align = field->type_entry->abi_align;
+ } else {
+ if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ return err;
}
-
if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
-
- this_field_align = field->type_entry->abi_align;
}
- if (most_aligned_union_member == nullptr ||
- this_field_align > most_aligned_union_member->abi_align)
- {
- most_aligned_union_member = field->type_entry;
+ if (most_aligned_union_member == nullptr || field->align > most_aligned_union_member->align) {
+ most_aligned_union_member = field;
}
}
// unset temporary flag
- union_type->data.unionation.resolve_loop_flag = false;
+ union_type->data.unionation.resolve_loop_flag_other = false;
union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown;
union_type->data.unionation.most_aligned_union_member = most_aligned_union_member;
@@ -1793,18 +2004,18 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
union_type->abi_align = tag_type->abi_align;
union_type->data.unionation.gen_tag_index = SIZE_MAX;
union_type->data.unionation.gen_union_index = SIZE_MAX;
- } else if (tag_type->abi_align > most_aligned_union_member->abi_align) {
+ } else if (tag_type->abi_align > most_aligned_union_member->align) {
union_type->abi_align = tag_type->abi_align;
union_type->data.unionation.gen_tag_index = 0;
union_type->data.unionation.gen_union_index = 1;
} else {
- union_type->abi_align = most_aligned_union_member->abi_align;
+ union_type->abi_align = most_aligned_union_member->align;
union_type->data.unionation.gen_union_index = 0;
union_type->data.unionation.gen_tag_index = 1;
}
} else {
assert(most_aligned_union_member != nullptr);
- union_type->abi_align = most_aligned_union_member->abi_align;
+ union_type->abi_align = most_aligned_union_member->align;
union_type->data.unionation.gen_union_index = SIZE_MAX;
union_type->data.unionation.gen_tag_index = SIZE_MAX;
}
@@ -1812,6 +2023,17 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
return ErrorNone;
}
+ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field) {
+ Error err;
+ if (union_field->type_entry == nullptr) {
+ if ((err = ir_resolve_lazy(g, union_field->decl_node, union_field->type_val))) {
+ return nullptr;
+ }
+ union_field->type_entry = union_field->type_val->data.x_type;
+ }
+ return union_field->type_entry;
+}
+
static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
assert(union_type->id == ZigTypeIdUnion);
@@ -1831,30 +2053,32 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
assert(decl_node->type == NodeTypeContainerDecl);
uint32_t field_count = union_type->data.unionation.src_field_count;
- ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
+ TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
assert(union_type->data.unionation.fields);
size_t union_abi_size = 0;
size_t union_size_in_bits = 0;
- if (union_type->data.unionation.resolve_loop_flag) {
- if (!union_type->data.unionation.reported_infinite_err) {
- union_type->data.unionation.reported_infinite_err = true;
+ if (union_type->data.unionation.resolve_loop_flag_other) {
+ if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
- ErrorMsg *msg = add_node_error(g, decl_node,
- buf_sprintf("union '%s' depends on its own size", buf_ptr(&union_type->name)));
- emit_error_notes_for_ref_stack(g, msg);
+ add_node_error(g, decl_node,
+ buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name)));
}
return ErrorSemanticAnalyzeFail;
}
// set temporary flag
- union_type->data.unionation.resolve_loop_flag = true;
+ union_type->data.unionation.resolve_loop_flag_other = true;
for (uint32_t i = 0; i < field_count; i += 1) {
TypeUnionField *union_field = &union_type->data.unionation.fields[i];
- ZigType *field_type = union_field->type_entry;
+ ZigType *field_type = resolve_union_field_type(g, union_field);
+ if (field_type == nullptr) {
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ return ErrorSemanticAnalyzeFail;
+ }
if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
@@ -1874,11 +2098,11 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
// The union itself for now has to be treated as being independently aligned.
// See https://github.com/ziglang/zig/issues/2166.
if (most_aligned_union_member != nullptr) {
- union_abi_size = align_forward(union_abi_size, most_aligned_union_member->abi_align);
+ union_abi_size = align_forward(union_abi_size, most_aligned_union_member->align);
}
// unset temporary flag
- union_type->data.unionation.resolve_loop_flag = false;
+ union_type->data.unionation.resolve_loop_flag_other = false;
union_type->data.unionation.resolve_status = ResolveStatusSizeKnown;
union_type->data.unionation.union_abi_size = union_abi_size;
@@ -1897,7 +2121,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
field_sizes[union_type->data.unionation.gen_tag_index] = tag_type->abi_size;
field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align;
field_sizes[union_type->data.unionation.gen_union_index] = union_abi_size;
- field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->abi_align;
+ field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->align;
size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[1]);
union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], union_type->abi_align);
union_type->size_in_bits = union_type->abi_size * 8;
@@ -1925,24 +2149,25 @@ static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
assert(enum_type->id == ZigTypeIdEnum);
- if (enum_type->data.enumeration.is_invalid)
+ if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
-
- if (enum_type->data.enumeration.zero_bits_known)
+ if (enum_type->data.enumeration.resolve_status >= ResolveStatusZeroBitsKnown)
return ErrorNone;
- if (enum_type->data.enumeration.zero_bits_loop_flag) {
- ErrorMsg *msg = add_node_error(g, enum_type->data.enumeration.decl_node,
- buf_sprintf("'%s' depends on itself", buf_ptr(&enum_type->name)));
- emit_error_notes_for_ref_stack(g, msg);
- enum_type->data.enumeration.is_invalid = true;
+ AstNode *decl_node = enum_type->data.enumeration.decl_node;
+ assert(decl_node->type == NodeTypeContainerDecl);
+
+ if (enum_type->data.enumeration.resolve_loop_flag) {
+ if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) {
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
+ add_node_error(g, decl_node,
+ buf_sprintf("enum '%s' depends on itself",
+ buf_ptr(&enum_type->name)));
+ }
return ErrorSemanticAnalyzeFail;
}
- enum_type->data.enumeration.zero_bits_loop_flag = true;
-
- AstNode *decl_node = enum_type->data.enumeration.decl_node;
- assert(decl_node->type == NodeTypeContainerDecl);
+ enum_type->data.enumeration.resolve_loop_flag = true;
assert(!enum_type->data.enumeration.fields);
uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
@@ -1951,9 +2176,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
enum_type->data.enumeration.src_field_count = field_count;
enum_type->data.enumeration.fields = nullptr;
- enum_type->data.enumeration.is_invalid = true;
- enum_type->data.enumeration.zero_bits_loop_flag = false;
- enum_type->data.enumeration.zero_bits_known = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
@@ -1982,14 +2205,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
if (decl_node->data.container_decl.init_arg_expr != nullptr) {
ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
if (type_is_invalid(wanted_tag_int_type)) {
- enum_type->data.enumeration.is_invalid = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
} else if (wanted_tag_int_type->id != ZigTypeIdInt) {
- enum_type->data.enumeration.is_invalid = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
add_node_error(g, decl_node->data.container_decl.init_arg_expr,
buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
} else if (enum_type->data.enumeration.layout == ContainerLayoutExtern &&
!type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) {
- enum_type->data.enumeration.is_invalid = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
buf_sprintf("'%s' is not a valid tag type for an extern enum",
buf_ptr(&wanted_tag_int_type->name)));
@@ -2022,6 +2245,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
buf_sprintf("structs and unions, not enums, support field types"));
add_error_note(g, msg, decl_node,
buf_sprintf("consider 'union(enum)' here"));
+ } else if (field_node->data.struct_field.align_expr != nullptr) {
+ ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr,
+ buf_sprintf("structs and unions, not enums, support field alignment"));
+ add_error_note(g, msg, decl_node,
+ buf_sprintf("consider 'union(enum)' here"));
}
auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
@@ -2029,7 +2257,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
ErrorMsg *msg = add_node_error(g, field_node,
buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
- enum_type->data.enumeration.is_invalid = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
continue;
}
@@ -2037,9 +2265,10 @@ 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.is_invalid = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
continue;
}
@@ -2060,7 +2289,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
if (!bigint_fits_in_bits(&type_enum_field->value,
tag_int_type->size_in_bits,
tag_int_type->data.integral.is_signed)) {
- enum_type->data.enumeration.is_invalid = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
Buf *val_buf = buf_alloc();
bigint_append_buf(val_buf, &type_enum_field->value, 10);
@@ -2075,7 +2304,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
// Make sure the value is unique
auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
if (entry != nullptr) {
- enum_type->data.enumeration.is_invalid = true;
+ enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
Buf *val_buf = buf_alloc();
bigint_append_buf(val_buf, &type_enum_field->value, 10);
@@ -2089,13 +2318,12 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
last_enum_field = type_enum_field;
}
- enum_type->data.enumeration.zero_bits_loop_flag = false;
- enum_type->data.enumeration.zero_bits_known = true;
- enum_type->data.enumeration.complete = true;
-
- if (enum_type->data.enumeration.is_invalid)
+ if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
+ enum_type->data.enumeration.resolve_loop_flag = false;
+ enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
+
return ErrorNone;
}
@@ -2112,16 +2340,17 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
AstNode *decl_node = struct_type->data.structure.decl_node;
assert(decl_node->type == NodeTypeContainerDecl);
- if (struct_type->data.structure.resolve_loop_flag) {
- // TODO This is a problem. I believe it can be solved with lazy values.
- struct_type->size_in_bits = SIZE_MAX;
- struct_type->abi_size = SIZE_MAX;
- struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
- struct_type->data.structure.resolve_loop_flag = false;
- return ErrorNone;
+ if (struct_type->data.structure.resolve_loop_flag_zero_bits) {
+ if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ add_node_error(g, decl_node,
+ buf_sprintf("struct '%s' depends on itself",
+ buf_ptr(&struct_type->name)));
+ }
+ return ErrorSemanticAnalyzeFail;
}
- struct_type->data.structure.resolve_loop_flag = true;
+ struct_type->data.structure.resolve_loop_flag_zero_bits = true;
assert(!struct_type->data.structure.fields);
size_t field_count = decl_node->data.container_decl.fields.length;
@@ -2153,58 +2382,60 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
return ErrorSemanticAnalyzeFail;
}
- ZigType *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
- type_struct_field->type_entry = field_type;
- if (type_is_invalid(field_type)) {
+ 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;
}
+ assert(field_type_val->special != ConstValSpecialRuntime);
+ type_struct_field->type_val = field_type_val;
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
- if (struct_type->data.structure.layout == ContainerLayoutExtern &&
- !type_allowed_in_extern(g, field_type))
- {
- add_node_error(g, field_node,
- buf_sprintf("extern structs cannot contain fields of type '%s'",
- buf_ptr(&field_type->name)));
+ bool field_is_opaque_type;
+ if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
- } else if (struct_type->data.structure.layout == ContainerLayoutPacked) {
- if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_node))) {
- struct_type->data.structure.resolve_status = ResolveStatusInvalid;
- return ErrorSemanticAnalyzeFail;
- }
}
-
- type_struct_field->src_index = i;
- type_struct_field->gen_index = SIZE_MAX;
-
- if (field_type->id == ZigTypeIdOpaque) {
+ if (field_is_opaque_type) {
add_node_error(g, field_node->data.struct_field.type,
buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
- switch (type_requires_comptime(g, field_type)) {
+
+ type_struct_field->src_index = i;
+ type_struct_field->gen_index = SIZE_MAX;
+
+ switch (type_val_resolve_requires_comptime(g, field_type_val)) {
case ReqCompTimeYes:
struct_type->data.structure.requires_comptime = true;
break;
case ReqCompTimeInvalid:
+ if (g->trace_err != nullptr) {
+ g->trace_err = add_error_note(g, g->trace_err, field_node,
+ buf_create_from_str("while checking this field"));
+ }
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
case ReqCompTimeNo:
break;
}
- if (!type_has_bits(field_type))
+ bool field_is_zero_bits;
+ if ((err = type_val_resolve_zero_bits(g, field_type_val, struct_type, nullptr, &field_is_zero_bits))) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ return ErrorSemanticAnalyzeFail;
+ }
+ if (field_is_zero_bits)
continue;
type_struct_field->gen_index = gen_field_index;
gen_field_index += 1;
}
- struct_type->data.structure.resolve_loop_flag = false;
+ struct_type->data.structure.resolve_loop_flag_zero_bits = false;
struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
if (gen_field_index != 0) {
struct_type->abi_size = SIZE_MAX;
@@ -2234,17 +2465,16 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
AstNode *decl_node = struct_type->data.structure.decl_node;
- if (struct_type->data.structure.resolve_loop_flag) {
+ if (struct_type->data.structure.resolve_loop_flag_other) {
if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
- ErrorMsg *msg = add_node_error(g, decl_node,
- buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
- emit_error_notes_for_ref_stack(g, msg);
+ add_node_error(g, decl_node,
+ buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name)));
}
return ErrorSemanticAnalyzeFail;
}
- struct_type->data.structure.resolve_loop_flag = true;
+ struct_type->data.structure.resolve_loop_flag_other = true;
assert(decl_node->type == NodeTypeContainerDecl);
size_t field_count = struct_type->data.structure.src_field_count;
@@ -2255,47 +2485,31 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
if (field->gen_index == SIZE_MAX)
continue;
- uint32_t this_field_align;
-
- // TODO: Sets the field alignment in the type, but doesn't do anything
- // to actually make that happen yet.
AstNode *align_expr = field->decl_node->data.struct_field.align_expr;
if (align_expr != nullptr) {
- if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, &this_field_align)) {
- field->type_entry = g->builtin_types.entry_invalid;
- } else {
- field->align = this_field_align;
+ if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr,
+ &field->align))
+ {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ return err;
}
} else if (packed) {
- // TODO: https://github.com/ziglang/zig/issues/1512
- // TODO: Validate requested alignment is possible, given packed,
- // and given other field alignments.
- this_field_align = 1;
- // TODO If we have no type_entry for the field, we've already failed to
- // compile the program correctly. This stage1 compiler needs a deeper
- // reworking to make this correct, or we can ignore the problem
- // and make sure it is fixed in stage2. This workaround is for when
- // there is a false positive of a dependency loop, of alignment depending
- // on itself. When this false positive happens we assume a pointer-aligned
- // field, which is usually fine but could be incorrectly over-aligned or
- // even under-aligned. See https://github.com/ziglang/zig/issues/1512
- } else if (field->type_entry == nullptr) {
- this_field_align = g->builtin_types.entry_usize->abi_align;
+ field->align = 1;
} else {
- if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
+ if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
- return ErrorSemanticAnalyzeFail;
+ return err;
}
- this_field_align = field->type_entry->abi_align;
+ if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
+ return ErrorSemanticAnalyzeFail;
}
- // TODO: https://github.com/ziglang/zig/issues/1512
- if (this_field_align > struct_type->abi_align) {
- struct_type->abi_align = this_field_align;
+ if (field->align > struct_type->abi_align) {
+ struct_type->abi_align = field->align;
}
}
- struct_type->data.structure.resolve_loop_flag = false;
+ struct_type->data.structure.resolve_loop_flag_other = false;
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
return ErrorSemanticAnalyzeFail;
@@ -2316,23 +2530,21 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
if (union_type->data.unionation.resolve_status >= ResolveStatusZeroBitsKnown)
return ErrorNone;
- if (union_type->data.unionation.resolve_loop_flag) {
- // If we get here it's due to recursion. From this we conclude that the struct is
- // not zero bits.
- // TODO actually it could still be zero bits. Here we should continue analyzing
- // the union from the next field index.
- union_type->data.unionation.resolve_status = ResolveStatusZeroBitsKnown;
- union_type->data.unionation.resolve_loop_flag = false;
- union_type->abi_size = SIZE_MAX;
- union_type->size_in_bits = SIZE_MAX;
- return ErrorNone;
- }
-
- union_type->data.unionation.resolve_loop_flag = true;
-
AstNode *decl_node = union_type->data.unionation.decl_node;
assert(decl_node->type == NodeTypeContainerDecl);
+ if (union_type->data.unionation.resolve_loop_flag_zero_bits) {
+ if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) {
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ add_node_error(g, decl_node,
+ buf_sprintf("union '%s' depends on itself",
+ buf_ptr(&union_type->name)));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+
+ union_type->data.unionation.resolve_loop_flag_zero_bits = true;
+
assert(union_type->data.unionation.fields == nullptr);
uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;
if (field_count == 0) {
@@ -2392,14 +2604,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
tag_type->size_in_bits = tag_int_type->size_in_bits;
tag_type->data.enumeration.tag_int_type = tag_int_type;
- tag_type->data.enumeration.zero_bits_known = true;
+ tag_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
tag_type->data.enumeration.decl_node = decl_node;
tag_type->data.enumeration.layout = ContainerLayoutAuto;
tag_type->data.enumeration.src_field_count = field_count;
tag_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
tag_type->data.enumeration.fields_by_name.init(field_count);
tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope;
- tag_type->data.enumeration.complete = true;
} else if (enum_type_node != nullptr) {
ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node);
if (type_is_invalid(enum_type)) {
@@ -2441,49 +2652,68 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
return ErrorSemanticAnalyzeFail;
}
- ZigType *field_type;
+ bool field_is_zero_bits;
if (field_node->data.struct_field.type == nullptr) {
- if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
- field_type = g->builtin_types.entry_void;
+ if (decl_node->data.container_decl.auto_enum ||
+ decl_node->data.container_decl.init_arg_expr != nullptr)
+ {
+ union_field->type_entry = g->builtin_types.entry_void;
+ field_is_zero_bits = true;
} else {
add_node_error(g, field_node, buf_sprintf("union field missing type"));
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
} else {
- field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
- if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) {
+ 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;
}
+ assert(field_type_val->special != ConstValSpecialRuntime);
+ union_field->type_val = field_type_val;
if (union_type->data.unionation.resolve_status == ResolveStatusInvalid)
return ErrorSemanticAnalyzeFail;
- }
- union_field->type_entry = field_type;
- if (field_type->id == ZigTypeIdOpaque) {
- add_node_error(g, field_node->data.struct_field.type,
- buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));
- union_type->data.unionation.resolve_status = ResolveStatusInvalid;
- return ErrorSemanticAnalyzeFail;
- }
+ bool field_is_opaque_type;
+ if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) {
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ return ErrorSemanticAnalyzeFail;
+ }
+ if (field_is_opaque_type) {
+ add_node_error(g, field_node->data.struct_field.type,
+ buf_create_from_str(
+ "opaque types have unknown size and therefore cannot be directly embedded in unions"));
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ return ErrorSemanticAnalyzeFail;
+ }
- switch (type_requires_comptime(g, field_type)) {
- case ReqCompTimeInvalid:
+ switch (type_val_resolve_requires_comptime(g, field_type_val)) {
+ case ReqCompTimeInvalid:
+ if (g->trace_err != nullptr) {
+ g->trace_err = add_error_note(g, g->trace_err, field_node,
+ buf_create_from_str("while checking this field"));
+ }
+ union_type->data.unionation.resolve_status = ResolveStatusInvalid;
+ return ErrorSemanticAnalyzeFail;
+ case ReqCompTimeYes:
+ union_type->data.unionation.requires_comptime = true;
+ break;
+ case ReqCompTimeNo:
+ break;
+ }
+
+ if ((err = type_val_resolve_zero_bits(g, field_type_val, union_type, nullptr, &field_is_zero_bits))) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
- case ReqCompTimeYes:
- union_type->data.unionation.requires_comptime = true;
- break;
- case ReqCompTimeNo:
- break;
+ }
}
if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
- buf_sprintf("non-enum union field assignment"));
- add_error_note(g, msg, decl_node,
- buf_sprintf("consider 'union(enum)' here"));
+ buf_create_from_str("untagged union field assignment"));
+ add_error_note(g, msg, decl_node, buf_create_from_str("consider 'union(enum)' here"));
}
if (create_enum_type) {
@@ -2501,7 +2731,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;
@@ -2542,7 +2773,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
}
assert(union_field->enum_field != nullptr);
- if (!type_has_bits(field_type))
+ if (field_is_zero_bits)
continue;
union_field->gen_index = gen_field_index;
@@ -2619,7 +2850,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
return ErrorSemanticAnalyzeFail;
}
- union_type->data.unionation.resolve_loop_flag = false;
+ union_type->data.unionation.resolve_loop_flag_zero_bits = false;
union_type->data.unionation.gen_field_count = gen_field_index;
bool zero_bits = gen_field_index == 0 && (field_count < 2 || !src_have_tag);
@@ -2676,6 +2907,8 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node) {
fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
proto_node->data.fn_proto.fn_def_node->data.fn_def.body;
+ fn_entry->analyzed_executable.source_node = fn_entry->body_node;
+
return fn_entry;
}
@@ -2702,7 +2935,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) {
@@ -2848,7 +3081,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) {
@@ -2943,7 +3177,7 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source
void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
Tld *tld = get_container_scope(g->compile_var_import)->decl_table.get(name);
- resolve_top_level_decl(g, tld, tld->source_node);
+ resolve_top_level_decl(g, tld, tld->source_node, false);
assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld;
tld_var->var->const_value = value;
@@ -3185,7 +3419,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
return variable_entry;
}
-static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
+static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) {
AstNode *source_node = tld_var->base.source_node;
AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration;
@@ -3197,9 +3431,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
ZigType *explicit_type = nullptr;
if (var_decl->type) {
if (tld_var->analyzing_type) {
- ErrorMsg *msg = add_node_error(g, var_decl->type,
+ add_node_error(g, var_decl->type,
buf_sprintf("type of '%s' depends on itself", buf_ptr(tld_var->base.name)));
- emit_error_notes_for_ref_stack(g, msg);
explicit_type = g->builtin_types.entry_invalid;
} else {
tld_var->analyzing_type = true;
@@ -3217,7 +3450,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
if (explicit_type && explicit_type->id == ZigTypeIdInvalid) {
implicit_type = explicit_type;
} else if (var_decl->expr) {
- init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
+ 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;
@@ -3372,7 +3606,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)) {
@@ -3392,51 +3627,61 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
}
}
-void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {
- if (tld->resolution != TldResolutionUnresolved)
+void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy) {
+ bool want_resolve_lazy = tld->resolution == TldResolutionOkLazy && !allow_lazy;
+ if (tld->resolution != TldResolutionUnresolved && !want_resolve_lazy)
return;
- assert(tld->resolution != TldResolutionResolving);
tld->resolution = TldResolutionResolving;
- g->tld_ref_source_node_stack.append(source_node);
switch (tld->id) {
- case TldIdVar:
- {
- TldVar *tld_var = (TldVar *)tld;
- resolve_decl_var(g, tld_var);
- break;
- }
- case TldIdFn:
- {
- TldFn *tld_fn = (TldFn *)tld;
- resolve_decl_fn(g, tld_fn);
- break;
- }
- case TldIdContainer:
- {
- TldContainer *tld_container = (TldContainer *)tld;
- resolve_decl_container(g, tld_container);
- break;
- }
- case TldIdCompTime:
- {
- TldCompTime *tld_comptime = (TldCompTime *)tld;
- resolve_decl_comptime(g, tld_comptime);
- break;
+ case TldIdVar: {
+ TldVar *tld_var = (TldVar *)tld;
+ if (want_resolve_lazy) {
+ ir_resolve_lazy(g, source_node, tld_var->var->const_value);
+ } else {
+ resolve_decl_var(g, tld_var, allow_lazy);
}
+ tld->resolution = allow_lazy ? TldResolutionOkLazy : TldResolutionOk;
+ break;
+ }
+ case TldIdFn: {
+ TldFn *tld_fn = (TldFn *)tld;
+ resolve_decl_fn(g, tld_fn);
+
+ tld->resolution = TldResolutionOk;
+ break;
+ }
+ case TldIdContainer: {
+ TldContainer *tld_container = (TldContainer *)tld;
+ resolve_decl_container(g, tld_container);
+
+ tld->resolution = TldResolutionOk;
+ break;
+ }
+ case TldIdCompTime: {
+ TldCompTime *tld_comptime = (TldCompTime *)tld;
+ resolve_decl_comptime(g, tld_comptime);
+
+ tld->resolution = TldResolutionOk;
+ break;
+ }
case TldIdUsingNamespace: {
TldUsingNamespace *tld_using_namespace = (TldUsingNamespace *)tld;
assert(tld_using_namespace->base.parent_scope->id == ScopeIdDecls);
ScopeDecls *dest_decls_scope = (ScopeDecls *)tld_using_namespace->base.parent_scope;
preview_use_decl(g, tld_using_namespace, dest_decls_scope);
resolve_use_decl(g, tld_using_namespace, dest_decls_scope);
+
+ tld->resolution = TldResolutionOk;
break;
}
}
- tld->resolution = TldResolutionOk;
- g->tld_ref_source_node_stack.pop();
+ if (g->trace_err != nullptr && source_node != nullptr && !source_node->already_traced_this_node) {
+ g->trace_err = add_error_note(g, g->trace_err, source_node, buf_create_from_str("referenced here"));
+ source_node->already_traced_this_node = true;
+ }
}
Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) {
@@ -3562,7 +3807,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag)
}
TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag) {
- assert(enum_type->data.enumeration.zero_bits_known);
+ assert(type_is_resolved(enum_type, ResolveStatusZeroBitsKnown));
for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
TypeEnumField *field = &enum_type->data.enumeration.fields[i];
if (bigint_cmp(&field->value, tag) == CmpEQ) {
@@ -3631,43 +3876,6 @@ ZigType *container_ref_type(ZigType *type_entry) {
type_entry->data.pointer.child_type : type_entry;
}
-Error resolve_container_type(CodeGen *g, ZigType *type_entry) {
- switch (type_entry->id) {
- case ZigTypeIdStruct:
- return resolve_struct_type(g, type_entry);
- case ZigTypeIdEnum:
- return resolve_enum_zero_bits(g, type_entry);
- case ZigTypeIdUnion:
- return resolve_union_type(g, type_entry);
- case ZigTypeIdPointer:
- case ZigTypeIdMetaType:
- case ZigTypeIdVoid:
- case ZigTypeIdBool:
- case ZigTypeIdUnreachable:
- case ZigTypeIdInt:
- case ZigTypeIdFloat:
- case ZigTypeIdArray:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdEnumLiteral:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- case ZigTypeIdOptional:
- case ZigTypeIdErrorUnion:
- case ZigTypeIdErrorSet:
- case ZigTypeIdFn:
- case ZigTypeIdBoundFn:
- case ZigTypeIdInvalid:
- case ZigTypeIdArgTuple:
- case ZigTypeIdOpaque:
- case ZigTypeIdVector:
- case ZigTypeIdFnFrame:
- case ZigTypeIdAnyFrame:
- zig_unreachable();
- }
- zig_unreachable();
-}
-
ZigType *get_src_ptr_type(ZigType *type) {
if (type->id == ZigTypeIdPointer) return type;
if (type->id == ZigTypeIdFn) return type;
@@ -3803,6 +4011,13 @@ static void resolve_async_fn_frame(CodeGen *g, ZigFn *fn) {
ZigType *frame_type = get_fn_frame_type(g, fn);
Error err;
if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) {
+ if (g->trace_err != nullptr && frame_type->data.frame.resolve_loop_src_node != nullptr &&
+ !frame_type->data.frame.reported_loop_err)
+ {
+ frame_type->data.frame.reported_loop_err = true;
+ g->trace_err = add_error_note(g, g->trace_err, frame_type->data.frame.resolve_loop_src_node,
+ buf_sprintf("when analyzing type '%s' here", buf_ptr(&frame_type->name)));
+ }
fn->anal_state = FnAnalStateInvalid;
return;
}
@@ -3918,7 +4133,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
&fn->analyzed_executable, fn_type_id->return_type, return_type_node);
fn->src_implicit_return_type = block_return_type;
- if (type_is_invalid(block_return_type) || fn->analyzed_executable.invalid) {
+ if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) {
assert(g->errors.length > 0);
fn->anal_state = FnAnalStateInvalid;
return;
@@ -4002,7 +4217,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
assert(!fn_type->data.fn.is_generic);
ir_gen_fn(g, fn_table_entry);
- if (fn_table_entry->ir_executable.invalid) {
+ if (fn_table_entry->ir_executable.first_err_trace_msg != nullptr) {
fn_table_entry->anal_state = FnAnalStateInvalid;
return;
}
@@ -4140,12 +4355,14 @@ void semantic_analyze(CodeGen *g) {
{
for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {
Tld *tld = g->resolve_queue.at(g->resolve_queue_index);
+ g->trace_err = nullptr;
AstNode *source_node = nullptr;
- resolve_top_level_decl(g, tld, source_node);
+ resolve_top_level_decl(g, tld, source_node, false);
}
for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);
+ g->trace_err = nullptr;
analyze_fn_body(g, fn_entry);
}
}
@@ -4157,6 +4374,7 @@ void semantic_analyze(CodeGen *g) {
// second pass over functions for detecting async
for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
+ g->trace_err = nullptr;
analyze_fn_async(g, fn, true);
if (fn_is_async(fn) && fn->non_async_node != nullptr) {
ErrorMsg *msg = add_node_error(g, fn->proto_node,
@@ -4802,7 +5020,10 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdStruct:
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
TypeStructField *field = &type_entry->data.structure.fields[i];
- switch (type_has_one_possible_value(g, field->type_entry)) {
+ OnePossibleValue opv = (field->type_entry != nullptr) ?
+ type_has_one_possible_value(g, field->type_entry) :
+ type_val_resolve_has_one_possible_value(g, field->type_val);
+ switch (opv) {
case OnePossibleValueInvalid:
return OnePossibleValueInvalid;
case OnePossibleValueNo:
@@ -4828,18 +5049,19 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdUnion:
if (type_entry->data.unionation.src_field_count > 1)
return OnePossibleValueNo;
- return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
+ TypeUnionField *only_field = &type_entry->data.unionation.fields[0];
+ if (only_field->type_entry != nullptr) {
+ return type_has_one_possible_value(g, only_field->type_entry);
+ }
+ return type_val_resolve_has_one_possible_value(g, only_field->type_val);
}
zig_unreachable();
}
-ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
+ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
Error err;
- if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
- return ReqCompTimeInvalid;
- switch (type_entry->id) {
+ switch (ty->id) {
case ZigTypeIdInvalid:
- case ZigTypeIdOpaque:
zig_unreachable();
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
@@ -4851,23 +5073,36 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdArgTuple:
return ReqCompTimeYes;
case ZigTypeIdArray:
- return type_requires_comptime(g, type_entry->data.array.child_type);
+ return type_requires_comptime(g, ty->data.array.child_type);
case ZigTypeIdStruct:
- return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
+ if (ty->data.structure.resolve_loop_flag_zero_bits) {
+ // Does a struct which contains a pointer field to itself require comptime? No.
+ return ReqCompTimeNo;
+ }
+ if ((err = type_resolve(g, ty, ResolveStatusZeroBitsKnown)))
+ return ReqCompTimeInvalid;
+ return ty->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
case ZigTypeIdUnion:
- return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
+ if (ty->data.unionation.resolve_loop_flag_zero_bits) {
+ // Does a union which contains a pointer field to itself require comptime? No.
+ return ReqCompTimeNo;
+ }
+ if ((err = type_resolve(g, ty, ResolveStatusZeroBitsKnown)))
+ return ReqCompTimeInvalid;
+ return ty->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
case ZigTypeIdOptional:
- return type_requires_comptime(g, type_entry->data.maybe.child_type);
+ return type_requires_comptime(g, ty->data.maybe.child_type);
case ZigTypeIdErrorUnion:
- return type_requires_comptime(g, type_entry->data.error_union.payload_type);
+ return type_requires_comptime(g, ty->data.error_union.payload_type);
case ZigTypeIdPointer:
- if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
+ if (ty->data.pointer.child_type->id == ZigTypeIdOpaque) {
return ReqCompTimeNo;
} else {
- return type_requires_comptime(g, type_entry->data.pointer.child_type);
+ return type_requires_comptime(g, ty->data.pointer.child_type);
}
case ZigTypeIdFn:
- return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
+ return ty->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
+ case ZigTypeIdOpaque:
case ZigTypeIdEnum:
case ZigTypeIdErrorSet:
case ZigTypeIdBool:
@@ -5155,34 +5390,6 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
}
-void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
- Error err;
- ZigType *wanted_type = const_val->type;
- if (wanted_type->id == ZigTypeIdArray) {
- const_val->special = ConstValSpecialStatic;
- const_val->data.x_array.special = ConstArraySpecialUndef;
- } else if (wanted_type->id == ZigTypeIdStruct) {
- if ((err = ensure_complete_type(g, wanted_type))) {
- return;
- }
-
- const_val->special = ConstValSpecialStatic;
- size_t field_count = wanted_type->data.structure.src_field_count;
- const_val->data.x_struct.fields = create_const_vals(field_count);
- for (size_t i = 0; i < field_count; i += 1) {
- ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
- field_val->type = wanted_type->data.structure.fields[i].type_entry;
- assert(field_val->type);
- init_const_undefined(g, field_val);
- field_val->parent.id = ConstParentIdStruct;
- field_val->parent.data.p_struct.struct_val = const_val;
- field_val->parent.data.p_struct.field_index = i;
- }
- } else {
- const_val->special = ConstValSpecialUndef;
- }
-}
-
ConstExprValue *create_const_vals(size_t count) {
ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(count);
ConstExprValue *vals = allocate<ConstExprValue>(count);
@@ -5192,10 +5399,6 @@ ConstExprValue *create_const_vals(size_t count) {
return vals;
}
-Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
- return type_resolve(g, type_entry, ResolveStatusSizeKnown);
-}
-
static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync)
return orig_fn_type;
@@ -5209,27 +5412,6 @@ static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
return fn_type;
}
-static void emit_error_notes_for_type_loop(CodeGen *g, ErrorMsg *msg, ZigType *stop_type,
- ZigType *ty, AstNode *src_node)
-{
- ErrorMsg *note = add_error_note(g, msg, src_node,
- buf_sprintf("when analyzing type '%s' here", buf_ptr(&ty->name)));
- if (ty == stop_type)
- return;
- switch (ty->id) {
- case ZigTypeIdFnFrame: {
- ty->data.frame.reported_loop_err = true;
- ZigType *depending_type = ty->data.frame.resolve_loop_type;
- if (depending_type == nullptr)
- return;
- emit_error_notes_for_type_loop(g, note, stop_type,
- depending_type, ty->data.frame.resolve_loop_src_node);
- }
- default:
- return;
- }
-}
-
static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
Error err;
@@ -5241,14 +5423,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
if (frame_type->data.frame.resolve_loop_type != nullptr) {
if (!frame_type->data.frame.reported_loop_err) {
- frame_type->data.frame.reported_loop_err = true;
- ErrorMsg *msg = add_node_error(g, fn->proto_node,
+ add_node_error(g, fn->proto_node,
buf_sprintf("'%s' depends on itself", buf_ptr(&frame_type->name)));
- emit_error_notes_for_type_loop(g, msg,
- frame_type,
- frame_type->data.frame.resolve_loop_type,
- frame_type->data.frame.resolve_loop_src_node);
- emit_error_notes_for_ref_stack(g, msg);
}
return ErrorSemanticAnalyzeFail;
}
@@ -5264,11 +5440,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
return ErrorSemanticAnalyzeFail;
break;
case FnAnalStateProbing: {
- ErrorMsg *msg = add_node_error(g, fn->proto_node,
+ add_node_error(g, fn->proto_node,
buf_sprintf("cannot resolve '%s': function not fully analyzed yet",
buf_ptr(&frame_type->name)));
- ir_add_analysis_trace(fn->ir_executable.analysis, msg,
- buf_sprintf("depends on its own frame here"));
return ErrorSemanticAnalyzeFail;
}
}
@@ -5339,10 +5513,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
if (callee->anal_state == FnAnalStateProbing) {
ErrorMsg *msg = add_node_error(g, fn->proto_node,
buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name)));
- ErrorMsg *note = add_error_note(g, msg, call->base.source_node,
+ g->trace_err = add_error_note(g, msg, call->base.source_node,
buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name)));
- ir_add_analysis_trace(callee->ir_executable.analysis, note,
- buf_sprintf("depends on the frame here"));
return ErrorSemanticAnalyzeFail;
}
@@ -5454,6 +5626,37 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
return ErrorNone;
}
+static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) {
+ Error err;
+
+ if (ty->abi_size != SIZE_MAX)
+ return ErrorNone;
+
+ if (ty->data.pointer.resolve_loop_flag_zero_bits) {
+ ty->abi_size = g->builtin_types.entry_usize->abi_size;
+ ty->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
+ ty->abi_align = g->builtin_types.entry_usize->abi_align;
+ return ErrorNone;
+ }
+ ty->data.pointer.resolve_loop_flag_zero_bits = true;
+
+ ZigType *elem_type = ty->data.pointer.child_type;
+
+ if ((err = type_resolve(g, elem_type, ResolveStatusZeroBitsKnown)))
+ return err;
+
+ if (type_has_bits(elem_type)) {
+ ty->abi_size = g->builtin_types.entry_usize->abi_size;
+ ty->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
+ ty->abi_align = g->builtin_types.entry_usize->abi_align;
+ } else {
+ ty->abi_size = 0;
+ ty->size_in_bits = 0;
+ ty->abi_align = 0;
+ }
+ return ErrorNone;
+}
+
Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
if (type_is_invalid(ty))
return ErrorSemanticAnalyzeFail;
@@ -5463,36 +5666,48 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
case ResolveStatusInvalid:
zig_unreachable();
case ResolveStatusZeroBitsKnown:
- if (ty->id == ZigTypeIdStruct) {
- return resolve_struct_zero_bits(g, ty);
- } else if (ty->id == ZigTypeIdEnum) {
- return resolve_enum_zero_bits(g, ty);
- } else if (ty->id == ZigTypeIdUnion) {
- return resolve_union_zero_bits(g, ty);
+ switch (ty->id) {
+ case ZigTypeIdStruct:
+ return resolve_struct_zero_bits(g, ty);
+ case ZigTypeIdEnum:
+ return resolve_enum_zero_bits(g, ty);
+ case ZigTypeIdUnion:
+ return resolve_union_zero_bits(g, ty);
+ case ZigTypeIdPointer:
+ return resolve_pointer_zero_bits(g, ty);
+ default:
+ return ErrorNone;
}
- return ErrorNone;
case ResolveStatusAlignmentKnown:
- if (ty->id == ZigTypeIdStruct) {
- return resolve_struct_alignment(g, ty);
- } else if (ty->id == ZigTypeIdEnum) {
- return resolve_enum_zero_bits(g, ty);
- } else if (ty->id == ZigTypeIdUnion) {
- return resolve_union_alignment(g, ty);
- } else if (ty->id == ZigTypeIdFnFrame) {
- return resolve_async_frame(g, ty);
+ switch (ty->id) {
+ case ZigTypeIdStruct:
+ return resolve_struct_alignment(g, ty);
+ case ZigTypeIdEnum:
+ return resolve_enum_zero_bits(g, ty);
+ case ZigTypeIdUnion:
+ return resolve_union_alignment(g, ty);
+ case ZigTypeIdFnFrame:
+ return resolve_async_frame(g, ty);
+ case ZigTypeIdPointer:
+ return resolve_pointer_zero_bits(g, ty);
+ default:
+ return ErrorNone;
}
- return ErrorNone;
case ResolveStatusSizeKnown:
- if (ty->id == ZigTypeIdStruct) {
- return resolve_struct_type(g, ty);
- } else if (ty->id == ZigTypeIdEnum) {
- return resolve_enum_zero_bits(g, ty);
- } else if (ty->id == ZigTypeIdUnion) {
- return resolve_union_type(g, ty);
- } else if (ty->id == ZigTypeIdFnFrame) {
- return resolve_async_frame(g, ty);
+ switch (ty->id) {
+ case ZigTypeIdStruct:
+ return resolve_struct_type(g, ty);
+ case ZigTypeIdEnum:
+ return resolve_enum_zero_bits(g, ty);
+ case ZigTypeIdUnion:
+ return resolve_union_type(g, ty);
+ case ZigTypeIdFnFrame:
+ return resolve_async_frame(g, ty);
+ case ZigTypeIdPointer:
+ return resolve_pointer_zero_bits(g, ty);
+ default:
+ return ErrorNone;
}
- return ErrorNone;
case ResolveStatusLLVMFwdDecl:
case ResolveStatusLLVMFull:
resolve_llvm_types(g, ty, status);
@@ -5867,6 +6082,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
case ConstValSpecialRuntime:
buf_appendf(buf, "(runtime value)");
return;
+ case ConstValSpecialLazy:
+ buf_appendf(buf, "(lazy value)");
+ return;
case ConstValSpecialUndef:
buf_appendf(buf, "undefined");
return;
@@ -6241,6 +6459,40 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
zig_unreachable();
}
+static void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
+ Error err;
+ ZigType *wanted_type = const_val->type;
+ if (wanted_type->id == ZigTypeIdArray) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->data.x_array.special = ConstArraySpecialUndef;
+ } else if (wanted_type->id == ZigTypeIdStruct) {
+ if ((err = type_resolve(g, wanted_type, ResolveStatusZeroBitsKnown))) {
+ return;
+ }
+
+ const_val->special = ConstValSpecialStatic;
+ size_t field_count = wanted_type->data.structure.src_field_count;
+ const_val->data.x_struct.fields = create_const_vals(field_count);
+ for (size_t i = 0; i < field_count; i += 1) {
+ ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
+ field_val->type = wanted_type->data.structure.fields[i].type_entry;
+ assert(field_val->type);
+ init_const_undefined(g, field_val);
+ field_val->parent.id = ConstParentIdStruct;
+ field_val->parent.data.p_struct.struct_val = const_val;
+ field_val->parent.data.p_struct.field_index = i;
+ }
+ } else {
+ const_val->special = ConstValSpecialUndef;
+ }
+}
+
+void expand_undef_struct(CodeGen *g, ConstExprValue *const_val) {
+ if (const_val->special == ConstValSpecialUndef) {
+ init_const_undefined(g, const_val);
+ }
+}
+
// Canonicalize the array value as ConstArraySpecialNone
void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
size_t elem_count;
@@ -6504,7 +6756,7 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) {
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));
- resolve_top_level_decl(codegen, tld, nullptr);
+ resolve_top_level_decl(codegen, tld, nullptr, false);
assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld;
ConstExprValue *var_value = tld_var->var->const_value;
@@ -6719,19 +6971,6 @@ bool ptr_allows_addr_zero(ZigType *ptr_type) {
return false;
}
-void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg) {
- size_t i = g->tld_ref_source_node_stack.length;
- for (;;) {
- if (i == 0)
- break;
- i -= 1;
- AstNode *source_node = g->tld_ref_source_node_stack.at(i);
- if (source_node) {
- msg = add_error_note(g, msg, source_node, buf_sprintf("referenced here"));
- }
- }
-}
-
Buf *type_bare_name(ZigType *type_entry) {
if (is_slice(type_entry)) {
return &type_entry->name;
@@ -7134,10 +7373,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
struct_type->data.structure.resolve_status = ResolveStatusLLVMFull;
}
-static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
- assert(!enum_type->data.enumeration.is_invalid);
- assert(enum_type->data.enumeration.complete);
- if (enum_type->llvm_di_type != nullptr) return;
+static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatus wanted_resolve_status) {
+ assert(enum_type->data.enumeration.resolve_status >= ResolveStatusSizeKnown);
+ if (enum_type->data.enumeration.resolve_status >= wanted_resolve_status) return;
Scope *scope = &enum_type->data.enumeration.decls_scope->base;
ZigType *import = get_scope_import(scope);
@@ -7158,6 +7396,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
debug_align_in_bits,
ZigLLVM_DIFlags_Zero,
nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
+ enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
return;
}
@@ -7190,14 +7429,16 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
get_llvm_di_type(g, tag_int_type), "");
enum_type->llvm_di_type = tag_di_type;
+ enum_type->data.enumeration.resolve_status = ResolveStatusLLVMFull;
}
static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) {
if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return;
- ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
+ TypeUnionField *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member;
ZigType *tag_type = union_type->data.unionation.tag_type;
- if (most_aligned_union_member == nullptr) {
+ uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
+ if (gen_field_count == 0) {
union_type->llvm_type = get_llvm_type(g, tag_type);
union_type->llvm_di_type = get_llvm_di_type(g, tag_type);
union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
@@ -7221,7 +7462,6 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;
}
- uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
ZigLLVMDIType **union_inner_di_types = allocate<ZigLLVMDIType*>(gen_field_count);
uint32_t field_count = union_type->data.unionation.src_field_count;
for (uint32_t i = 0; i < field_count; i += 1) {
@@ -7248,17 +7488,17 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
if (tag_type == nullptr || !type_has_bits(tag_type)) {
assert(most_aligned_union_member != nullptr);
- size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size;
+ size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
if (padding_bytes > 0) {
ZigType *u8_type = get_int_type(g, false, 8);
ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
LLVMTypeRef union_element_types[] = {
- most_aligned_union_member->llvm_type,
+ most_aligned_union_member->type_entry->llvm_type,
get_llvm_type(g, padding_array),
};
LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, false);
} else {
- LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->llvm_type, 1, false);
+ LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->type_entry->llvm_type, 1, false);
}
union_type->data.unionation.union_llvm_type = union_type->llvm_type;
union_type->data.unionation.gen_tag_index = SIZE_MAX;
@@ -7269,7 +7509,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name),
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
union_type->data.unionation.union_abi_size * 8,
- most_aligned_union_member->abi_align * 8,
+ most_aligned_union_member->align * 8,
ZigLLVM_DIFlags_Zero, union_inner_di_types,
gen_field_count, 0, "");
@@ -7280,14 +7520,14 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
}
LLVMTypeRef union_type_ref;
- size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size;
+ size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
if (padding_bytes == 0) {
- union_type_ref = get_llvm_type(g, most_aligned_union_member);
+ union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
} else {
ZigType *u8_type = get_int_type(g, false, 8);
ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
LLVMTypeRef union_element_types[] = {
- get_llvm_type(g, most_aligned_union_member),
+ get_llvm_type(g, most_aligned_union_member->type_entry),
get_llvm_type(g, padding_array),
};
union_type_ref = LLVMStructType(union_element_types, 2, false);
@@ -7303,7 +7543,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder,
ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion",
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
- most_aligned_union_member->size_in_bits, 8*most_aligned_union_member->abi_align,
+ most_aligned_union_member->type_entry->size_in_bits, 8*most_aligned_union_member->align,
ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, "");
uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type,
@@ -7314,8 +7554,8 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder,
ZigLLVMTypeToScope(union_type->llvm_di_type), "payload",
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
- most_aligned_union_member->size_in_bits,
- 8*most_aligned_union_member->abi_align,
+ most_aligned_union_member->type_entry->size_in_bits,
+ 8*most_aligned_union_member->align,
union_offset_in_bits,
ZigLLVM_DIFlags_Zero, union_di_type);
@@ -7352,6 +7592,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
if (type->llvm_di_type != nullptr) return;
+ if (resolve_pointer_zero_bits(g, type) != ErrorNone)
+ zig_unreachable();
+
if (!type_has_bits(type)) {
type->llvm_type = g->builtin_types.entry_void->llvm_type;
type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
@@ -7921,7 +8164,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
else
return resolve_llvm_types_struct(g, type, wanted_resolve_status, nullptr);
case ZigTypeIdEnum:
- return resolve_llvm_types_enum(g, type);
+ return resolve_llvm_types_enum(g, type, wanted_resolve_status);
case ZigTypeIdUnion:
return resolve_llvm_types_union(g, type, wanted_resolve_status);
case ZigTypeIdPointer: