authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-23 15:02:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-23 15:02:38-04:00
log53ae03ebe9e0aa56bca1c9219a47d124b0435258
tree2f69fc4aeb6bdbc9567338b033337c4556f5c0c0
parent29b82d20a4534fc7e3393c21ad637d44d20449a2
signaturelock-open Commit is signed but in an unrecognized format.

make type_allowed_in_extern more robust

Previously if the type parameter was a pointer, it would assert that the size of the type was resolved. It used to be that the size of pointers was always resolved, however with lazy values, pointers gained the possibility of not having their size resolved. Now, type_allowed_in_extern triggers the resolution of whether a pointer is zero bits, and returns a possible error if the resolution fails. This fixes a compiler assertion when building the [zootdeck project](https://github.com/donpdonp/zootdeck). I do not have a test case reduction for the issue.

3 files changed, 105 insertions(+), 53 deletions(-)

src/analyze.cpp+91-49
......@@ -1538,7 +1538,8 @@ static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType
15381538 return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union");
15391539}
15401540
1541bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1541Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
1542 Error err;
15421543 switch (type_entry->id) {
15431544 case ZigTypeIdInvalid:
15441545 zig_unreachable();
......@@ -1555,11 +1556,13 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
15551556 case ZigTypeIdVoid:
15561557 case ZigTypeIdFnFrame:
15571558 case ZigTypeIdAnyFrame:
1558 return false;
1559 *result = false;
1560 return ErrorNone;
15591561 case ZigTypeIdOpaque:
15601562 case ZigTypeIdUnreachable:
15611563 case ZigTypeIdBool:
1562 return true;
1564 *result = true;
1565 return ErrorNone;
15631566 case ZigTypeIdInt:
15641567 switch (type_entry->data.integral.bit_count) {
15651568 case 8:
......@@ -1567,37 +1570,52 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
15671570 case 32:
15681571 case 64:
15691572 case 128:
1570 return true;
1573 *result = true;
1574 return ErrorNone;
15711575 default:
1572 return false;
1576 *result = false;
1577 return ErrorNone;
15731578 }
15741579 case ZigTypeIdVector:
1575 return type_allowed_in_extern(g, type_entry->data.vector.elem_type);
1580 return type_allowed_in_extern(g, type_entry->data.vector.elem_type, result);
15761581 case ZigTypeIdFloat:
1577 return true;
1582 *result = true;
1583 return ErrorNone;
15781584 case ZigTypeIdArray:
1579 return type_allowed_in_extern(g, type_entry->data.array.child_type);
1585 return type_allowed_in_extern(g, type_entry->data.array.child_type, result);
15801586 case ZigTypeIdFn:
1581 return type_entry->data.fn.fn_type_id.cc == CallingConventionC ||
1587 *result = type_entry->data.fn.fn_type_id.cc == CallingConventionC ||
15821588 type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall;
1589 return ErrorNone;
15831590 case ZigTypeIdPointer:
1584 if (type_size(g, type_entry) == 0)
1585 return false;
1586 return true;
1591 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1592 return err;
1593 if (!type_has_bits(type_entry)) {
1594 *result = false;
1595 return ErrorNone;
1596 }
1597 *result = true;
1598 return ErrorNone;
15871599 case ZigTypeIdStruct:
1588 return type_entry->data.structure.layout == ContainerLayoutExtern || type_entry->data.structure.layout == ContainerLayoutPacked;
1589 case ZigTypeIdOptional:
1590 {
1591 ZigType *child_type = type_entry->data.maybe.child_type;
1592 if (child_type->id != ZigTypeIdPointer && child_type->id != ZigTypeIdFn) {
1593 return false;
1594 }
1595 return type_allowed_in_extern(g, child_type);
1600 *result = type_entry->data.structure.layout == ContainerLayoutExtern ||
1601 type_entry->data.structure.layout == ContainerLayoutPacked;
1602 return ErrorNone;
1603 case ZigTypeIdOptional: {
1604 ZigType *child_type = type_entry->data.maybe.child_type;
1605 if (child_type->id != ZigTypeIdPointer && child_type->id != ZigTypeIdFn) {
1606 *result = false;
1607 return ErrorNone;
15961608 }
1609 return type_allowed_in_extern(g, child_type, result);
1610 }
15971611 case ZigTypeIdEnum:
1598 return type_entry->data.enumeration.layout == ContainerLayoutExtern || type_entry->data.enumeration.layout == ContainerLayoutPacked;
1612 *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
1613 type_entry->data.enumeration.layout == ContainerLayoutPacked;
1614 return ErrorNone;
15991615 case ZigTypeIdUnion:
1600 return type_entry->data.unionation.layout == ContainerLayoutExtern || type_entry->data.unionation.layout == ContainerLayoutPacked;
1616 *result = type_entry->data.unionation.layout == ContainerLayoutExtern ||
1617 type_entry->data.unionation.layout == ContainerLayoutPacked;
1618 return ErrorNone;
16011619 }
16021620 zig_unreachable();
16031621}
......@@ -1687,12 +1705,17 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
16871705 }
16881706 }
16891707
1690 if (!calling_convention_allows_zig_types(fn_type_id.cc) && !type_allowed_in_extern(g, type_entry)) {
1691 add_node_error(g, param_node->data.param_decl.type,
1692 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
1693 buf_ptr(&type_entry->name),
1694 calling_convention_name(fn_type_id.cc)));
1695 return g->builtin_types.entry_invalid;
1708 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
1709 bool ok_type;
1710 if ((err = type_allowed_in_extern(g, type_entry, &ok_type)))
1711 return g->builtin_types.entry_invalid;
1712 if (!ok_type) {
1713 add_node_error(g, param_node->data.param_decl.type,
1714 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
1715 buf_ptr(&type_entry->name),
1716 calling_convention_name(fn_type_id.cc)));
1717 return g->builtin_types.entry_invalid;
1718 }
16961719 }
16971720
16981721 switch (type_entry->id) {
......@@ -1809,7 +1832,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
18091832 {
18101833 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown)))
18111834 return g->builtin_types.entry_invalid;
1812 if (!type_allowed_in_extern(g, fn_type_id.return_type)) {
1835 bool ok_type;
1836 if ((err = type_allowed_in_extern(g, fn_type_id.return_type, &ok_type)))
1837 return g->builtin_types.entry_invalid;
1838 if (!ok_type) {
18131839 add_node_error(g, fn_proto->return_type,
18141840 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
18151841 buf_ptr(&fn_type_id.return_type->name),
......@@ -2128,14 +2154,19 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
21282154 return err;
21292155 }
21302156
2131 if (struct_type->data.structure.layout == ContainerLayoutExtern &&
2132 !type_allowed_in_extern(g, field_type))
2133 {
2134 add_node_error(g, field->decl_node,
2135 buf_sprintf("extern structs cannot contain fields of type '%s'",
2136 buf_ptr(&field_type->name)));
2137 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2138 return ErrorSemanticAnalyzeFail;
2157 if (struct_type->data.structure.layout == ContainerLayoutExtern) {
2158 bool ok_type;
2159 if ((err = type_allowed_in_extern(g, field_type, &ok_type))) {
2160 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2161 return ErrorSemanticAnalyzeFail;
2162 }
2163 if (!ok_type) {
2164 add_node_error(g, field->decl_node,
2165 buf_sprintf("extern structs cannot contain fields of type '%s'",
2166 buf_ptr(&field_type->name)));
2167 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2168 return ErrorSemanticAnalyzeFail;
2169 }
21392170 }
21402171 }
21412172
......@@ -2368,19 +2399,22 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
23682399 return ErrorNone;
23692400}
23702401
2371static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
2402static Error type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty, bool *result) {
23722403 // Only integer types are allowed by the C ABI
2373 if(ty->id != ZigTypeIdInt)
2374 return false;
2404 if(ty->id != ZigTypeIdInt) {
2405 *result = false;
2406 return ErrorNone;
2407 }
23752408
23762409 // According to the ANSI C standard the enumeration type should be either a
23772410 // signed char, a signed integer or an unsigned one. But GCC/Clang allow
23782411 // other integral types as a compiler extension so let's accomodate them
23792412 // aswell.
2380 return type_allowed_in_extern(g, ty);
2413 return type_allowed_in_extern(g, ty, result);
23812414}
23822415
23832416static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2417 Error err;
23842418 assert(enum_type->id == ZigTypeIdEnum);
23852419
23862420 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
......@@ -2443,15 +2477,23 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
24432477 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
24442478 add_node_error(g, decl_node->data.container_decl.init_arg_expr,
24452479 buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
2446 } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern &&
2447 !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) {
2448 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2449 ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
2450 buf_sprintf("'%s' is not a valid tag type for an extern enum",
2451 buf_ptr(&wanted_tag_int_type->name)));
2452 add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr,
2453 buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid"));
24542480 } else {
2481 if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
2482 bool ok_type;
2483 if ((err = type_is_valid_extern_enum_tag(g, wanted_tag_int_type, &ok_type))) {
2484 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2485 return err;
2486 }
2487 if (!ok_type) {
2488 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2489 ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr,
2490 buf_sprintf("'%s' is not a valid tag type for an extern enum",
2491 buf_ptr(&wanted_tag_int_type->name)));
2492 add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr,
2493 buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid"));
2494 return ErrorNone;
2495 }
2496 }
24552497 tag_int_type = wanted_tag_int_type;
24562498 }
24572499 }
src/analyze.hpp+1-1
......@@ -42,7 +42,7 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type);
4242bool handle_is_ptr(ZigType *type_entry);
4343
4444bool type_has_bits(ZigType *type_entry);
45bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
45Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result);
4646bool ptr_allows_addr_zero(ZigType *ptr_type);
4747bool type_is_nonnull_ptr(ZigType *type);
4848
src/ir.cpp+13-3
......@@ -14837,6 +14837,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1483714837}
1483814838
1483914839static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
14840 Error err;
14841
1484014842 IrInstruction *name = instruction->name->child;
1484114843 Buf *symbol_name = ir_resolve_str(ira, name);
1484214844 if (symbol_name == nullptr) {
......@@ -14933,8 +14935,12 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1493314935 want_var_export = true;
1493414936 }
1493514937 break;
14936 case ZigTypeIdArray:
14937 if (!type_allowed_in_extern(ira->codegen, target->value.type->data.array.child_type)) {
14938 case ZigTypeIdArray: {
14939 bool ok_type;
14940 if ((err = type_allowed_in_extern(ira->codegen, target->value.type->data.array.child_type, &ok_type)))
14941 return ira->codegen->invalid_instruction;
14942
14943 if (!ok_type) {
1493814944 ir_add_error(ira, target,
1493914945 buf_sprintf("array element type '%s' not extern-compatible",
1494014946 buf_ptr(&target->value.type->data.array.child_type->name)));
......@@ -14942,6 +14948,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1494214948 want_var_export = true;
1494314949 }
1494414950 break;
14951 }
1494514952 case ZigTypeIdMetaType: {
1494614953 ZigType *type_value = target->value.data.x_type;
1494714954 switch (type_value->id) {
......@@ -26720,7 +26727,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
2672026727 buf_create_from_str("unknown-length pointer to opaque"));
2672126728 return ErrorSemanticAnalyzeFail;
2672226729 } else if (lazy_ptr_type->ptr_len == PtrLenC) {
26723 if (!type_allowed_in_extern(ira->codegen, elem_type)) {
26730 bool ok_type;
26731 if ((err = type_allowed_in_extern(ira->codegen, elem_type, &ok_type)))
26732 return err;
26733 if (!ok_type) {
2672426734 ir_add_error(ira, lazy_ptr_type->elem_type,
2672526735 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'",
2672626736 buf_ptr(&elem_type->name)));