about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexey Yerin <yyp@disroot.org>2023-10-04 20:59:45 +0300
committerAlexey Yerin <yyp@disroot.org>2023-10-04 20:59:45 +0300
commit07cff557463d13bbd1baa970f609c8dbb13e16a8 (patch)
tree5ed04987ffde8fd18f7e58886cdb3e7e57465609
parenta3f09a04518ce9ed7cb93719149f75c36ad02856 (diff)
Update for opaque and other Hare changes
-rw-r--r--bindings/gobject/types.ha2
-rw-r--r--bindings/types/libc/types.ha2
-rw-r--r--cmd/demo/main.ha4
-rw-r--r--cmd/demo4/main.ha4
-rw-r--r--cmd/hare-gi/ctype.ha21
-rw-r--r--cmd/hare-gi/emit.ha42
-rw-r--r--gir/parse.ha82
-rw-r--r--gir/types.ha2
8 files changed, 90 insertions, 69 deletions
diff --git a/bindings/gobject/types.ha b/bindings/gobject/types.ha
index 193bffd..570fe30 100644
--- a/bindings/gobject/types.ha
+++ b/bindings/gobject/types.ha
@@ -9,5 +9,5 @@ export type ValueUnion = union {
 	v_uint64: u64,
 	v_float: f32,
 	v_double: f64,
-	v_pointer: *void,
+	v_pointer: *opaque,
 };
diff --git a/bindings/types/libc/types.ha b/bindings/types/libc/types.ha
index bfb0dc0..e6b83b7 100644
--- a/bindings/types/libc/types.ha
+++ b/bindings/types/libc/types.ha
@@ -14,7 +14,7 @@ export type tm = struct {
 	tm_isdst: int,
 };
 
-export type FILE = void;
+export type FILE = opaque;
 
 export type passwd = struct {
 	pw_name: *c::char,
diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha
index cf807c6..0926134 100644
--- a/cmd/demo/main.ha
+++ b/cmd/demo/main.ha
@@ -6,7 +6,7 @@ use os;
 use rt;
 use types::c;
 
-fn about_clicked(btn: *gtk::Button, data: *void) void = {
+fn about_clicked(btn: *gtk::Button, data: *opaque) void = {
 	let dialog = gtk::about_dialog_new();
 	const authors: []*c::char = [
 		c::fromstr("Harriet?"),
@@ -28,7 +28,7 @@ fn about_clicked(btn: *gtk::Button, data: *void) void = {
 	gtk::widget_show_all(dialog);
 };
 
-fn activate(app: *gio::Application, data: *void) void = {
+fn activate(app: *gio::Application, data: *opaque) void = {
 	const app = app: *gtk::Application;
 
 	let button = gtk::button_new_with_label(c::fromstr("About"));
diff --git a/cmd/demo4/main.ha b/cmd/demo4/main.ha
index c46bed2..ea8649c 100644
--- a/cmd/demo4/main.ha
+++ b/cmd/demo4/main.ha
@@ -6,7 +6,7 @@ use os;
 use rt;
 use types::c;
 
-fn about_clicked(btn: *gtk4::Button, data: *void) void = {
+fn about_clicked(btn: *gtk4::Button, data: *opaque) void = {
 	let dialog = gtk4::about_dialog_new();
 	const authors: []*c::char = [
 		c::fromstr("Harriet?"),
@@ -28,7 +28,7 @@ fn about_clicked(btn: *gtk4::Button, data: *void) void = {
 	gtk4::widget_show(dialog);
 };
 
-fn activate(app: *gio::Application, data: *void) void = {
+fn activate(app: *gio::Application, data: *opaque) void = {
 	const app = app: *gtk4::Application;
 
 	let button = gtk4::button_new_with_label(c::fromstr("About"));
diff --git a/cmd/hare-gi/ctype.ha b/cmd/hare-gi/ctype.ha
index 185be7d..c687703 100644
--- a/cmd/hare-gi/ctype.ha
+++ b/cmd/hare-gi/ctype.ha
@@ -9,13 +9,15 @@ type ctype = ((cmodule, str) | str | cbuiltin | cpointer);
 type cpointer = *ctype;
 type cbuiltin = enum {
 	VOID,
+	OPAQUE,
 	INT,
 	UINT,
 	BOOL,
 	SIZE,
 	RUNE,
 	VALIST,
-	VOID_POINTER,
+	UINTPTR,
+	OPAQUE_POINTER,
 
 	CHAR,
 	UCHAR,
@@ -50,13 +52,15 @@ fn ctype_finish(type_: ctype) void = {
 
 fn cbuiltin_str(b: cbuiltin) const str = switch (b) {
 case cbuiltin::VOID => yield "void";
+case cbuiltin::OPAQUE => yield "opaque";
 case cbuiltin::INT => yield "int";
 case cbuiltin::UINT => yield "uint";
 case cbuiltin::BOOL => yield "bool";
 case cbuiltin::SIZE => yield "size";
 case cbuiltin::RUNE => yield "rune";
 case cbuiltin::VALIST => yield "valist";
-case cbuiltin::VOID_POINTER => yield "*void";
+case cbuiltin::UINTPTR => yield "uintptr";
+case cbuiltin::OPAQUE_POINTER => yield "*opaque";
 
 case cbuiltin::CHAR => yield "c::char";
 case cbuiltin::UCHAR => yield "c::uchar";
@@ -130,10 +134,11 @@ let map: [](str, ctype) = [
 	("guint", cbuiltin::UINT),
 	("gfloat", cbuiltin::F32),
 	("gdouble", cbuiltin::F64),
-	("gpointer", cbuiltin::VOID_POINTER),
-	("gconstpointer", cbuiltin::VOID_POINTER),
+	("gpointer", cbuiltin::OPAQUE_POINTER),
+	("gconstpointer", cbuiltin::OPAQUE_POINTER),
 	("grefcount", cbuiltin::UINT),
 	("gatomicrefcount", cbuiltin::UINT),
+	("guintptr", cbuiltin::UINTPTR),
 
 	("gint8", cbuiltin::I8), ("guint8", cbuiltin::U8),
 	("gint16", cbuiltin::I16), ("guint16", cbuiltin::U16),
@@ -191,6 +196,14 @@ fn parse_ctype(type_: str) ctype = {
 	case let r: rune =>
 		switch (r) {
 		case '*' =>
+			match (current) {
+			case let b: cbuiltin =>
+				if (b == cbuiltin::VOID) {
+					current = cbuiltin::OPAQUE_POINTER;
+					continue;
+				};
+			case => void;
+			};
 			current = alloc(current): cpointer: ctype;
 		case => abort();
 		};
diff --git a/cmd/hare-gi/emit.ha b/cmd/hare-gi/emit.ha
index 9f3486e..cf0ecce 100644
--- a/cmd/hare-gi/emit.ha
+++ b/cmd/hare-gi/emit.ha
@@ -27,7 +27,7 @@ fn emit(ctx: *context) (void | io::error) = {
 
 		if (ns.output_file == -1) continue;
 
-		static let wbuf: [os::BUFSIZ]u8 = [0...];
+		static let wbuf: [os::BUFSZ]u8 = [0...];
 		const stream = bufio::init(ns.output_file, [], wbuf);
 		ctx.current.output = &stream;
 
@@ -86,7 +86,7 @@ fn emit_alias(ctx: *context, alias: *gir::alias) (void | io::error) = {
 	emit_doc(ctx, alias)?;
 	fmt::fprintf(ctx.current.output, "export type {} = ",
 		fix_identifier(alias.name))?;
-	emit_type(ctx, alias.inner)?;
+	emit_type(ctx, alias.inner, ctype_flag::VOID_IS_OPAQUE)?;
 	fmt::fprintln(ctx.current.output, ";")?;
 };
 
@@ -101,7 +101,7 @@ fn emit_class(ctx: *context, class: *gir::class) (void | io::error) = {
 		fix_identifier(class.name))?;
 	if (len(class.entries) == 0) {
 		// opaque
-		fmt::fprintln(ctx.current.output, "*void;")?;
+		fmt::fprintln(ctx.current.output, "*opaque;")?;
 	} else {
 		fmt::fprintln(ctx.current.output, "struct {")?;
 		for (let i = 0z; i < len(class.entries); i += 1) {
@@ -146,7 +146,7 @@ fn emit_interface(ctx: *context, iface: *gir::interface) (void | io::error) = {
 		fix_identifier(iface.name))?;
 	if (len(iface.entries) == 0) {
 		// opaque
-		fmt::fprintln(ctx.current.output, "*void;")?;
+		fmt::fprintln(ctx.current.output, "*opaque;")?;
 	} else {
 		fmt::fprintln(ctx.current.output, "struct {")?;
 		for (let i = 0z; i < len(iface.entries); i += 1) {
@@ -190,7 +190,7 @@ fn emit_union(ctx: *context, union_: *gir::union_) (void | io::error) = {
 	fmt::fprintf(ctx.current.output, "export type {} = ",
 		fix_identifier(union_.name))?;
 	if (len(union_.entries) == 0) {
-		fmt::fprintln(ctx.current.output, "void;")?; // FIXME
+		fmt::fprintln(ctx.current.output, "opaque;")?; // FIXME
 	} else {
 		fmt::fprintln(ctx.current.output, "union {")?;
 		for (let i = 0z; i < len(union_.entries); i += 1) {
@@ -221,8 +221,8 @@ fn emit_record(ctx: *context, record: *gir::record) (void | io::error) = {
 	emit_doc(ctx, record)?;
 	fmt::fprintf(ctx.current.output, "export type {} = ",
 		fix_identifier(record.name))?;
-	if (record.opaque || len(record.entries) == 0) {
-		fmt::fprintln(ctx.current.output, "*void;")?;
+	if (record.opaque_ || len(record.entries) == 0) {
+		fmt::fprintln(ctx.current.output, "*opaque;")?;
 	} else {
 		fmt::fprintln(ctx.current.output, "struct {")?;
 		for (let i = 0z; i < len(record.entries); i += 1) {
@@ -404,13 +404,13 @@ fn emit_signal(ctx: *context, signal: *gir::signal) (void | io::error) = {
 	//
 	// export fn window_connect_activate(
 	// 	instance: *gtk::Window,
-	// 	handler: *fn(instance: *gtk::Window, data: *void) void,
-	// 	data: nullable *void,
+	// 	handler: *fn(instance: *gtk::Window, data: *opaque) void,
+	// 	data: nullable *opaque,
 	// ) u64 = gobject::signal_connect_data(
 	// 	instance,
 	// 	*(&"activate\0": []u8): *[*]u8: *c::char,
 	// 	handler: gobject::Callback,
-	// 	data: *void,
+	// 	data: *opaque,
 	// 	null: gobject::ClosureNotify, 0,
 	// );
 
@@ -434,10 +434,10 @@ fn emit_signal(ctx: *context, signal: *gir::signal) (void | io::error) = {
 		fmt::fprint(ctx.current.output, ", ")?;
 		emit_params(ctx, signal.params)?;
 	};
-	fmt::fprint(ctx.current.output, ", data: *void) ")?;
+	fmt::fprint(ctx.current.output, ", data: *opaque) ")?;
 	emit_return_value(ctx, signal.return_value)?;
 	fmt::fprintln(ctx.current.output, ",")?;
-	fmt::fprintln(ctx.current.output, "\t" "data: nullable *void,")?;
+	fmt::fprintln(ctx.current.output, "\t" "data: nullable *opaque,")?;
 	fmt::fprint(ctx.current.output, ") u64 = ")?;
 	emit_object(ctx, ctx.gobject, "signal_connect_data")?;
 	fmt::fprintln(ctx.current.output, "(")?;
@@ -449,7 +449,7 @@ fn emit_signal(ctx: *context, signal: *gir::signal) (void | io::error) = {
 	fmt::fprint(ctx.current.output,    "\t" "handler: ")?;
 	emit_object(ctx, ctx.gobject, "Callback")?;
 	fmt::fprintln(ctx.current.output, ",")?;
-	fmt::fprintln(ctx.current.output,  "\t" "data: *void,")?;
+	fmt::fprintln(ctx.current.output,  "\t" "data: *opaque,")?;
 	fmt::fprint(ctx.current.output,    "\t" "null: ")?;
 	emit_object(ctx, ctx.gobject, "ClosureNotify")?;
 	fmt::fprintln(ctx.current.output, ", 0,")?;
@@ -584,13 +584,17 @@ fn emit_doc(ctx: *context, item: *gir::documentation) (void | io::error) = {
 	};
 };
 
-fn emit_type(ctx: *context, t: (gir::any_type | gir::callback)) (void | io::error) = {
+type ctype_flag = enum {
+	VOID_IS_OPAQUE,
+};
+
+fn emit_type(ctx: *context, t: (gir::any_type | gir::callback), flags: ctype_flag...) (void | io::error) = {
 	match (t) {
 	case let t: gir::simple_type =>
 		if (len(t.c_type) > 0) {
 			const parsed = parse_ctype(t.c_type);
 			defer ctype_finish(parsed);
-			return emit_c_type(ctx, parsed);
+			return emit_c_type(ctx, parsed, flags...);
 		} else {
 			const (first, second) = strings::cut(t.name, ".");
 			if (len(second) == 0) {
@@ -613,7 +617,7 @@ fn emit_type(ctx: *context, t: (gir::any_type | gir::callback)) (void | io::erro
 					};
 				case => void;
 				};
-				return emit_c_type(ctx, parsed);
+				return emit_c_type(ctx, parsed, flags...);
 			} else {
 				const ns = match (get_namespace(ctx, first)) {
 				case let ns: *namespace =>
@@ -665,7 +669,7 @@ fn emit_callback_type(ctx: *context, cb: *gir::callback) (void | io::error) = {
 	emit_return_value(ctx, cb.return_value)?;
 };
 
-fn emit_c_type(ctx: *context, type_: ctype) (void | io::error) = {
+fn emit_c_type(ctx: *context, type_: ctype, flags: ctype_flag...) (void | io::error) = {
 	match (type_) {
 	case let special: (cmodule, str) =>
 		const (mod, id) = special;
@@ -690,6 +694,10 @@ fn emit_c_type(ctx: *context, type_: ctype) (void | io::error) = {
 		if (cbuiltin_needs_import(b)) {
 			add_import(ctx.current, ["types", "c"]);
 		};
+		if (b == cbuiltin::VOID && len(flags) > 0) {
+			// there's only one flag - VOID_IS_OPAQUE
+			b = cbuiltin::OPAQUE;
+		};
 		fmt::fprint(ctx.current.output, cbuiltin_str(b))?;
 	case let p: cpointer =>
 		fmt::fprint(ctx.current.output, '*')?;
diff --git a/gir/parse.ha b/gir/parse.ha
index a484dc6..91c55d4 100644
--- a/gir/parse.ha
+++ b/gir/parse.ha
@@ -32,7 +32,7 @@ export fn parse(in: io::file) (repository | error) = {
 	return repo;
 };
 
-fn parse_repository(parser: *xml::parser, repo: *void) (void | error) = {
+fn parse_repository(parser: *xml::parser, repo: *opaque) (void | error) = {
 	const repo = repo: *repository;
 	return parse_element(parser, "repository",
 		("xmlns", null),
@@ -48,7 +48,7 @@ fn parse_repository(parser: *xml::parser, repo: *void) (void | error) = {
 	);
 };
 
-fn parse_include(parser: *xml::parser, includes: *void) (void | error) = {
+fn parse_include(parser: *xml::parser, includes: *opaque) (void | error) = {
 	const includes = includes: *[]include;
 	let new = include { ... };
 	parse_element(parser, "include",
@@ -58,7 +58,7 @@ fn parse_include(parser: *xml::parser, includes: *void) (void | error) = {
 	append(includes, new);
 };
 
-fn parse_namespace(parser: *xml::parser, namespaces: *void) (void | error) = {
+fn parse_namespace(parser: *xml::parser, namespaces: *opaque) (void | error) = {
 	const namespaces = namespaces: *[]namespace;
 	let new = namespace { ... };
 	parse_element(parser, "namespace",
@@ -88,7 +88,7 @@ fn parse_namespace(parser: *xml::parser, namespaces: *void) (void | error) = {
 	append(namespaces, new);
 };
 
-fn parse_alias(parser: *xml::parser, aliases: *void) (void | error) = {
+fn parse_alias(parser: *xml::parser, aliases: *opaque) (void | error) = {
 	const aliases = aliases: *[]alias;
 	let new = alias { ... };
 	parse_element(parser, "alias",
@@ -100,7 +100,7 @@ fn parse_alias(parser: *xml::parser, aliases: *void) (void | error) = {
 	append(aliases, new);
 };
 
-fn parse_class(parser: *xml::parser, classes: *void) (void | error) = {
+fn parse_class(parser: *xml::parser, classes: *opaque) (void | error) = {
 	const classes = classes: *[]class;
 	let new = class { ... };
 	parse_element(parser, "class",
@@ -135,7 +135,7 @@ fn parse_class(parser: *xml::parser, classes: *void) (void | error) = {
 	)?;
 	append(classes, new);
 };
-fn parse_implements(parser: *xml::parser, implements: *void) (void | error) = {
+fn parse_implements(parser: *xml::parser, implements: *opaque) (void | error) = {
 	const implements = implements: *[]str;
 	let name = "";
 	parse_element(parser, "implements",
@@ -143,7 +143,7 @@ fn parse_implements(parser: *xml::parser, implements: *void) (void | error) = {
 	)?;
 	append(implements, name);
 };
-fn parse_interface(parser: *xml::parser, interfaces: *void) (void | error) = {
+fn parse_interface(parser: *xml::parser, interfaces: *opaque) (void | error) = {
 	const interfaces = interfaces: *[]interface;
 	let new = interface { ... };
 	parse_element(parser, "interface",
@@ -169,7 +169,7 @@ fn parse_interface(parser: *xml::parser, interfaces: *void) (void | error) = {
 	)?;
 	append(interfaces, new);
 };
-fn parse_prerequisite(parser: *xml::parser, prerequisites: *void) (void | error) = {
+fn parse_prerequisite(parser: *xml::parser, prerequisites: *opaque) (void | error) = {
 	const prerequisites = prerequisites: *[]str;
 	let name = "";
 	parse_element(parser, "prerequisite",
@@ -178,7 +178,7 @@ fn parse_prerequisite(parser: *xml::parser, prerequisites: *void) (void | error)
 	append(prerequisites, name);
 };
 
-fn parse_record(parser: *xml::parser, records: *void) (void | error) = {
+fn parse_record(parser: *xml::parser, records: *opaque) (void | error) = {
 	const records = records: *[]record;
 	let new = record { ... };
 	parse_element(parser, "record",
@@ -186,7 +186,7 @@ fn parse_record(parser: *xml::parser, records: *void) (void | error) = {
 		("name", &new.name),
 		("c:type", &new.c_type),
 		("disguised", &new.disguised),
-		("opaque", &new.opaque),
+		("opaque", &new.opaque_),
 		("pointer", &new.pointer),
 		("glib:type-name", &new.glib_type_name),
 		("glib:get-type", &new.glib_get_type),
@@ -205,7 +205,7 @@ fn parse_record(parser: *xml::parser, records: *void) (void | error) = {
 	append(records, new);
 };
 
-fn parse_record_entry(parser: *xml::parser, entries: *void) (void | error) = {
+fn parse_record_entry(parser: *xml::parser, entries: *opaque) (void | error) = {
 	const entries = entries: *[]entry;
 	let records: []record = [];
 	defer free(records);
@@ -213,7 +213,7 @@ fn parse_record_entry(parser: *xml::parser, entries: *void) (void | error) = {
 	append(entries, records[0]);
 };
 
-fn parse_constructor(parser: *xml::parser, constructors: *void) (void | error) = {
+fn parse_constructor(parser: *xml::parser, constructors: *opaque) (void | error) = {
 	const constructors = constructors: *[]constructor;
 	let new = constructor { return_value = void, ... };
 	parse_element(parser, "constructor",
@@ -223,7 +223,7 @@ fn parse_constructor(parser: *xml::parser, constructors: *void) (void | error) =
 	)?;
 	append(constructors, new);
 };
-fn parse_method(parser: *xml::parser, methods: *void) (void | error) = {
+fn parse_method(parser: *xml::parser, methods: *opaque) (void | error) = {
 	const methods = methods: *[]method;
 	let new = method { return_value = void, ... };
 	parse_element(parser, "method",
@@ -236,7 +236,7 @@ fn parse_method(parser: *xml::parser, methods: *void) (void | error) = {
 	)?;
 	append(methods, new);
 };
-fn parse_virtual_method(parser: *xml::parser, vmethods: *void) (void | error) = {
+fn parse_virtual_method(parser: *xml::parser, vmethods: *opaque) (void | error) = {
 	const vmethods = vmethods: *[]virtual_method;
 	let new = virtual_method { return_value = void, ... };
 	parse_element(parser, "virtual-method",
@@ -248,7 +248,7 @@ fn parse_virtual_method(parser: *xml::parser, vmethods: *void) (void | error) =
 	)?;
 	append(vmethods, new);
 };
-fn parse_field(parser: *xml::parser, entries: *void) (void | error) = {
+fn parse_field(parser: *xml::parser, entries: *opaque) (void | error) = {
 	const entries = entries: *[]entry;
 	let new = field { type_ = simple_type { ... }, ... };
 	let type_: any_type = simple_type { ... };
@@ -271,7 +271,7 @@ fn parse_field(parser: *xml::parser, entries: *void) (void | error) = {
 	};
 	append(entries, new);
 };
-fn parse_property(parser: *xml::parser, properties: *void) (void | error) = {
+fn parse_property(parser: *xml::parser, properties: *opaque) (void | error) = {
 	const properties = properties: *[]property;
 	let new = property { type_ = simple_type { ... }, ... };
 	parse_element(parser, "property",
@@ -291,7 +291,7 @@ fn parse_property(parser: *xml::parser, properties: *void) (void | error) = {
 	append(properties, new);
 };
 
-fn parse_enumeration(parser: *xml::parser, enums: *void) (void | error) = {
+fn parse_enumeration(parser: *xml::parser, enums: *opaque) (void | error) = {
 	const enums = enums: *[]enumeration;
 	let new = enumeration { ... };
 	parse_element(parser, "enumeration",
@@ -308,7 +308,7 @@ fn parse_enumeration(parser: *xml::parser, enums: *void) (void | error) = {
 	append(enums, new);
 };
 
-fn parse_function(parser: *xml::parser, functions: *void) (void | error) = {
+fn parse_function(parser: *xml::parser, functions: *opaque) (void | error) = {
 	const functions = functions: *[]function;
 	let new = function { return_value = void, ... };
 	parse_element(parser, "function",
@@ -319,7 +319,7 @@ fn parse_function(parser: *xml::parser, functions: *void) (void | error) = {
 	append(functions, new);
 };
 
-fn parse_union(parser: *xml::parser, unions: *void) (void | error) = {
+fn parse_union(parser: *xml::parser, unions: *opaque) (void | error) = {
 	const unions = unions: *[]union_;
 	let new = union_ { ... };
 	parse_element(parser, "union",
@@ -341,7 +341,7 @@ fn parse_union(parser: *xml::parser, unions: *void) (void | error) = {
 	append(unions, new);
 };
 
-fn parse_union_entry(parser: *xml::parser, entries: *void) (void | error) = {
+fn parse_union_entry(parser: *xml::parser, entries: *opaque) (void | error) = {
 	const entries = entries: *[]entry;
 	let unions: []union_ = [];
 	defer free(unions);
@@ -349,7 +349,7 @@ fn parse_union_entry(parser: *xml::parser, entries: *void) (void | error) = {
 	append(entries, unions[0]);
 };
 
-fn parse_bitfield(parser: *xml::parser, bitfields: *void) (void | error) = {
+fn parse_bitfield(parser: *xml::parser, bitfields: *opaque) (void | error) = {
 	const bitfields = bitfields: *[]bitfield;
 	let new = bitfield { ... };
 	parse_element(parser, "bitfield",
@@ -365,13 +365,13 @@ fn parse_bitfield(parser: *xml::parser, bitfields: *void) (void | error) = {
 	append(bitfields, new);
 };
 
-fn parse_callback(parser: *xml::parser, callbacks: *void) (void | error) = {
+fn parse_callback(parser: *xml::parser, callbacks: *opaque) (void | error) = {
 	const callbacks = callbacks: *[]callback;
 	let new = callback { return_value = void, ... };
 	parse_one_callback(parser, &new)?;
 	append(callbacks, new);
 };
-fn parse_one_callback(parser: *xml::parser, cb: *void) (void | error) = {
+fn parse_one_callback(parser: *xml::parser, cb: *opaque) (void | error) = {
 	const cb = cb: *callback;
 	return parse_element(parser, "callback",
 		parse_info(cb),
@@ -384,7 +384,7 @@ fn parse_one_callback(parser: *xml::parser, cb: *void) (void | error) = {
 	);
 };
 
-fn parse_constant(parser: *xml::parser, constants: *void) (void | error) = {
+fn parse_constant(parser: *xml::parser, constants: *opaque) (void | error) = {
 	const constants = constants: *[]constant;
 	let new = constant { type_ = void, ... };
 	let type_: any_type = simple_type { ... };
@@ -404,7 +404,7 @@ fn parse_constant(parser: *xml::parser, constants: *void) (void | error) = {
 	append(constants, new);
 };
 
-fn parse_signal(parser: *xml::parser, signals: *void) (void | error) = {
+fn parse_signal(parser: *xml::parser, signals: *opaque) (void | error) = {
 	const signals = signals: *[]signal;
 	let new = signal { return_value = void, ... };
 	parse_element(parser, "glib:signal",
@@ -424,7 +424,7 @@ fn parse_signal(parser: *xml::parser, signals: *void) (void | error) = {
 };
 
 // enum + bitfield
-fn parse_member(parser: *xml::parser, members: *void) (void | error) = {
+fn parse_member(parser: *xml::parser, members: *opaque) (void | error) = {
 	const members = members: *[]member;
 	let new = member { ... };
 	parse_element(parser, "member",
@@ -458,13 +458,13 @@ fn parse_callable(callable: *callable) [17]scan = [
 	("throws", &callable.throws),
 	("moved-to", null),
 ];
-fn parse_parameters(parser: *xml::parser, parameters: *void) (void | error) = {
+fn parse_parameters(parser: *xml::parser, parameters: *opaque) (void | error) = {
 	return parse_element(parser, "parameters",
 		("parameter", &parse_parameter, parameters),
 		("varargs", &parse_varargs, parameters),
 	);
 };
-fn parse_method_parameters(parser: *xml::parser, parameters: *void) (void | error) = {
+fn parse_method_parameters(parser: *xml::parser, parameters: *opaque) (void | error) = {
 	const parameters = parameters: *(*instance_parameter, *[]callable_param);
 	return parse_element(parser, "parameters",
 		("instance-parameter", &parse_instance_parameter, parameters.0),
@@ -472,7 +472,7 @@ fn parse_method_parameters(parser: *xml::parser, parameters: *void) (void | erro
 		("varargs", &parse_varargs, parameters.1),
 	);
 };
-fn parse_instance_parameter(parser: *xml::parser, param: *void) (void | error) = {
+fn parse_instance_parameter(parser: *xml::parser, param: *opaque) (void | error) = {
 	const param = param: *instance_parameter;
 	return parse_element(parser, "instance-parameter",
 		parse_info(param),
@@ -486,7 +486,7 @@ fn parse_instance_parameter(parser: *xml::parser, param: *void) (void | error) =
 		("type", &parse_simple_type, &param.type_),
 	);
 };
-fn parse_parameter(parser: *xml::parser, parameters: *void) (void | error) = {
+fn parse_parameter(parser: *xml::parser, parameters: *opaque) (void | error) = {
 	const parameters = parameters: *[]callable_param;
 	let new = callable_param { parameter = simple_type { ... }, ... };
 	let type_: any_type = simple_type { ... };
@@ -515,11 +515,11 @@ fn parse_parameter(parser: *xml::parser, parameters: *void) (void | error) = {
 	};
 	append(parameters, new);
 };
-fn parse_varargs(parser: *xml::parser, has_varargs: *void) (void | error) = {
+fn parse_varargs(parser: *xml::parser, has_varargs: *opaque) (void | error) = {
 	*(has_varargs: *bool) = true;
 	return parse_element(parser, "varargs");
 };
-fn parse_return_value(parser: *xml::parser, return_value: *void) (void | error) = {
+fn parse_return_value(parser: *xml::parser, return_value: *opaque) (void | error) = {
 	const return_value = return_value: *(callable_return | void);
 	let new = callable_return { type_ = simple_type { ... }, ... };
 	parse_element(parser, "return-value",
@@ -550,7 +550,7 @@ fn parse_info(doc: *documentation) [11]scan = [
 	("source-position", null, null),
 	("attribute", null, null),
 ];
-fn parse_doc(parser: *xml::parser, text: *void) (void | error) = {
+fn parse_doc(parser: *xml::parser, text: *opaque) (void | error) = {
 	const text = text: *str;
 	return parse_element(parser, "doc",
 		("xml:space", null),
@@ -563,7 +563,7 @@ fn parse_doc(parser: *xml::parser, text: *void) (void | error) = {
 };
 
 // types
-fn parse_simple_type(parser: *xml::parser, out: *void) (void | error) = {
+fn parse_simple_type(parser: *xml::parser, out: *opaque) (void | error) = {
 	const out = out: *simple_type;
 	return parse_element(parser, "type",
 		parse_info(out),
@@ -575,7 +575,7 @@ fn parse_simple_type(parser: *xml::parser, out: *void) (void | error) = {
 	);
 };
 
-fn parse_array_type(parser: *xml::parser, out: *void) (void | error) = {
+fn parse_array_type(parser: *xml::parser, out: *opaque) (void | error) = {
 	const out = out: *array_type;
 	let inner: any_type = simple_type { ... };
 	parse_element(parser, "array",
@@ -595,24 +595,24 @@ fn parse_any_type(out: *any_type) [2]scan = [
 	("type", &parse_simple_type_union, out),
 	("array", &parse_array_type_union, out),
 ];
-fn parse_simple_type_union(parser: *xml::parser, out: *void) (void | error) = {
+fn parse_simple_type_union(parser: *xml::parser, out: *opaque) (void | error) = {
 	const out = out: *any_type;
 	let simple = simple_type { ... };
 	parse_simple_type(parser, &simple)?;
 	*out = simple;
 };
-fn parse_array_type_union(parser: *xml::parser, out: *void) (void | error) = {
+fn parse_array_type_union(parser: *xml::parser, out: *opaque) (void | error) = {
 	const out = out: *any_type;
 	let array = array_type { inner = null: *any_type, ... };
 	parse_array_type(parser, &array)?;
 	*out = array;
 };
 
-type parse_func = nullable *fn(parser: *xml::parser, data: *void) (void | error);
+type parse_func = nullable *fn(parser: *xml::parser, data: *opaque) (void | error);
 type scan_element = (
 	str,
 	parse_func,
-	nullable *void,
+	nullable *opaque,
 );
 type scan_attribute = (
 	str,
@@ -662,8 +662,8 @@ fn parse_element(
 			const (name, func, data) = elements[i];
 			if (start == name) {
 				match (func) {
-				case let func: *fn(*xml::parser, *void) (void | error) =>
-					func(parser, data: *void)?;
+				case let func: *fn(*xml::parser, *opaque) (void | error) =>
+					func(parser, data: *opaque)?;
 				case null =>
 					ignore(parser, name)?;
 				};
diff --git a/gir/types.ha b/gir/types.ha
index 6616d69..f0f8355 100644
--- a/gir/types.ha
+++ b/gir/types.ha
@@ -108,7 +108,7 @@ export type record = struct {
 	name: str,
 	c_type: str,
 	disguised: bool,
-	opaque: bool,
+	opaque_: bool,
 	pointer: bool,
 	glib_type_name: str,
 	glib_get_type: str,