| author | |
| committer | |
| log | 069fbb3c01d8be0940d60e3324213a0cde4a42d5 |
| tree | 6e236ae2f9cca59057afd945ec5cad6fee855d27 |
| parent | 7f7e2d608adb81cd00e54fd7fe5e7035a890565f |
| signature | Commit is signed but in an unrecognized format. |
15 files changed, 159 insertions(+), 29 deletions(-)
doc/langref.html.in+3-2| ... | ... | @@ -11193,7 +11193,7 @@ PtrTypeStart |
| 11193 | 11193 | ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE |
| 11194 | 11194 | |
| 11195 | 11195 | ContainerDeclType |
| 11196 | <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)? | |
| 11196 | <- (KEYWORD_struct / KEYWORD_enum / KEYWORD_opaque) (LPAREN Expr RPAREN)? | |
| 11197 | 11197 | / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| 11198 | 11198 | |
| 11199 | 11199 | # Alignment |
| ... | ... | @@ -11340,6 +11340,7 @@ KEYWORD_inline <- 'inline' end_of_word |
| 11340 | 11340 | KEYWORD_noalias <- 'noalias' end_of_word |
| 11341 | 11341 | KEYWORD_nosuspend <- 'nosuspend' end_of_word |
| 11342 | 11342 | KEYWORD_null <- 'null' end_of_word |
| 11343 | KEYWORD_opaque <- 'opaque' end_of_word | |
| 11343 | 11344 | KEYWORD_or <- 'or' end_of_word |
| 11344 | 11345 | KEYWORD_orelse <- 'orelse' end_of_word |
| 11345 | 11346 | KEYWORD_packed <- 'packed' end_of_word |
| ... | ... | @@ -11368,7 +11369,7 @@ keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyframe / KEYWORD_anytype |
| 11368 | 11369 | / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer |
| 11369 | 11370 | / KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false |
| 11370 | 11371 | / KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline |
| 11371 | / KEYWORD_noalias / KEYWORD_null / KEYWORD_or | |
| 11372 | / KEYWORD_noalias / KEYWORD_null / KEYWORD_opaque / KEYWORD_or | |
| 11372 | 11373 | / KEYWORD_orelse / KEYWORD_packed / KEYWORD_pub |
| 11373 | 11374 | / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection |
| 11374 | 11375 | / KEYWORD_struct / KEYWORD_suspend |
lib/std/builtin.zig+7-1| ... | ... | @@ -199,7 +199,7 @@ pub const TypeInfo = union(enum) { |
| 199 | 199 | Union: Union, |
| 200 | 200 | Fn: Fn, |
| 201 | 201 | BoundFn: Fn, |
| 202 | Opaque: void, | |
| 202 | Opaque: Opaque, | |
| 203 | 203 | Frame: Frame, |
| 204 | 204 | AnyFrame: AnyFrame, |
| 205 | 205 | Vector: Vector, |
| ... | ... | @@ -360,6 +360,12 @@ pub const TypeInfo = union(enum) { |
| 360 | 360 | args: []const FnArg, |
| 361 | 361 | }; |
| 362 | 362 | |
| 363 | /// This data structure is used by the Zig language code generation and | |
| 364 | /// therefore must be kept in sync with the compiler implementation. | |
| 365 | pub const Opaque = struct { | |
| 366 | decls: []const Declaration, | |
| 367 | }; | |
| 368 | ||
| 363 | 369 | /// This data structure is used by the Zig language code generation and |
| 364 | 370 | /// therefore must be kept in sync with the compiler implementation. |
| 365 | 371 | pub const Frame = struct { |
lib/std/zig/ast.zig+1-1| ... | ... | @@ -288,7 +288,7 @@ pub const Error = union(enum) { |
| 288 | 288 | pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'"); |
| 289 | 289 | pub const ExpectedFn = SingleTokenError("Expected function, found '{}'"); |
| 290 | 290 | pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'"); |
| 291 | pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'"); | |
| 291 | pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', '" ++ Token.Id.Keyword_enum.symbol() ++ "', or '" ++ Token.Id.Keyword_opaque.symbol() ++ "', found '{}'"); | |
| 292 | 292 | pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'"); |
| 293 | 293 | pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{}'"); |
| 294 | 294 | pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{}'"); |
lib/std/zig/parse.zig+2-1| ... | ... | @@ -2896,11 +2896,12 @@ const Parser = struct { |
| 2896 | 2896 | /// <- KEYWORD_struct |
| 2897 | 2897 | /// / KEYWORD_enum (LPAREN Expr RPAREN)? |
| 2898 | 2898 | /// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| 2899 | /// / KEYWORD_opaque | |
| 2899 | 2900 | fn parseContainerDeclType(p: *Parser) !?ContainerDeclType { |
| 2900 | 2901 | const kind_token = p.nextToken(); |
| 2901 | 2902 | |
| 2902 | 2903 | const init_arg_expr = switch (p.token_ids[kind_token]) { |
| 2903 | .Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} }, | |
| 2904 | .Keyword_struct, .Keyword_opaque => Node.ContainerDecl.InitArg{ .None = {} }, | |
| 2904 | 2905 | .Keyword_enum => blk: { |
| 2905 | 2906 | if (p.eatToken(.LParen) != null) { |
| 2906 | 2907 | const expr = try p.expectNode(parseExpr, .{ |
lib/std/zig/render.zig+13-1| ... | ... | @@ -1492,7 +1492,19 @@ fn renderExpression( |
| 1492 | 1492 | |
| 1493 | 1493 | // TODO remove after 0.7.0 release |
| 1494 | 1494 | if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType")) |
| 1495 | return ais.writer().writeAll("@Type(.Opaque)"); | |
| 1495 | return ais.writer().writeAll("opaque {}"); | |
| 1496 | ||
| 1497 | // TODO remove after 0.7.0 release | |
| 1498 | { | |
| 1499 | const params = builtin_call.paramsConst(); | |
| 1500 | if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and | |
| 1501 | params.len == 1) | |
| 1502 | { | |
| 1503 | if (params[0].castTag(.EnumLiteral)) |enum_literal| | |
| 1504 | if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque")) | |
| 1505 | return ais.writer().writeAll("opaque {}"); | |
| 1506 | } | |
| 1507 | } | |
| 1496 | 1508 | |
| 1497 | 1509 | try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name |
| 1498 | 1510 |
lib/std/zig/tokenizer.zig+3| ... | ... | @@ -47,6 +47,7 @@ pub const Token = struct { |
| 47 | 47 | .{ "noinline", .Keyword_noinline }, |
| 48 | 48 | .{ "nosuspend", .Keyword_nosuspend }, |
| 49 | 49 | .{ "null", .Keyword_null }, |
| 50 | .{ "opaque", .Keyword_opaque }, | |
| 50 | 51 | .{ "or", .Keyword_or }, |
| 51 | 52 | .{ "orelse", .Keyword_orelse }, |
| 52 | 53 | .{ "packed", .Keyword_packed }, |
| ... | ... | @@ -173,6 +174,7 @@ pub const Token = struct { |
| 173 | 174 | Keyword_noinline, |
| 174 | 175 | Keyword_nosuspend, |
| 175 | 176 | Keyword_null, |
| 177 | Keyword_opaque, | |
| 176 | 178 | Keyword_or, |
| 177 | 179 | Keyword_orelse, |
| 178 | 180 | Keyword_packed, |
| ... | ... | @@ -296,6 +298,7 @@ pub const Token = struct { |
| 296 | 298 | .Keyword_noinline => "noinline", |
| 297 | 299 | .Keyword_nosuspend => "nosuspend", |
| 298 | 300 | .Keyword_null => "null", |
| 301 | .Keyword_opaque => "opaque", | |
| 299 | 302 | .Keyword_or => "or", |
| 300 | 303 | .Keyword_orelse => "orelse", |
| 301 | 304 | .Keyword_packed => "packed", |
src/stage1/all_types.hpp+4| ... | ... | @@ -1054,6 +1054,7 @@ enum ContainerKind { |
| 1054 | 1054 | ContainerKindStruct, |
| 1055 | 1055 | ContainerKindEnum, |
| 1056 | 1056 | ContainerKindUnion, |
| 1057 | ContainerKindOpaque, | |
| 1057 | 1058 | }; |
| 1058 | 1059 | |
| 1059 | 1060 | enum ContainerLayout { |
| ... | ... | @@ -1571,7 +1572,10 @@ enum OnePossibleValue { |
| 1571 | 1572 | }; |
| 1572 | 1573 | |
| 1573 | 1574 | struct ZigTypeOpaque { |
| 1575 | AstNode *decl_node; | |
| 1574 | 1576 | Buf *bare_name; |
| 1577 | ||
| 1578 | ScopeDecls *decls_scope; | |
| 1575 | 1579 | }; |
| 1576 | 1580 | |
| 1577 | 1581 | struct ZigTypeFnFrame { |
src/stage1/analyze.cpp+44-10| ... | ... | @@ -86,14 +86,18 @@ ZigType *new_type_table_entry(ZigTypeId id) { |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | static ScopeDecls **get_container_scope_ptr(ZigType *type_entry) { |
| 89 | if (type_entry->id == ZigTypeIdStruct) { | |
| 90 | return &type_entry->data.structure.decls_scope; | |
| 91 | } else if (type_entry->id == ZigTypeIdEnum) { | |
| 92 | return &type_entry->data.enumeration.decls_scope; | |
| 93 | } else if (type_entry->id == ZigTypeIdUnion) { | |
| 94 | return &type_entry->data.unionation.decls_scope; | |
| 89 | switch (type_entry->id) { | |
| 90 | case ZigTypeIdStruct: | |
| 91 | return &type_entry->data.structure.decls_scope; | |
| 92 | case ZigTypeIdEnum: | |
| 93 | return &type_entry->data.enumeration.decls_scope; | |
| 94 | case ZigTypeIdUnion: | |
| 95 | return &type_entry->data.unionation.decls_scope; | |
| 96 | case ZigTypeIdOpaque: | |
| 97 | return &type_entry->data.opaque.decls_scope; | |
| 98 | default: | |
| 99 | zig_unreachable(); | |
| 95 | 100 | } |
| 96 | zig_unreachable(); | |
| 97 | 101 | } |
| 98 | 102 | |
| 99 | 103 | static ScopeExpr *find_expr_scope(Scope *scope) { |
| ... | ... | @@ -912,13 +916,17 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c |
| 912 | 916 | ZigType *import = scope ? get_scope_import(scope) : nullptr; |
| 913 | 917 | unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0; |
| 914 | 918 | |
| 919 | // Note: duplicated in get_partial_container_type | |
| 915 | 920 | entry->llvm_type = LLVMInt8Type(); |
| 916 | 921 | entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, |
| 917 | 922 | ZigLLVMTag_DW_structure_type(), full_name, |
| 918 | 923 | import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr, |
| 919 | 924 | import ? import->data.structure.root_struct->di_file : nullptr, |
| 920 | 925 | line); |
| 926 | entry->data.opaque.decl_node = source_node; | |
| 921 | 927 | entry->data.opaque.bare_name = bare_name; |
| 928 | entry->data.opaque.decls_scope = create_decls_scope( | |
| 929 | g, source_node, scope, entry, import, &entry->name); | |
| 922 | 930 | |
| 923 | 931 | // The actual size is unknown, but the value must not be 0 because that |
| 924 | 932 | // is how type_has_bits is determined. |
| ... | ... | @@ -1080,6 +1088,8 @@ static ZigTypeId container_to_type(ContainerKind kind) { |
| 1080 | 1088 | return ZigTypeIdEnum; |
| 1081 | 1089 | case ContainerKindUnion: |
| 1082 | 1090 | return ZigTypeIdUnion; |
| 1091 | case ContainerKindOpaque: | |
| 1092 | return ZigTypeIdOpaque; | |
| 1083 | 1093 | } |
| 1084 | 1094 | zig_unreachable(); |
| 1085 | 1095 | } |
| ... | ... | @@ -1121,6 +1131,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind |
| 1121 | 1131 | entry->data.unionation.decl_node = decl_node; |
| 1122 | 1132 | entry->data.unionation.layout = layout; |
| 1123 | 1133 | break; |
| 1134 | case ContainerKindOpaque: { | |
| 1135 | ZigType *import = scope ? get_scope_import(scope) : nullptr; | |
| 1136 | unsigned line = decl_node ? (unsigned)(decl_node->line + 1) : 0; | |
| 1137 | // Note: duplicated in get_opaque_type | |
| 1138 | entry->llvm_type = LLVMInt8Type(); | |
| 1139 | entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, | |
| 1140 | ZigLLVMTag_DW_structure_type(), full_name, | |
| 1141 | import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr, | |
| 1142 | import ? import->data.structure.root_struct->di_file : nullptr, | |
| 1143 | line); | |
| 1144 | entry->data.opaque.decl_node = decl_node; | |
| 1145 | entry->abi_size = SIZE_MAX; | |
| 1146 | entry->size_in_bits = SIZE_MAX; | |
| 1147 | entry->abi_align = 1; | |
| 1148 | break; | |
| 1149 | } | |
| 1124 | 1150 | } |
| 1125 | 1151 | |
| 1126 | 1152 | buf_init_from_str(&entry->name, full_name); |
| ... | ... | @@ -3430,6 +3456,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { |
| 3430 | 3456 | return ErrorNone; |
| 3431 | 3457 | } |
| 3432 | 3458 | |
| 3459 | static Error resolve_opaque_type(CodeGen *g, ZigType *opaque_type) { | |
| 3460 | opaque_type->abi_align = UINT32_MAX; | |
| 3461 | opaque_type->abi_size = SIZE_MAX; | |
| 3462 | opaque_type->size_in_bits = SIZE_MAX; | |
| 3463 | return ErrorNone; | |
| 3464 | } | |
| 3465 | ||
| 3433 | 3466 | void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type) { |
| 3434 | 3467 | if (g->root_import == container_type || buf_len(&container_type->name) == 0) return; |
| 3435 | 3468 | buf_append_buf(buf, &container_type->name); |
| ... | ... | @@ -3896,6 +3929,8 @@ static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) { |
| 3896 | 3929 | return resolve_enum_zero_bits(g, tld_container->type_entry); |
| 3897 | 3930 | case ZigTypeIdUnion: |
| 3898 | 3931 | return resolve_union_type(g, tld_container->type_entry); |
| 3932 | case ZigTypeIdOpaque: | |
| 3933 | return resolve_opaque_type(g, tld_container->type_entry); | |
| 3899 | 3934 | default: |
| 3900 | 3935 | zig_unreachable(); |
| 3901 | 3936 | } |
| ... | ... | @@ -4462,6 +4497,7 @@ bool is_container(ZigType *type_entry) { |
| 4462 | 4497 | return type_entry->data.structure.special != StructSpecialSlice; |
| 4463 | 4498 | case ZigTypeIdEnum: |
| 4464 | 4499 | case ZigTypeIdUnion: |
| 4500 | case ZigTypeIdOpaque: | |
| 4465 | 4501 | return true; |
| 4466 | 4502 | case ZigTypeIdPointer: |
| 4467 | 4503 | case ZigTypeIdMetaType: |
| ... | ... | @@ -4481,7 +4517,6 @@ bool is_container(ZigType *type_entry) { |
| 4481 | 4517 | case ZigTypeIdErrorSet: |
| 4482 | 4518 | case ZigTypeIdFn: |
| 4483 | 4519 | case ZigTypeIdBoundFn: |
| 4484 | case ZigTypeIdOpaque: | |
| 4485 | 4520 | case ZigTypeIdVector: |
| 4486 | 4521 | case ZigTypeIdFnFrame: |
| 4487 | 4522 | case ZigTypeIdAnyFrame: |
| ... | ... | @@ -8168,6 +8203,7 @@ const char *container_string(ContainerKind kind) { |
| 8168 | 8203 | case ContainerKindEnum: return "enum"; |
| 8169 | 8204 | case ContainerKindStruct: return "struct"; |
| 8170 | 8205 | case ContainerKindUnion: return "union"; |
| 8206 | case ContainerKindOpaque: return "opaque"; | |
| 8171 | 8207 | } |
| 8172 | 8208 | zig_unreachable(); |
| 8173 | 8209 | } |
| ... | ... | @@ -8186,8 +8222,6 @@ Buf *type_bare_name(ZigType *type_entry) { |
| 8186 | 8222 | return &type_entry->name; |
| 8187 | 8223 | } else if (is_container(type_entry)) { |
| 8188 | 8224 | return get_container_scope(type_entry)->bare_name; |
| 8189 | } else if (type_entry->id == ZigTypeIdOpaque) { | |
| 8190 | return type_entry->data.opaque.bare_name; | |
| 8191 | 8225 | } else { |
| 8192 | 8226 | return &type_entry->name; |
| 8193 | 8227 | } |
src/stage1/ir.cpp+35-2| ... | ... | @@ -22587,7 +22587,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name |
| 22587 | 22587 | } |
| 22588 | 22588 | } |
| 22589 | 22589 | |
| 22590 | if (bare_type->id == ZigTypeIdEnum) { | |
| 22590 | if (bare_type->id == ZigTypeIdEnum || bare_type->id == ZigTypeIdOpaque) { | |
| 22591 | 22591 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 22592 | 22592 | source_instr, container_ptr, container_ptr_src, container_type); |
| 22593 | 22593 | } |
| ... | ... | @@ -25183,7 +25183,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25183 | 25183 | case ZigTypeIdEnumLiteral: |
| 25184 | 25184 | case ZigTypeIdUndefined: |
| 25185 | 25185 | case ZigTypeIdNull: |
| 25186 | case ZigTypeIdOpaque: | |
| 25187 | 25186 | result = ira->codegen->intern.for_void(); |
| 25188 | 25187 | break; |
| 25189 | 25188 | case ZigTypeIdInt: |
| ... | ... | @@ -25737,6 +25736,25 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25737 | 25736 | if ((err = ir_make_type_info_value(ira, source_instr, fn_type, &result))) |
| 25738 | 25737 | return err; |
| 25739 | 25738 | |
| 25739 | break; | |
| 25740 | } | |
| 25741 | case ZigTypeIdOpaque: | |
| 25742 | { | |
| 25743 | result = ira->codegen->pass1_arena->create<ZigValue>(); | |
| 25744 | result->special = ConstValSpecialStatic; | |
| 25745 | result->type = ir_type_info_get_type(ira, "Opaque", nullptr); | |
| 25746 | ||
| 25747 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1); | |
| 25748 | result->data.x_struct.fields = fields; | |
| 25749 | ||
| 25750 | // decls: []TypeInfo.Declaration | |
| 25751 | ensure_field_index(result->type, "decls", 0); | |
| 25752 | if ((err = ir_make_type_info_decls(ira, source_instr, fields[0], | |
| 25753 | type_entry->data.opaque.decls_scope, false))) | |
| 25754 | { | |
| 25755 | return err; | |
| 25756 | } | |
| 25757 | ||
| 25740 | 25758 | break; |
| 25741 | 25759 | } |
| 25742 | 25760 | case ZigTypeIdFnFrame: |
| ... | ... | @@ -26044,6 +26062,21 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26044 | 26062 | return get_error_union_type(ira->codegen, err_set_type, payload_type); |
| 26045 | 26063 | } |
| 26046 | 26064 | case ZigTypeIdOpaque: { |
| 26065 | assert(payload->special == ConstValSpecialStatic); | |
| 26066 | assert(payload->type == ir_type_info_get_type(ira, "Opaque", nullptr)); | |
| 26067 | ||
| 26068 | ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 0); | |
| 26069 | if (decls_value == nullptr) | |
| 26070 | return ira->codegen->invalid_inst_gen->value->type; | |
| 26071 | assert(decls_value->special == ConstValSpecialStatic); | |
| 26072 | assert(is_slice(decls_value->type)); | |
| 26073 | ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index]; | |
| 26074 | size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint); | |
| 26075 | if (decls_len != 0) { | |
| 26076 | ir_add_error(ira, source_instr, buf_create_from_str("TypeInfo.Struct.decls must be empty for @Type")); | |
| 26077 | return ira->codegen->invalid_inst_gen->value->type; | |
| 26078 | } | |
| 26079 | ||
| 26047 | 26080 | Buf *bare_name = buf_alloc(); |
| 26048 | 26081 | Buf *full_name = get_anon_type_name(ira->codegen, |
| 26049 | 26082 | ira->old_irb.exec, "opaque", source_instr->scope, source_instr->source_node, bare_name); |
src/stage1/parser.cpp+9| ... | ... | @@ -2920,6 +2920,7 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { |
| 2920 | 2920 | // <- KEYWORD_struct |
| 2921 | 2921 | // / KEYWORD_enum (LPAREN Expr RPAREN)? |
| 2922 | 2922 | // / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| 2923 | // / KEYWORD_opaque | |
| 2923 | 2924 | static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2924 | 2925 | Token *first = eat_token_if(pc, TokenIdKeywordStruct); |
| 2925 | 2926 | if (first != nullptr) { |
| ... | ... | @@ -2929,6 +2930,14 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2929 | 2930 | return res; |
| 2930 | 2931 | } |
| 2931 | 2932 | |
| 2933 | first = eat_token_if(pc, TokenIdKeywordOpaque); | |
| 2934 | if (first != nullptr) { | |
| 2935 | AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); | |
| 2936 | res->data.container_decl.init_arg_expr = nullptr; | |
| 2937 | res->data.container_decl.kind = ContainerKindOpaque; | |
| 2938 | return res; | |
| 2939 | } | |
| 2940 | ||
| 2932 | 2941 | first = eat_token_if(pc, TokenIdKeywordEnum); |
| 2933 | 2942 | if (first != nullptr) { |
| 2934 | 2943 | AstNode *init_arg_expr = nullptr; |
src/stage1/tokenizer.cpp+2| ... | ... | @@ -133,6 +133,7 @@ static const struct ZigKeyword zig_keywords[] = { |
| 133 | 133 | {"noinline", TokenIdKeywordNoInline}, |
| 134 | 134 | {"nosuspend", TokenIdKeywordNoSuspend}, |
| 135 | 135 | {"null", TokenIdKeywordNull}, |
| 136 | {"opaque", TokenIdKeywordOpaque}, | |
| 136 | 137 | {"or", TokenIdKeywordOr}, |
| 137 | 138 | {"orelse", TokenIdKeywordOrElse}, |
| 138 | 139 | {"packed", TokenIdKeywordPacked}, |
| ... | ... | @@ -1595,6 +1596,7 @@ const char * token_name(TokenId id) { |
| 1595 | 1596 | case TokenIdKeywordNoInline: return "noinline"; |
| 1596 | 1597 | case TokenIdKeywordNoSuspend: return "nosuspend"; |
| 1597 | 1598 | case TokenIdKeywordNull: return "null"; |
| 1599 | case TokenIdKeywordOpaque: return "opaque"; | |
| 1598 | 1600 | case TokenIdKeywordOr: return "or"; |
| 1599 | 1601 | case TokenIdKeywordOrElse: return "orelse"; |
| 1600 | 1602 | case TokenIdKeywordPacked: return "packed"; |
src/stage1/tokenizer.hpp+1| ... | ... | @@ -81,6 +81,7 @@ enum TokenId { |
| 81 | 81 | TokenIdKeywordNoAlias, |
| 82 | 82 | TokenIdKeywordNoSuspend, |
| 83 | 83 | TokenIdKeywordNull, |
| 84 | TokenIdKeywordOpaque, | |
| 84 | 85 | TokenIdKeywordOr, |
| 85 | 86 | TokenIdKeywordOrElse, |
| 86 | 87 | TokenIdKeywordPacked, |
src/translate_c.zig+8-8| ... | ... | @@ -930,9 +930,9 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* |
| 930 | 930 | const init_node = blk: { |
| 931 | 931 | const rp = makeRestorePoint(c); |
| 932 | 932 | const record_def = ZigClangRecordDecl_getDefinition(record_decl) orelse { |
| 933 | const opaque = try transCreateNodeOpaqueType(c); | |
| 933 | const opaque_type = try transCreateNodeOpaqueType(c); | |
| 934 | 934 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 935 | break :blk opaque; | |
| 935 | break :blk opaque_type; | |
| 936 | 936 | }; |
| 937 | 937 | |
| 938 | 938 | const layout_tok = try if (ZigClangRecordDecl_getPackedAttribute(record_decl)) |
| ... | ... | @@ -954,17 +954,17 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* |
| 954 | 954 | const field_qt = ZigClangFieldDecl_getType(field_decl); |
| 955 | 955 | |
| 956 | 956 | if (ZigClangFieldDecl_isBitField(field_decl)) { |
| 957 | const opaque = try transCreateNodeOpaqueType(c); | |
| 957 | const opaque_type = try transCreateNodeOpaqueType(c); | |
| 958 | 958 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 959 | 959 | try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name}); |
| 960 | break :blk opaque; | |
| 960 | break :blk opaque_type; | |
| 961 | 961 | } |
| 962 | 962 | |
| 963 | 963 | if (ZigClangType_isIncompleteOrZeroLengthArrayType(qualTypeCanon(field_qt), c.clang_context)) { |
| 964 | const opaque = try transCreateNodeOpaqueType(c); | |
| 964 | const opaque_type = try transCreateNodeOpaqueType(c); | |
| 965 | 965 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 966 | 966 | try emitWarning(c, field_loc, "{} demoted to opaque type - has variable length array", .{container_kind_name}); |
| 967 | break :blk opaque; | |
| 967 | break :blk opaque_type; | |
| 968 | 968 | } |
| 969 | 969 | |
| 970 | 970 | var is_anon = false; |
| ... | ... | @@ -979,10 +979,10 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* |
| 979 | 979 | _ = try appendToken(c, .Colon, ":"); |
| 980 | 980 | const field_type = transQualType(rp, field_qt, field_loc) catch |err| switch (err) { |
| 981 | 981 | error.UnsupportedType => { |
| 982 | const opaque = try transCreateNodeOpaqueType(c); | |
| 982 | const opaque_type = try transCreateNodeOpaqueType(c); | |
| 983 | 983 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 984 | 984 | try emitWarning(c, record_loc, "{} demoted to opaque type - unable to translate type of field {}", .{ container_kind_name, raw_name }); |
| 985 | break :blk opaque; | |
| 985 | break :blk opaque_type; | |
| 986 | 986 | }, |
| 987 | 987 | else => |e| return e, |
| 988 | 988 | }; |
test/stage1/behavior/type.zig+11-2| ... | ... | @@ -190,8 +190,17 @@ test "Type.ErrorUnion" { |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | 192 | test "Type.Opaque" { |
| 193 | testing.expect(@Type(.Opaque) != @Type(.Opaque)); | |
| 194 | testing.expect(@typeInfo(@Type(.Opaque)) == .Opaque); | |
| 193 | const Opaque = @Type(.{ | |
| 194 | .Opaque = .{ | |
| 195 | .decls = &[_]TypeInfo.Declaration{}, | |
| 196 | }, | |
| 197 | }); | |
| 198 | testing.expect(Opaque != opaque {}); | |
| 199 | testing.expectEqualSlices( | |
| 200 | TypeInfo.Declaration, | |
| 201 | &[_]TypeInfo.Declaration{}, | |
| 202 | @typeInfo(Opaque).Opaque.decls, | |
| 203 | ); | |
| 195 | 204 | } |
| 196 | 205 | |
| 197 | 206 | test "Type.Vector" { |
test/stage1/behavior/type_info.zig+16-1| ... | ... | @@ -199,7 +199,7 @@ fn testUnion() void { |
| 199 | 199 | expect(typeinfo_info.Union.tag_type.? == TypeId); |
| 200 | 200 | expect(typeinfo_info.Union.fields.len == 25); |
| 201 | 201 | expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int)); |
| 202 | expect(typeinfo_info.Union.decls.len == 21); | |
| 202 | expect(typeinfo_info.Union.decls.len == 22); | |
| 203 | 203 | |
| 204 | 204 | const TestNoTagUnion = union { |
| 205 | 205 | Foo: void, |
| ... | ... | @@ -265,6 +265,21 @@ const TestStruct = packed struct { |
| 265 | 265 | const Self = @This(); |
| 266 | 266 | }; |
| 267 | 267 | |
| 268 | test "type info: opaque info" { | |
| 269 | testOpaque(); | |
| 270 | comptime testOpaque(); | |
| 271 | } | |
| 272 | ||
| 273 | fn testOpaque() void { | |
| 274 | const Foo = opaque { | |
| 275 | const A = 1; | |
| 276 | fn b() void {} | |
| 277 | }; | |
| 278 | ||
| 279 | const foo_info = @typeInfo(Foo); | |
| 280 | expect(foo_info.Opaque.decls.len == 2); | |
| 281 | } | |
| 282 | ||
| 268 | 283 | test "type info: function type info" { |
| 269 | 284 | // wasm doesn't support align attributes on functions |
| 270 | 285 | if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest; |