diff --git a/doc/docgen.zig b/doc/docgen.zig index 50523d0948..52f373f5b1 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -808,6 +808,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: anytype, source_token: .Keyword_noalias, .Keyword_noinline, .Keyword_nosuspend, + .Keyword_opaque, .Keyword_or, .Keyword_orelse, .Keyword_packed, diff --git a/doc/langref.html.in b/doc/langref.html.in index 22faf7fd8f..021fc76289 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1988,7 +1988,7 @@ test "null terminated array" {
{#syntax#}void{#endsyntax#} is distinct from {#syntax#}c_void{#endsyntax#}, which is defined like this: - {#syntax#}pub const c_void = @Type(.Opaque);{#endsyntax#}. + {#syntax#}pub const c_void = opaque {};{#endsyntax#}. {#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}c_void{#endsyntax#} has an unknown, but non-zero, size.
@@ -8471,7 +8471,7 @@ test "integer truncation" {
- {#syntax#}@Type(.Opaque){#endsyntax#} creates a new type with an unknown (but non-zero) size and alignment. + {#syntax#}opaque {}{#endsyntax#} declares a new type with an unknown (but non-zero) size and alignment. + It can have declarations like structs, unions, or enums.
This is typically used for type safety when interacting with C code that does not expose struct details. Example:
{#code_begin|test_err|expected type '*Derp', found '*Wat'#} -const Derp = @Type(.Opaque); -const Wat = @Type(.Opaque); +const Derp = opaque {}; +const Wat = opaque {}; extern fn bar(d: *Derp) void; fn foo(w: *Wat) callconv(.C) void { @@ -11193,7 +11194,7 @@ PtrTypeStart ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE ContainerDeclType - <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)? + <- (KEYWORD_struct / KEYWORD_enum / KEYWORD_opaque) (LPAREN Expr RPAREN)? / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? # Alignment @@ -11340,6 +11341,7 @@ KEYWORD_inline <- 'inline' end_of_word KEYWORD_noalias <- 'noalias' end_of_word KEYWORD_nosuspend <- 'nosuspend' end_of_word KEYWORD_null <- 'null' end_of_word +KEYWORD_opaque <- 'opaque' end_of_word KEYWORD_or <- 'or' end_of_word KEYWORD_orelse <- 'orelse' end_of_word KEYWORD_packed <- 'packed' end_of_word @@ -11368,7 +11370,7 @@ keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyframe / KEYWORD_anytype / KEYWORD_defer / KEYWORD_else / KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export / KEYWORD_extern / KEYWORD_false / KEYWORD_fn / KEYWORD_for / KEYWORD_if / KEYWORD_inline - / KEYWORD_noalias / KEYWORD_null / KEYWORD_or + / KEYWORD_noalias / KEYWORD_null / KEYWORD_opaque / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed / KEYWORD_pub / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection / KEYWORD_struct / KEYWORD_suspend diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 95b66d9af6..8543461f33 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -198,7 +198,7 @@ pub const TypeInfo = union(enum) { Union: Union, Fn: Fn, BoundFn: Fn, - Opaque: void, + Opaque: Opaque, Frame: Frame, AnyFrame: AnyFrame, Vector: Vector, @@ -359,6 +359,12 @@ pub const TypeInfo = union(enum) { args: []const FnArg, }; + /// This data structure is used by the Zig language code generation and + /// therefore must be kept in sync with the compiler implementation. + pub const Opaque = struct { + decls: []const Declaration, + }; + /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const Frame = struct { diff --git a/lib/std/c.zig b/lib/std/c.zig index 7cfc44714f..a75fcaa84b 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -329,8 +329,8 @@ pub extern "c" fn pthread_cond_signal(cond: *pthread_cond_t) c_int; pub extern "c" fn pthread_cond_broadcast(cond: *pthread_cond_t) c_int; pub extern "c" fn pthread_cond_destroy(cond: *pthread_cond_t) c_int; -pub const pthread_t = *@Type(.Opaque); -pub const FILE = @Type(.Opaque); +pub const pthread_t = *opaque {}; +pub const FILE = opaque {}; pub extern "c" fn dlopen(path: [*:0]const u8, mode: c_int) ?*c_void; pub extern "c" fn dlclose(handle: *c_void) c_int; diff --git a/lib/std/os/linux/bpf/kern.zig b/lib/std/os/linux/bpf/kern.zig index 3bd605301a..a2e9d36aa1 100644 --- a/lib/std/os/linux/bpf/kern.zig +++ b/lib/std/os/linux/bpf/kern.zig @@ -12,28 +12,28 @@ const in_bpf_program = switch (std.builtin.arch) { pub const helpers = if (in_bpf_program) @import("helpers.zig") else struct {}; -pub const BpfSock = @Type(.Opaque); -pub const BpfSockAddr = @Type(.Opaque); -pub const FibLookup = @Type(.Opaque); -pub const MapDef = @Type(.Opaque); -pub const PerfEventData = @Type(.Opaque); -pub const PerfEventValue = @Type(.Opaque); -pub const PidNsInfo = @Type(.Opaque); -pub const SeqFile = @Type(.Opaque); -pub const SkBuff = @Type(.Opaque); -pub const SkMsgMd = @Type(.Opaque); -pub const SkReusePortMd = @Type(.Opaque); -pub const Sock = @Type(.Opaque); -pub const SockAddr = @Type(.Opaque); -pub const SockOps = @Type(.Opaque); -pub const SockTuple = @Type(.Opaque); -pub const SpinLock = @Type(.Opaque); -pub const SysCtl = @Type(.Opaque); -pub const Tcp6Sock = @Type(.Opaque); -pub const TcpRequestSock = @Type(.Opaque); -pub const TcpSock = @Type(.Opaque); -pub const TcpTimewaitSock = @Type(.Opaque); -pub const TunnelKey = @Type(.Opaque); -pub const Udp6Sock = @Type(.Opaque); -pub const XdpMd = @Type(.Opaque); -pub const XfrmState = @Type(.Opaque); +pub const BpfSock = opaque {}; +pub const BpfSockAddr = opaque {}; +pub const FibLookup = opaque {}; +pub const MapDef = opaque {}; +pub const PerfEventData = opaque {}; +pub const PerfEventValue = opaque {}; +pub const PidNsInfo = opaque {}; +pub const SeqFile = opaque {}; +pub const SkBuff = opaque {}; +pub const SkMsgMd = opaque {}; +pub const SkReusePortMd = opaque {}; +pub const Sock = opaque {}; +pub const SockAddr = opaque {}; +pub const SockOps = opaque {}; +pub const SockTuple = opaque {}; +pub const SpinLock = opaque {}; +pub const SysCtl = opaque {}; +pub const Tcp6Sock = opaque {}; +pub const TcpRequestSock = opaque {}; +pub const TcpSock = opaque {}; +pub const TcpTimewaitSock = opaque {}; +pub const TunnelKey = opaque {}; +pub const Udp6Sock = opaque {}; +pub const XdpMd = opaque {}; +pub const XfrmState = opaque {}; diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 0127033db2..ba1544105c 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -17,7 +17,7 @@ pub var handle: Handle = undefined; pub var system_table: *tables.SystemTable = undefined; /// A handle to an event structure. -pub const Event = *@Type(.Opaque); +pub const Event = *opaque {}; /// GUIDs must be align(8) pub const Guid = extern struct { @@ -51,7 +51,7 @@ pub const Guid = extern struct { }; /// An EFI Handle represents a collection of related interfaces. -pub const Handle = *@Type(.Opaque); +pub const Handle = *opaque {}; /// This structure represents time information. pub const Time = extern struct { @@ -108,4 +108,4 @@ pub const TimeCapabilities = extern struct { }; /// File Handle as specified in the EFI Shell Spec -pub const FileHandle = *@Type(.Opaque); +pub const FileHandle = *opaque {}; diff --git a/lib/std/os/uefi/protocols/hii.zig b/lib/std/os/uefi/protocols/hii.zig index 960402828e..ed7c40d6ac 100644 --- a/lib/std/os/uefi/protocols/hii.zig +++ b/lib/std/os/uefi/protocols/hii.zig @@ -6,7 +6,7 @@ const uefi = @import("std").os.uefi; const Guid = uefi.Guid; -pub const HIIHandle = *@Type(.Opaque); +pub const HIIHandle = *opaque {}; /// The header found at the start of each package. pub const HIIPackageHeader = packed struct { diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index d22f42d6e8..bf786d5c91 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -32,16 +32,16 @@ pub const UCHAR = u8; pub const FLOAT = f32; pub const HANDLE = *c_void; pub const HCRYPTPROV = ULONG_PTR; -pub const HBRUSH = *@Type(.Opaque); -pub const HCURSOR = *@Type(.Opaque); -pub const HICON = *@Type(.Opaque); -pub const HINSTANCE = *@Type(.Opaque); -pub const HMENU = *@Type(.Opaque); -pub const HMODULE = *@Type(.Opaque); -pub const HWND = *@Type(.Opaque); -pub const HDC = *@Type(.Opaque); -pub const HGLRC = *@Type(.Opaque); -pub const FARPROC = *@Type(.Opaque); +pub const HBRUSH = *opaque {}; +pub const HCURSOR = *opaque {}; +pub const HICON = *opaque {}; +pub const HINSTANCE = *opaque {}; +pub const HMENU = *opaque {}; +pub const HMODULE = *opaque {}; +pub const HWND = *opaque {}; +pub const HDC = *opaque {}; +pub const HGLRC = *opaque {}; +pub const FARPROC = *opaque {}; pub const INT = c_int; pub const LPBYTE = *BYTE; pub const LPCH = *CHAR; @@ -81,7 +81,7 @@ pub const WPARAM = usize; pub const LPARAM = ?*c_void; pub const LRESULT = ?*c_void; -pub const va_list = *@Type(.Opaque); +pub const va_list = *opaque {}; pub const TRUE = 1; pub const FALSE = 0; @@ -1175,10 +1175,10 @@ pub const UNICODE_STRING = extern struct { Buffer: [*]WCHAR, }; -const ACTIVATION_CONTEXT_DATA = @Type(.Opaque); -const ASSEMBLY_STORAGE_MAP = @Type(.Opaque); -const FLS_CALLBACK_INFO = @Type(.Opaque); -const RTL_BITMAP = @Type(.Opaque); +const ACTIVATION_CONTEXT_DATA = opaque {}; +const ASSEMBLY_STORAGE_MAP = opaque {}; +const FLS_CALLBACK_INFO = opaque {}; +const RTL_BITMAP = opaque {}; pub const PRTL_BITMAP = *RTL_BITMAP; const KAFFINITY = usize; diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig index ac21b6ffc9..19bfc0d83e 100644 --- a/lib/std/os/windows/ws2_32.zig +++ b/lib/std/os/windows/ws2_32.zig @@ -5,7 +5,7 @@ // and substantial portions of the software. usingnamespace @import("bits.zig"); -pub const SOCKET = *@Type(.Opaque); +pub const SOCKET = *opaque {}; pub const INVALID_SOCKET = @intToPtr(SOCKET, ~@as(usize, 0)); pub const SOCKET_ERROR = -1; diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index d8943adde0..0973877aa8 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -288,7 +288,7 @@ pub const Error = union(enum) { pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'"); pub const ExpectedFn = SingleTokenError("Expected function, found '{}'"); pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'"); - pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'"); + 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 '{}'"); pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'"); pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{}'"); pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{}'"); diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 2af2ee4a45..467b06a5ca 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -2896,11 +2896,12 @@ const Parser = struct { /// <- KEYWORD_struct /// / KEYWORD_enum (LPAREN Expr RPAREN)? /// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? + /// / KEYWORD_opaque fn parseContainerDeclType(p: *Parser) !?ContainerDeclType { const kind_token = p.nextToken(); const init_arg_expr = switch (p.token_ids[kind_token]) { - .Keyword_struct => Node.ContainerDecl.InitArg{ .None = {} }, + .Keyword_struct, .Keyword_opaque => Node.ContainerDecl.InitArg{ .None = {} }, .Keyword_enum => blk: { if (p.eatToken(.LParen) != null) { const expr = try p.expectNode(parseExpr, .{ diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 67afbb77d9..8c8a2fc50b 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1492,7 +1492,19 @@ fn renderExpression( // TODO remove after 0.7.0 release if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@OpaqueType")) - return ais.writer().writeAll("@Type(.Opaque)"); + return ais.writer().writeAll("opaque {}"); + + // TODO remove after 0.7.0 release + { + const params = builtin_call.paramsConst(); + if (mem.eql(u8, tree.tokenSlice(builtin_call.builtin_token), "@Type") and + params.len == 1) + { + if (params[0].castTag(.EnumLiteral)) |enum_literal| + if (mem.eql(u8, tree.tokenSlice(enum_literal.name), "Opaque")) + return ais.writer().writeAll("opaque {}"); + } + } try renderToken(tree, ais, builtin_call.builtin_token, Space.None); // @name diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig index e40483c022..c8f33dbfaa 100644 --- a/lib/std/zig/tokenizer.zig +++ b/lib/std/zig/tokenizer.zig @@ -47,6 +47,7 @@ pub const Token = struct { .{ "noinline", .Keyword_noinline }, .{ "nosuspend", .Keyword_nosuspend }, .{ "null", .Keyword_null }, + .{ "opaque", .Keyword_opaque }, .{ "or", .Keyword_or }, .{ "orelse", .Keyword_orelse }, .{ "packed", .Keyword_packed }, @@ -173,6 +174,7 @@ pub const Token = struct { Keyword_noinline, Keyword_nosuspend, Keyword_null, + Keyword_opaque, Keyword_or, Keyword_orelse, Keyword_packed, @@ -296,6 +298,7 @@ pub const Token = struct { .Keyword_noinline => "noinline", .Keyword_nosuspend => "nosuspend", .Keyword_null => "null", + .Keyword_opaque => "opaque", .Keyword_or => "or", .Keyword_orelse => "orelse", .Keyword_packed => "packed", diff --git a/src/clang.zig b/src/clang.zig index 2551829084..e93060edc5 100644 --- a/src/clang.zig +++ b/src/clang.zig @@ -1,89 +1,89 @@ const builtin = @import("builtin"); -pub const struct_ZigClangConditionalOperator = @Type(.Opaque); -pub const struct_ZigClangBinaryConditionalOperator = @Type(.Opaque); -pub const struct_ZigClangAbstractConditionalOperator = @Type(.Opaque); -pub const struct_ZigClangAPInt = @Type(.Opaque); -pub const struct_ZigClangAPSInt = @Type(.Opaque); -pub const struct_ZigClangAPFloat = @Type(.Opaque); -pub const struct_ZigClangASTContext = @Type(.Opaque); -pub const struct_ZigClangASTUnit = @Type(.Opaque); -pub const struct_ZigClangArraySubscriptExpr = @Type(.Opaque); -pub const struct_ZigClangArrayType = @Type(.Opaque); -pub const struct_ZigClangAttributedType = @Type(.Opaque); -pub const struct_ZigClangBinaryOperator = @Type(.Opaque); -pub const struct_ZigClangBreakStmt = @Type(.Opaque); -pub const struct_ZigClangBuiltinType = @Type(.Opaque); -pub const struct_ZigClangCStyleCastExpr = @Type(.Opaque); -pub const struct_ZigClangCallExpr = @Type(.Opaque); -pub const struct_ZigClangCaseStmt = @Type(.Opaque); -pub const struct_ZigClangCompoundAssignOperator = @Type(.Opaque); -pub const struct_ZigClangCompoundStmt = @Type(.Opaque); -pub const struct_ZigClangConstantArrayType = @Type(.Opaque); -pub const struct_ZigClangContinueStmt = @Type(.Opaque); -pub const struct_ZigClangDecayedType = @Type(.Opaque); -pub const ZigClangDecl = @Type(.Opaque); -pub const struct_ZigClangDeclRefExpr = @Type(.Opaque); -pub const struct_ZigClangDeclStmt = @Type(.Opaque); -pub const struct_ZigClangDefaultStmt = @Type(.Opaque); -pub const struct_ZigClangDiagnosticOptions = @Type(.Opaque); -pub const struct_ZigClangDiagnosticsEngine = @Type(.Opaque); -pub const struct_ZigClangDoStmt = @Type(.Opaque); -pub const struct_ZigClangElaboratedType = @Type(.Opaque); -pub const struct_ZigClangEnumConstantDecl = @Type(.Opaque); -pub const struct_ZigClangEnumDecl = @Type(.Opaque); -pub const struct_ZigClangEnumType = @Type(.Opaque); -pub const struct_ZigClangExpr = @Type(.Opaque); -pub const struct_ZigClangFieldDecl = @Type(.Opaque); -pub const struct_ZigClangFileID = @Type(.Opaque); -pub const struct_ZigClangForStmt = @Type(.Opaque); -pub const struct_ZigClangFullSourceLoc = @Type(.Opaque); -pub const struct_ZigClangFunctionDecl = @Type(.Opaque); -pub const struct_ZigClangFunctionProtoType = @Type(.Opaque); -pub const struct_ZigClangIfStmt = @Type(.Opaque); -pub const struct_ZigClangImplicitCastExpr = @Type(.Opaque); -pub const struct_ZigClangIncompleteArrayType = @Type(.Opaque); -pub const struct_ZigClangIntegerLiteral = @Type(.Opaque); -pub const struct_ZigClangMacroDefinitionRecord = @Type(.Opaque); -pub const struct_ZigClangMacroExpansion = @Type(.Opaque); -pub const struct_ZigClangMacroQualifiedType = @Type(.Opaque); -pub const struct_ZigClangMemberExpr = @Type(.Opaque); -pub const struct_ZigClangNamedDecl = @Type(.Opaque); -pub const struct_ZigClangNone = @Type(.Opaque); -pub const struct_ZigClangOpaqueValueExpr = @Type(.Opaque); -pub const struct_ZigClangPCHContainerOperations = @Type(.Opaque); -pub const struct_ZigClangParenExpr = @Type(.Opaque); -pub const struct_ZigClangParenType = @Type(.Opaque); -pub const struct_ZigClangParmVarDecl = @Type(.Opaque); -pub const struct_ZigClangPointerType = @Type(.Opaque); -pub const struct_ZigClangPreprocessedEntity = @Type(.Opaque); -pub const struct_ZigClangRecordDecl = @Type(.Opaque); -pub const struct_ZigClangRecordType = @Type(.Opaque); -pub const struct_ZigClangReturnStmt = @Type(.Opaque); -pub const struct_ZigClangSkipFunctionBodiesScope = @Type(.Opaque); -pub const struct_ZigClangSourceManager = @Type(.Opaque); -pub const struct_ZigClangSourceRange = @Type(.Opaque); -pub const ZigClangStmt = @Type(.Opaque); -pub const struct_ZigClangStringLiteral = @Type(.Opaque); -pub const struct_ZigClangStringRef = @Type(.Opaque); -pub const struct_ZigClangSwitchStmt = @Type(.Opaque); -pub const struct_ZigClangTagDecl = @Type(.Opaque); -pub const struct_ZigClangType = @Type(.Opaque); -pub const struct_ZigClangTypedefNameDecl = @Type(.Opaque); -pub const struct_ZigClangTypedefType = @Type(.Opaque); -pub const struct_ZigClangUnaryExprOrTypeTraitExpr = @Type(.Opaque); -pub const struct_ZigClangUnaryOperator = @Type(.Opaque); -pub const struct_ZigClangValueDecl = @Type(.Opaque); -pub const struct_ZigClangVarDecl = @Type(.Opaque); -pub const struct_ZigClangWhileStmt = @Type(.Opaque); -pub const struct_ZigClangFunctionType = @Type(.Opaque); -pub const struct_ZigClangPredefinedExpr = @Type(.Opaque); -pub const struct_ZigClangInitListExpr = @Type(.Opaque); -pub const ZigClangPreprocessingRecord = @Type(.Opaque); -pub const ZigClangFloatingLiteral = @Type(.Opaque); -pub const ZigClangConstantExpr = @Type(.Opaque); -pub const ZigClangCharacterLiteral = @Type(.Opaque); -pub const ZigClangStmtExpr = @Type(.Opaque); +pub const struct_ZigClangConditionalOperator = opaque {}; +pub const struct_ZigClangBinaryConditionalOperator = opaque {}; +pub const struct_ZigClangAbstractConditionalOperator = opaque {}; +pub const struct_ZigClangAPInt = opaque {}; +pub const struct_ZigClangAPSInt = opaque {}; +pub const struct_ZigClangAPFloat = opaque {}; +pub const struct_ZigClangASTContext = opaque {}; +pub const struct_ZigClangASTUnit = opaque {}; +pub const struct_ZigClangArraySubscriptExpr = opaque {}; +pub const struct_ZigClangArrayType = opaque {}; +pub const struct_ZigClangAttributedType = opaque {}; +pub const struct_ZigClangBinaryOperator = opaque {}; +pub const struct_ZigClangBreakStmt = opaque {}; +pub const struct_ZigClangBuiltinType = opaque {}; +pub const struct_ZigClangCStyleCastExpr = opaque {}; +pub const struct_ZigClangCallExpr = opaque {}; +pub const struct_ZigClangCaseStmt = opaque {}; +pub const struct_ZigClangCompoundAssignOperator = opaque {}; +pub const struct_ZigClangCompoundStmt = opaque {}; +pub const struct_ZigClangConstantArrayType = opaque {}; +pub const struct_ZigClangContinueStmt = opaque {}; +pub const struct_ZigClangDecayedType = opaque {}; +pub const ZigClangDecl = opaque {}; +pub const struct_ZigClangDeclRefExpr = opaque {}; +pub const struct_ZigClangDeclStmt = opaque {}; +pub const struct_ZigClangDefaultStmt = opaque {}; +pub const struct_ZigClangDiagnosticOptions = opaque {}; +pub const struct_ZigClangDiagnosticsEngine = opaque {}; +pub const struct_ZigClangDoStmt = opaque {}; +pub const struct_ZigClangElaboratedType = opaque {}; +pub const struct_ZigClangEnumConstantDecl = opaque {}; +pub const struct_ZigClangEnumDecl = opaque {}; +pub const struct_ZigClangEnumType = opaque {}; +pub const struct_ZigClangExpr = opaque {}; +pub const struct_ZigClangFieldDecl = opaque {}; +pub const struct_ZigClangFileID = opaque {}; +pub const struct_ZigClangForStmt = opaque {}; +pub const struct_ZigClangFullSourceLoc = opaque {}; +pub const struct_ZigClangFunctionDecl = opaque {}; +pub const struct_ZigClangFunctionProtoType = opaque {}; +pub const struct_ZigClangIfStmt = opaque {}; +pub const struct_ZigClangImplicitCastExpr = opaque {}; +pub const struct_ZigClangIncompleteArrayType = opaque {}; +pub const struct_ZigClangIntegerLiteral = opaque {}; +pub const struct_ZigClangMacroDefinitionRecord = opaque {}; +pub const struct_ZigClangMacroExpansion = opaque {}; +pub const struct_ZigClangMacroQualifiedType = opaque {}; +pub const struct_ZigClangMemberExpr = opaque {}; +pub const struct_ZigClangNamedDecl = opaque {}; +pub const struct_ZigClangNone = opaque {}; +pub const struct_ZigClangOpaqueValueExpr = opaque {}; +pub const struct_ZigClangPCHContainerOperations = opaque {}; +pub const struct_ZigClangParenExpr = opaque {}; +pub const struct_ZigClangParenType = opaque {}; +pub const struct_ZigClangParmVarDecl = opaque {}; +pub const struct_ZigClangPointerType = opaque {}; +pub const struct_ZigClangPreprocessedEntity = opaque {}; +pub const struct_ZigClangRecordDecl = opaque {}; +pub const struct_ZigClangRecordType = opaque {}; +pub const struct_ZigClangReturnStmt = opaque {}; +pub const struct_ZigClangSkipFunctionBodiesScope = opaque {}; +pub const struct_ZigClangSourceManager = opaque {}; +pub const struct_ZigClangSourceRange = opaque {}; +pub const ZigClangStmt = opaque {}; +pub const struct_ZigClangStringLiteral = opaque {}; +pub const struct_ZigClangStringRef = opaque {}; +pub const struct_ZigClangSwitchStmt = opaque {}; +pub const struct_ZigClangTagDecl = opaque {}; +pub const struct_ZigClangType = opaque {}; +pub const struct_ZigClangTypedefNameDecl = opaque {}; +pub const struct_ZigClangTypedefType = opaque {}; +pub const struct_ZigClangUnaryExprOrTypeTraitExpr = opaque {}; +pub const struct_ZigClangUnaryOperator = opaque {}; +pub const struct_ZigClangValueDecl = opaque {}; +pub const struct_ZigClangVarDecl = opaque {}; +pub const struct_ZigClangWhileStmt = opaque {}; +pub const struct_ZigClangFunctionType = opaque {}; +pub const struct_ZigClangPredefinedExpr = opaque {}; +pub const struct_ZigClangInitListExpr = opaque {}; +pub const ZigClangPreprocessingRecord = opaque {}; +pub const ZigClangFloatingLiteral = opaque {}; +pub const ZigClangConstantExpr = opaque {}; +pub const ZigClangCharacterLiteral = opaque {}; +pub const ZigClangStmtExpr = opaque {}; pub const ZigClangBO = extern enum { PtrMemD, @@ -749,11 +749,11 @@ pub const ZigClangCharacterLiteral_CharacterKind = extern enum { }; pub const ZigClangRecordDecl_field_iterator = extern struct { - opaque: *c_void, + ptr: *c_void, }; pub const ZigClangEnumDecl_enumerator_iterator = extern struct { - opaque: *c_void, + ptr: *c_void, }; pub const ZigClangPreprocessingRecord_iterator = extern struct { diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index fc201538f1..89f3693a13 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -1053,6 +1053,7 @@ enum ContainerKind { ContainerKindStruct, ContainerKindEnum, ContainerKindUnion, + ContainerKindOpaque, }; enum ContainerLayout { @@ -1570,7 +1571,10 @@ enum OnePossibleValue { }; struct ZigTypeOpaque { + AstNode *decl_node; Buf *bare_name; + + ScopeDecls *decls_scope; }; struct ZigTypeFnFrame { diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 88bbf6b9ac..bc9d265bd1 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -86,14 +86,18 @@ ZigType *new_type_table_entry(ZigTypeId id) { } static ScopeDecls **get_container_scope_ptr(ZigType *type_entry) { - if (type_entry->id == ZigTypeIdStruct) { - return &type_entry->data.structure.decls_scope; - } else if (type_entry->id == ZigTypeIdEnum) { - return &type_entry->data.enumeration.decls_scope; - } else if (type_entry->id == ZigTypeIdUnion) { - return &type_entry->data.unionation.decls_scope; + switch (type_entry->id) { + case ZigTypeIdStruct: + return &type_entry->data.structure.decls_scope; + case ZigTypeIdEnum: + return &type_entry->data.enumeration.decls_scope; + case ZigTypeIdUnion: + return &type_entry->data.unionation.decls_scope; + case ZigTypeIdOpaque: + return &type_entry->data.opaque.decls_scope; + default: + zig_unreachable(); } - zig_unreachable(); } static ScopeExpr *find_expr_scope(Scope *scope) { @@ -912,13 +916,17 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c ZigType *import = scope ? get_scope_import(scope) : nullptr; unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0; + // Note: duplicated in get_partial_container_type entry->llvm_type = LLVMInt8Type(); entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, ZigLLVMTag_DW_structure_type(), full_name, import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr, import ? import->data.structure.root_struct->di_file : nullptr, line); + entry->data.opaque.decl_node = source_node; entry->data.opaque.bare_name = bare_name; + entry->data.opaque.decls_scope = create_decls_scope( + g, source_node, scope, entry, import, &entry->name); // The actual size is unknown, but the value must not be 0 because that // is how type_has_bits is determined. @@ -1078,6 +1086,8 @@ static ZigTypeId container_to_type(ContainerKind kind) { return ZigTypeIdEnum; case ContainerKindUnion: return ZigTypeIdUnion; + case ContainerKindOpaque: + return ZigTypeIdOpaque; } zig_unreachable(); } @@ -1119,6 +1129,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind entry->data.unionation.decl_node = decl_node; entry->data.unionation.layout = layout; break; + case ContainerKindOpaque: { + ZigType *import = scope ? get_scope_import(scope) : nullptr; + unsigned line = decl_node ? (unsigned)(decl_node->line + 1) : 0; + // Note: duplicated in get_opaque_type + entry->llvm_type = LLVMInt8Type(); + entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, + ZigLLVMTag_DW_structure_type(), full_name, + import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr, + import ? import->data.structure.root_struct->di_file : nullptr, + line); + entry->data.opaque.decl_node = decl_node; + entry->abi_size = SIZE_MAX; + entry->size_in_bits = SIZE_MAX; + entry->abi_align = 1; + break; + } } buf_init_from_str(&entry->name, full_name); @@ -3428,6 +3454,21 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { return ErrorNone; } +static Error resolve_opaque_type(CodeGen *g, ZigType *opaque_type) { + Error err = ErrorNone; + AstNode *container_node = opaque_type->data.opaque.decl_node; + if (container_node != nullptr) { + assert(container_node->type == NodeTypeContainerDecl); + AstNodeContainerDecl *container_decl = &container_node->data.container_decl; + for (size_t i = 0; i < container_decl->fields.length; i++) { + AstNode *field_node = container_decl->fields.items[i]; + add_node_error(g, field_node, buf_create_from_str("opaque types cannot have fields")); + err = ErrorSemanticAnalyzeFail; + } + } + return err; +} + void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type) { if (g->root_import == container_type || buf_len(&container_type->name) == 0) return; buf_append_buf(buf, &container_type->name); @@ -3893,6 +3934,8 @@ static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) { return resolve_enum_zero_bits(g, tld_container->type_entry); case ZigTypeIdUnion: return resolve_union_type(g, tld_container->type_entry); + case ZigTypeIdOpaque: + return resolve_opaque_type(g, tld_container->type_entry); default: zig_unreachable(); } @@ -4459,6 +4502,7 @@ bool is_container(ZigType *type_entry) { return type_entry->data.structure.special != StructSpecialSlice; case ZigTypeIdEnum: case ZigTypeIdUnion: + case ZigTypeIdOpaque: return true; case ZigTypeIdPointer: case ZigTypeIdMetaType: @@ -4478,7 +4522,6 @@ bool is_container(ZigType *type_entry) { case ZigTypeIdErrorSet: case ZigTypeIdFn: case ZigTypeIdBoundFn: - case ZigTypeIdOpaque: case ZigTypeIdVector: case ZigTypeIdFnFrame: case ZigTypeIdAnyFrame: @@ -8165,6 +8208,7 @@ const char *container_string(ContainerKind kind) { case ContainerKindEnum: return "enum"; case ContainerKindStruct: return "struct"; case ContainerKindUnion: return "union"; + case ContainerKindOpaque: return "opaque"; } zig_unreachable(); } @@ -8183,8 +8227,6 @@ Buf *type_bare_name(ZigType *type_entry) { return &type_entry->name; } else if (is_container(type_entry)) { return get_container_scope(type_entry)->bare_name; - } else if (type_entry->id == ZigTypeIdOpaque) { - return type_entry->data.opaque.bare_name; } else { return &type_entry->name; } diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 44f3cd0bde..5ab667e831 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -22386,6 +22386,8 @@ static IrInstGen *ir_analyze_container_member_access_inner(IrAnalyze *ira, prefix_name = "enum "; } else if (bare_struct_type->id == ZigTypeIdUnion) { prefix_name = "union "; + } else if (bare_struct_type->id == ZigTypeIdOpaque) { + prefix_name = "opaque type "; } else { prefix_name = ""; } @@ -22586,7 +22588,7 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name } } - if (bare_type->id == ZigTypeIdEnum) { + if (bare_type->id == ZigTypeIdEnum || bare_type->id == ZigTypeIdOpaque) { return ir_analyze_container_member_access_inner(ira, bare_type, field_name, source_instr, container_ptr, container_ptr_src, container_type); } @@ -25182,7 +25184,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy case ZigTypeIdEnumLiteral: case ZigTypeIdUndefined: case ZigTypeIdNull: - case ZigTypeIdOpaque: result = ira->codegen->intern.for_void(); break; case ZigTypeIdInt: @@ -25736,6 +25737,25 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy if ((err = ir_make_type_info_value(ira, source_instr, fn_type, &result))) return err; + break; + } + case ZigTypeIdOpaque: + { + result = ira->codegen->pass1_arena->create