| ... | ... | @@ -1538,7 +1538,8 @@ static Error emit_error_unless_type_allowed_in_packed_union(CodeGen *g, ZigType |
| 1538 | 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 | 1543 | switch (type_entry->id) { |
| 1543 | 1544 | case ZigTypeIdInvalid: |
| 1544 | 1545 | zig_unreachable(); |
| ... | ... | @@ -1555,11 +1556,13 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1555 | 1556 | case ZigTypeIdVoid: |
| 1556 | 1557 | case ZigTypeIdFnFrame: |
| 1557 | 1558 | case ZigTypeIdAnyFrame: |
| 1558 | | return false; |
| 1559 | *result = false; |
| 1560 | return ErrorNone; |
| 1559 | 1561 | case ZigTypeIdOpaque: |
| 1560 | 1562 | case ZigTypeIdUnreachable: |
| 1561 | 1563 | case ZigTypeIdBool: |
| 1562 | | return true; |
| 1564 | *result = true; |
| 1565 | return ErrorNone; |
| 1563 | 1566 | case ZigTypeIdInt: |
| 1564 | 1567 | switch (type_entry->data.integral.bit_count) { |
| 1565 | 1568 | case 8: |
| ... | ... | @@ -1567,37 +1570,52 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1567 | 1570 | case 32: |
| 1568 | 1571 | case 64: |
| 1569 | 1572 | case 128: |
| 1570 | | return true; |
| 1573 | *result = true; |
| 1574 | return ErrorNone; |
| 1571 | 1575 | default: |
| 1572 | | return false; |
| 1576 | *result = false; |
| 1577 | return ErrorNone; |
| 1573 | 1578 | } |
| 1574 | 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 | 1581 | case ZigTypeIdFloat: |
| 1577 | | return true; |
| 1582 | *result = true; |
| 1583 | return ErrorNone; |
| 1578 | 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 | 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 | 1588 | type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall; |
| 1589 | return ErrorNone; |
| 1583 | 1590 | 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; |
| 1587 | 1599 | 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; |
| 1596 | 1608 | } |
| 1609 | return type_allowed_in_extern(g, child_type, result); |
| 1610 | } |
| 1597 | 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 | 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 | 1620 | zig_unreachable(); |
| 1603 | 1621 | } |
| ... | ... | @@ -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)) { |
| 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 | } |
| 1696 | 1719 | } |
| 1697 | 1720 | |
| 1698 | 1721 | switch (type_entry->id) { |
| ... | ... | @@ -1809,7 +1832,10 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1809 | 1832 | { |
| 1810 | 1833 | if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusSizeKnown))) |
| 1811 | 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 | 1839 | add_node_error(g, fn_proto->return_type, |
| 1814 | 1840 | buf_sprintf("return type '%s' not allowed in function with calling convention '%s'", |
| 1815 | 1841 | buf_ptr(&fn_type_id.return_type->name), |
| ... | ... | @@ -2128,14 +2154,19 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { |
| 2128 | 2154 | return err; |
| 2129 | 2155 | } |
| 2130 | 2156 | |
| 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 | } |
| 2139 | 2170 | } |
| 2140 | 2171 | } |
| 2141 | 2172 | |
| ... | ... | @@ -2368,19 +2399,22 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { |
| 2368 | 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 | 2403 | // 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 | } |
| 2375 | 2408 | |
| 2376 | 2409 | // According to the ANSI C standard the enumeration type should be either a |
| 2377 | 2410 | // signed char, a signed integer or an unsigned one. But GCC/Clang allow |
| 2378 | 2411 | // other integral types as a compiler extension so let's accomodate them |
| 2379 | 2412 | // aswell. |
| 2380 | | return type_allowed_in_extern(g, ty); |
| 2413 | return type_allowed_in_extern(g, ty, result); |
| 2381 | 2414 | } |
| 2382 | 2415 | |
| 2383 | 2416 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2417 | Error err; |
| 2384 | 2418 | assert(enum_type->id == ZigTypeIdEnum); |
| 2385 | 2419 | |
| 2386 | 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 | 2477 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2444 | 2478 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 2445 | 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 | 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 | 2497 | tag_int_type = wanted_tag_int_type; |
| 2456 | 2498 | } |
| 2457 | 2499 | } |