| ... | @@ -1538,7 +1538,8 @@ static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType | ... | @@ -1538,7 +1538,8 @@ static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType |
| 1538 | return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union"); | 1538 | return emit_error_unless_type_allowed_in_packed_container(g, type_entry, source_node, "union"); |
| 1539 | } | 1539 | } |
| 1540 | | 1540 | |
| 1541 | bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | 1541 | Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) { |
| | 1542 | Error err; |
| 1542 | switch (type_entry->id) { | 1543 | switch (type_entry->id) { |
| 1543 | case ZigTypeIdInvalid: | 1544 | case ZigTypeIdInvalid: |
| 1544 | zig_unreachable(); | 1545 | zig_unreachable(); |
| ... | @@ -1555,11 +1556,13 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | ... | @@ -1555,11 +1556,13 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1555 | case ZigTypeIdVoid: | 1556 | case ZigTypeIdVoid: |
| 1556 | case ZigTypeIdFnFrame: | 1557 | case ZigTypeIdFnFrame: |
| 1557 | case ZigTypeIdAnyFrame: | 1558 | case ZigTypeIdAnyFrame: |
| 1558 | return false; | 1559 | *result = false; |
| | 1560 | return ErrorNone; |
| 1559 | case ZigTypeIdOpaque: | 1561 | case ZigTypeIdOpaque: |
| 1560 | case ZigTypeIdUnreachable: | 1562 | case ZigTypeIdUnreachable: |
| 1561 | case ZigTypeIdBool: | 1563 | case ZigTypeIdBool: |
| 1562 | return true; | 1564 | *result = true; |
| | 1565 | return ErrorNone; |
| 1563 | case ZigTypeIdInt: | 1566 | case ZigTypeIdInt: |
| 1564 | switch (type_entry->data.integral.bit_count) { | 1567 | switch (type_entry->data.integral.bit_count) { |
| 1565 | case 8: | 1568 | case 8: |
| ... | @@ -1567,37 +1570,52 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { | ... | @@ -1567,37 +1570,52 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1567 | case 32: | 1570 | case 32: |
| 1568 | case 64: | 1571 | case 64: |
| 1569 | case 128: | 1572 | case 128: |
| 1570 | return true; | 1573 | *result = true; |
| | 1574 | return ErrorNone; |
| 1571 | default: | 1575 | default: |
| 1572 | return false; | 1576 | *result = false; |
| | 1577 | return ErrorNone; |
| 1573 | } | 1578 | } |
| 1574 | case ZigTypeIdVector: | 1579 | 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); |
| 1576 | case ZigTypeIdFloat: | 1581 | case ZigTypeIdFloat: |
| 1577 | return true; | 1582 | *result = true; |
| | 1583 | return ErrorNone; |
| 1578 | case ZigTypeIdArray: | 1584 | 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); |
| 1580 | case ZigTypeIdFn: | 1586 | case ZigTypeIdFn: |
| 1581 | return type_entry->data.fn.fn_type_id.cc == CallingConventionC || | 1587 | *result = type_entry->data.fn.fn_type_id.cc == CallingConventionC || |
| 1582 | type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall; | 1588 | type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall; |
| | 1589 | return ErrorNone; |
| 1583 | case ZigTypeIdPointer: | 1590 | case ZigTypeIdPointer: |
| 1584 | if (type_size(g, type_entry) == 0) | 1591 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) |
| 1585 | return false; | 1592 | return err; |
| 1586 | return true; | 1593 | if (!type_has_bits(type_entry)) { |
| | 1594 | *result = false; |
| | 1595 | return ErrorNone; |
| | 1596 | } |
| | 1597 | *result = true; |
| | 1598 | return ErrorNone; |
| 1587 | case ZigTypeIdStruct: | 1599 | case ZigTypeIdStruct: |
| 1588 | return type_entry->data.structure.layout == ContainerLayoutExtern || type_entry->data.structure.layout == ContainerLayoutPacked; | 1600 | *result = type_entry->data.structure.layout == ContainerLayoutExtern || |
| 1589 | case ZigTypeIdOptional: | 1601 | type_entry->data.structure.layout == ContainerLayoutPacked; |
| 1590 | { | 1602 | return ErrorNone; |
| 1591 | ZigType *child_type = type_entry->data.maybe.child_type; | 1603 | case ZigTypeIdOptional: { |
| 1592 | if (child_type->id != ZigTypeIdPointer && child_type->id != ZigTypeIdFn) { | 1604 | ZigType *child_type = type_entry->data.maybe.child_type; |
| 1593 | return false; | 1605 | if (child_type->id != ZigTypeIdPointer && child_type->id != ZigTypeIdFn) { |
| 1594 | } | 1606 | *result = false; |
| 1595 | return type_allowed_in_extern(g, child_type); | 1607 | return ErrorNone; |
| 1596 | } | 1608 | } |
| | 1609 | return type_allowed_in_extern(g, child_type, result); |
| | 1610 | } |
| 1597 | case ZigTypeIdEnum: | 1611 | 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; |
| 1599 | case ZigTypeIdUnion: | 1615 | 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; |
| 1601 | } | 1619 | } |
| 1602 | zig_unreachable(); | 1620 | zig_unreachable(); |
| 1603 | } | 1621 | } |
| ... | @@ -1687,12 +1705,17 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc | ... | @@ -1687,12 +1705,17 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1687 | } | 1705 | } |
| 1688 | } | 1706 | } |
| 1689 | | 1707 | |
| 1690 | if (!calling_convention_allows_zig_types(fn_type_id.cc) && !type_allowed_in_extern(g, type_entry)) { | 1708 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 1691 | add_node_error(g, param_node->data.param_decl.type, | 1709 | bool ok_type; |
| 1692 | buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", | 1710 | if ((err = type_allowed_in_extern(g, type_entry, &ok_type))) |
| 1693 | buf_ptr(&type_entry->name), | 1711 | return g->builtin_types.entry_invalid; |
| 1694 | calling_convention_name(fn_type_id.cc))); | 1712 | if (!ok_type) { |
| 1695 | return g->builtin_types.entry_invalid; | 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 | } |
| 1696 | } | 1719 | } |
| 1697 | | 1720 | |
| 1698 | switch (type_entry->id) { | 1721 | switch (type_entry->id) { |
| ... | @@ -1809,7 +1832,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc | ... | @@ -1809,7 +1832,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1809 | { | 1832 | { |
| 1810 | if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown))) | 1833 | if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown))) |
| 1811 | return g->builtin_types.entry_invalid; | 1834 | 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) { |
| 1813 | add_node_error(g, fn_proto->return_type, | 1839 | add_node_error(g, fn_proto->return_type, |
| 1814 | buf_sprintf("return type '%s' not allowed in function with calling convention '%s'", | 1840 | buf_sprintf("return type '%s' not allowed in function with calling convention '%s'", |
| 1815 | buf_ptr(&fn_type_id.return_type->name), | 1841 | buf_ptr(&fn_type_id.return_type->name), |
| ... | @@ -2128,14 +2154,19 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { | ... | @@ -2128,14 +2154,19 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 2128 | return err; | 2154 | return err; |
| 2129 | } | 2155 | } |
| 2130 | | 2156 | |
| 2131 | if (struct_type->data.structure.layout == ContainerLayoutExtern && | 2157 | if (struct_type->data.structure.layout == ContainerLayoutExtern) { |
| 2132 | !type_allowed_in_extern(g, field_type)) | 2158 | bool ok_type; |
| 2133 | { | 2159 | if ((err = type_allowed_in_extern(g, field_type, &ok_type))) { |
| 2134 | add_node_error(g, field->decl_node, | 2160 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2135 | buf_sprintf("extern structs cannot contain fields of type '%s'", | 2161 | return ErrorSemanticAnalyzeFail; |
| 2136 | buf_ptr(&field_type->name))); | 2162 | } |
| 2137 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2163 | if (!ok_type) { |
| 2138 | return ErrorSemanticAnalyzeFail; | 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 | } |
| 2139 | } | 2170 | } |
| 2140 | } | 2171 | } |
| 2141 | | 2172 | |
| ... | @@ -2368,19 +2399,22 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { | ... | @@ -2368,19 +2399,22 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { |
| 2368 | return ErrorNone; | 2399 | return ErrorNone; |
| 2369 | } | 2400 | } |
| 2370 | | 2401 | |
| 2371 | static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) { | 2402 | static Error type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty, bool *result) { |
| 2372 | // Only integer types are allowed by the C ABI | 2403 | // Only integer types are allowed by the C ABI |
| 2373 | if(ty->id != ZigTypeIdInt) | 2404 | if(ty->id != ZigTypeIdInt) { |
| 2374 | return false; | 2405 | *result = false; |
| | 2406 | return ErrorNone; |
| | 2407 | } |
| 2375 | | 2408 | |
| 2376 | // According to the ANSI C standard the enumeration type should be either a | 2409 | // According to the ANSI C standard the enumeration type should be either a |
| 2377 | // signed char, a signed integer or an unsigned one. But GCC/Clang allow | 2410 | // signed char, a signed integer or an unsigned one. But GCC/Clang allow |
| 2378 | // other integral types as a compiler extension so let's accomodate them | 2411 | // other integral types as a compiler extension so let's accomodate them |
| 2379 | // aswell. | 2412 | // aswell. |
| 2380 | return type_allowed_in_extern(g, ty); | 2413 | return type_allowed_in_extern(g, ty, result); |
| 2381 | } | 2414 | } |
| 2382 | | 2415 | |
| 2383 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | 2416 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| | 2417 | Error err; |
| 2384 | assert(enum_type->id == ZigTypeIdEnum); | 2418 | assert(enum_type->id == ZigTypeIdEnum); |
| 2385 | | 2419 | |
| 2386 | if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid) | 2420 | if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid) |
| ... | @@ -2443,15 +2477,23 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2443,15 +2477,23 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2443 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2477 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2444 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 2478 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 2445 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | 2479 | 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")); | | |
| 2454 | } else { | 2480 | } 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 | } |
| 2455 | tag_int_type = wanted_tag_int_type; | 2497 | tag_int_type = wanted_tag_int_type; |
| 2456 | } | 2498 | } |
| 2457 | } | 2499 | } |