mirror of
https://github.com/ziglang/zig.git
synced 2024-11-23 12:50:13 +00:00
translate-c: better typename parsing
This commit is contained in:
parent
46b9e061e0
commit
aa83cbb697
@ -280,6 +280,8 @@ pub const Context = struct {
|
|||||||
opaque_demotes: std.AutoHashMapUnmanaged(usize, void) = .{},
|
opaque_demotes: std.AutoHashMapUnmanaged(usize, void) = .{},
|
||||||
/// Table of unnamed enums and records that are child types of typedefs.
|
/// Table of unnamed enums and records that are child types of typedefs.
|
||||||
unnamed_typedefs: std.AutoHashMapUnmanaged(usize, []const u8) = .{},
|
unnamed_typedefs: std.AutoHashMapUnmanaged(usize, []const u8) = .{},
|
||||||
|
/// Needed to decide if we are parsing a typename
|
||||||
|
typedefs: std.StringArrayHashMapUnmanaged(void) = .{},
|
||||||
|
|
||||||
/// This one is different than the root scope's name table. This contains
|
/// This one is different than the root scope's name table. This contains
|
||||||
/// a list of names that we found by visiting all the top level decls without
|
/// a list of names that we found by visiting all the top level decls without
|
||||||
@ -348,6 +350,7 @@ pub fn translate(
|
|||||||
context.global_names.deinit(gpa);
|
context.global_names.deinit(gpa);
|
||||||
context.opaque_demotes.deinit(gpa);
|
context.opaque_demotes.deinit(gpa);
|
||||||
context.unnamed_typedefs.deinit(gpa);
|
context.unnamed_typedefs.deinit(gpa);
|
||||||
|
context.typedefs.deinit(gpa);
|
||||||
context.global_scope.deinit();
|
context.global_scope.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,6 +464,7 @@ fn declVisitorNamesOnly(c: *Context, decl: *const clang.Decl) Error!void {
|
|||||||
result.value_ptr.* = name;
|
result.value_ptr.* = name;
|
||||||
// Put this typedef in the decl_table to avoid redefinitions.
|
// Put this typedef in the decl_table to avoid redefinitions.
|
||||||
try c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), name);
|
try c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), name);
|
||||||
|
try c.typedefs.put(c.gpa, name, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -792,6 +796,8 @@ fn transTypeDef(c: *Context, scope: *Scope, typedef_decl: *const clang.TypedefNa
|
|||||||
// TODO https://github.com/ziglang/zig/issues/3756
|
// TODO https://github.com/ziglang/zig/issues/3756
|
||||||
// TODO https://github.com/ziglang/zig/issues/1802
|
// TODO https://github.com/ziglang/zig/issues/1802
|
||||||
var name: []const u8 = if (isZigPrimitiveType(bare_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ bare_name, c.getMangle() }) else bare_name;
|
var name: []const u8 = if (isZigPrimitiveType(bare_name)) try std.fmt.allocPrint(c.arena, "{s}_{d}", .{ bare_name, c.getMangle() }) else bare_name;
|
||||||
|
try c.typedefs.put(c.gpa, name, {});
|
||||||
|
|
||||||
if (builtin_typedef_map.get(name)) |builtin| {
|
if (builtin_typedef_map.get(name)) |builtin| {
|
||||||
return c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
|
return c.decl_table.putNoClobber(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin);
|
||||||
}
|
}
|
||||||
@ -5303,56 +5309,6 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
|
|||||||
.IntegerLiteral, .FloatLiteral => {
|
.IntegerLiteral, .FloatLiteral => {
|
||||||
return parseCNumLit(c, m);
|
return parseCNumLit(c, m);
|
||||||
},
|
},
|
||||||
// eventually this will be replaced by std.c.parse which will handle these correctly
|
|
||||||
.Keyword_void => return Tag.type.create(c.arena, "c_void"),
|
|
||||||
.Keyword_bool => return Tag.type.create(c.arena, "bool"),
|
|
||||||
.Keyword_double => return Tag.type.create(c.arena, "f64"),
|
|
||||||
.Keyword_long => return Tag.type.create(c.arena, "c_long"),
|
|
||||||
.Keyword_int => return Tag.type.create(c.arena, "c_int"),
|
|
||||||
.Keyword_float => return Tag.type.create(c.arena, "f32"),
|
|
||||||
.Keyword_short => return Tag.type.create(c.arena, "c_short"),
|
|
||||||
.Keyword_char => return Tag.type.create(c.arena, "u8"),
|
|
||||||
.Keyword_unsigned => if (m.next()) |t| switch (t) {
|
|
||||||
.Keyword_char => return Tag.type.create(c.arena, "u8"),
|
|
||||||
.Keyword_short => return Tag.type.create(c.arena, "c_ushort"),
|
|
||||||
.Keyword_int => return Tag.type.create(c.arena, "c_uint"),
|
|
||||||
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
|
|
||||||
_ = m.next();
|
|
||||||
return Tag.type.create(c.arena, "c_ulonglong");
|
|
||||||
} else return Tag.type.create(c.arena, "c_ulong"),
|
|
||||||
else => {
|
|
||||||
m.i -= 1;
|
|
||||||
return Tag.type.create(c.arena, "c_uint");
|
|
||||||
},
|
|
||||||
} else {
|
|
||||||
return Tag.type.create(c.arena, "c_uint");
|
|
||||||
},
|
|
||||||
.Keyword_signed => if (m.next()) |t| switch (t) {
|
|
||||||
.Keyword_char => return Tag.type.create(c.arena, "i8"),
|
|
||||||
.Keyword_short => return Tag.type.create(c.arena, "c_short"),
|
|
||||||
.Keyword_int => return Tag.type.create(c.arena, "c_int"),
|
|
||||||
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
|
|
||||||
_ = m.next();
|
|
||||||
return Tag.type.create(c.arena, "c_longlong");
|
|
||||||
} else return Tag.type.create(c.arena, "c_long"),
|
|
||||||
else => {
|
|
||||||
m.i -= 1;
|
|
||||||
return Tag.type.create(c.arena, "c_int");
|
|
||||||
},
|
|
||||||
} else {
|
|
||||||
return Tag.type.create(c.arena, "c_int");
|
|
||||||
},
|
|
||||||
.Keyword_enum, .Keyword_struct, .Keyword_union => {
|
|
||||||
// struct Foo will be declared as struct_Foo by transRecordDecl
|
|
||||||
const next_id = m.next().?;
|
|
||||||
if (next_id != .Identifier) {
|
|
||||||
try m.fail(c, "unable to translate C expr: expected Identifier instead got: {s}", .{@tagName(next_id)});
|
|
||||||
return error.ParseError;
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
|
|
||||||
return Tag.identifier.create(c.arena, name);
|
|
||||||
},
|
|
||||||
.Identifier => {
|
.Identifier => {
|
||||||
const mangled_name = scope.getAlias(slice);
|
const mangled_name = scope.getAlias(slice);
|
||||||
if (mem.startsWith(u8, mangled_name, "__builtin_") and !isBuiltinDefined(mangled_name)) {
|
if (mem.startsWith(u8, mangled_name, "__builtin_") and !isBuiltinDefined(mangled_name)) {
|
||||||
@ -5369,37 +5325,15 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
|
|||||||
try m.fail(c, "unable to translate C expr: expected ')' instead got: {s}", .{@tagName(next_id)});
|
try m.fail(c, "unable to translate C expr: expected ')' instead got: {s}", .{@tagName(next_id)});
|
||||||
return error.ParseError;
|
return error.ParseError;
|
||||||
}
|
}
|
||||||
var saw_l_paren = false;
|
return inner_node;
|
||||||
var saw_integer_literal = false;
|
|
||||||
switch (m.peek().?) {
|
|
||||||
// (type)(to_cast)
|
|
||||||
.LParen => {
|
|
||||||
saw_l_paren = true;
|
|
||||||
_ = m.next();
|
|
||||||
},
|
|
||||||
// (type)sizeof(x)
|
|
||||||
.Keyword_sizeof,
|
|
||||||
// (type)alignof(x)
|
|
||||||
.Keyword_alignof,
|
|
||||||
// (type)identifier
|
|
||||||
.Identifier,
|
|
||||||
=> {},
|
|
||||||
// (type)integer
|
|
||||||
.IntegerLiteral => {
|
|
||||||
saw_integer_literal = true;
|
|
||||||
},
|
|
||||||
else => return inner_node,
|
|
||||||
}
|
|
||||||
const node_to_cast = try parseCExpr(c, m, scope);
|
|
||||||
|
|
||||||
if (saw_l_paren and m.next().? != .RParen) {
|
|
||||||
try m.fail(c, "unable to translate C expr: expected ')'", .{});
|
|
||||||
return error.ParseError;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Tag.std_meta_cast.create(c.arena, .{ .lhs = inner_node, .rhs = node_to_cast });
|
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
// for handling type macros (EVIL)
|
||||||
|
// TODO maybe detect and treat type macros as typedefs in parseCSpecifierQualifierList?
|
||||||
|
m.i -= 1;
|
||||||
|
if (try parseCTypeName(c, m, scope)) |type_name| {
|
||||||
|
return type_name;
|
||||||
|
}
|
||||||
try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});
|
try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});
|
||||||
return error.ParseError;
|
return error.ParseError;
|
||||||
},
|
},
|
||||||
@ -5605,7 +5539,7 @@ fn parseCAddSubExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
||||||
var node = try parseCUnaryExpr(c, m, scope);
|
var node = try parseCCastExpr(c, m, scope);
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (m.next().?) {
|
switch (m.next().?) {
|
||||||
.Asterisk => {
|
.Asterisk => {
|
||||||
@ -5633,18 +5567,18 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
|||||||
} else {
|
} else {
|
||||||
// expr * expr
|
// expr * expr
|
||||||
const lhs = try macroBoolToInt(c, node);
|
const lhs = try macroBoolToInt(c, node);
|
||||||
const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
|
const rhs = try macroBoolToInt(c, try parseCCastExpr(c, m, scope));
|
||||||
node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
node = try Tag.mul.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Slash => {
|
.Slash => {
|
||||||
const lhs = try macroBoolToInt(c, node);
|
const lhs = try macroBoolToInt(c, node);
|
||||||
const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
|
const rhs = try macroBoolToInt(c, try parseCCastExpr(c, m, scope));
|
||||||
node = try Tag.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
node = try Tag.div.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
||||||
},
|
},
|
||||||
.Percent => {
|
.Percent => {
|
||||||
const lhs = try macroBoolToInt(c, node);
|
const lhs = try macroBoolToInt(c, node);
|
||||||
const rhs = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
|
const rhs = try macroBoolToInt(c, try parseCCastExpr(c, m, scope));
|
||||||
node = try Tag.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
node = try Tag.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs });
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
@ -5655,8 +5589,133 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
||||||
var node = try parseCPrimaryExpr(c, m, scope);
|
switch (m.next().?) {
|
||||||
|
.LParen => {
|
||||||
|
if (try parseCTypeName(c, m, scope)) |type_name| {
|
||||||
|
if (m.next().? != .RParen) {
|
||||||
|
try m.fail(c, "unable to translate C expr: expected ')'", .{});
|
||||||
|
return error.ParseError;
|
||||||
|
}
|
||||||
|
if (m.peek().? == .LBrace) {
|
||||||
|
// initializer list
|
||||||
|
return parseCPostfixExpr(c, m, scope, type_name);
|
||||||
|
}
|
||||||
|
const node_to_cast = try parseCCastExpr(c, m, scope);
|
||||||
|
return Tag.std_meta_cast.create(c.arena, .{ .lhs = type_name, .rhs = node_to_cast });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
m.i -= 1;
|
||||||
|
return parseCUnaryExpr(c, m, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseCTypeName(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!?Node {
|
||||||
|
if (try parseCSpecifierQualifierList(c, m, scope)) |node| {
|
||||||
|
return try parseCAbstractDeclarator(c, m, scope, node);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!?Node {
|
||||||
|
switch (m.next().?) {
|
||||||
|
.Identifier => {
|
||||||
|
const mangled_name = scope.getAlias(m.slice());
|
||||||
|
if (c.typedefs.contains(mangled_name)) {
|
||||||
|
return try Tag.identifier.create(c.arena, builtin_typedef_map.get(mangled_name) orelse mangled_name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// eventually this will be replaced by std.c.parse which will handle these correctly
|
||||||
|
.Keyword_void => return try Tag.type.create(c.arena, "c_void"),
|
||||||
|
.Keyword_bool => return try Tag.type.create(c.arena, "bool"),
|
||||||
|
.Keyword_double => return try Tag.type.create(c.arena, "f64"),
|
||||||
|
.Keyword_long => return try Tag.type.create(c.arena, "c_long"),
|
||||||
|
.Keyword_int => return try Tag.type.create(c.arena, "c_int"),
|
||||||
|
.Keyword_float => return try Tag.type.create(c.arena, "f32"),
|
||||||
|
.Keyword_short => return try Tag.type.create(c.arena, "c_short"),
|
||||||
|
.Keyword_char => return try Tag.type.create(c.arena, "u8"),
|
||||||
|
.Keyword_unsigned => if (m.next()) |t| switch (t) {
|
||||||
|
.Keyword_char => return try Tag.type.create(c.arena, "u8"),
|
||||||
|
.Keyword_short => return try Tag.type.create(c.arena, "c_ushort"),
|
||||||
|
.Keyword_int => return try Tag.type.create(c.arena, "c_uint"),
|
||||||
|
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
|
||||||
|
_ = m.next();
|
||||||
|
return try Tag.type.create(c.arena, "c_ulonglong");
|
||||||
|
} else return try Tag.type.create(c.arena, "c_ulong"),
|
||||||
|
else => {
|
||||||
|
m.i -= 1;
|
||||||
|
return try Tag.type.create(c.arena, "c_uint");
|
||||||
|
},
|
||||||
|
} else {
|
||||||
|
return try Tag.type.create(c.arena, "c_uint");
|
||||||
|
},
|
||||||
|
.Keyword_signed => if (m.next()) |t| switch (t) {
|
||||||
|
.Keyword_char => return try Tag.type.create(c.arena, "i8"),
|
||||||
|
.Keyword_short => return try Tag.type.create(c.arena, "c_short"),
|
||||||
|
.Keyword_int => return try Tag.type.create(c.arena, "c_int"),
|
||||||
|
.Keyword_long => if (m.peek() != null and m.peek().? == .Keyword_long) {
|
||||||
|
_ = m.next();
|
||||||
|
return try Tag.type.create(c.arena, "c_longlong");
|
||||||
|
} else return try Tag.type.create(c.arena, "c_long"),
|
||||||
|
else => {
|
||||||
|
m.i -= 1;
|
||||||
|
return try Tag.type.create(c.arena, "c_int");
|
||||||
|
},
|
||||||
|
} else {
|
||||||
|
return try Tag.type.create(c.arena, "c_int");
|
||||||
|
},
|
||||||
|
.Keyword_enum, .Keyword_struct, .Keyword_union => {
|
||||||
|
// struct Foo will be declared as struct_Foo by transRecordDecl
|
||||||
|
const slice = m.slice();
|
||||||
|
const next_id = m.next().?;
|
||||||
|
if (next_id != .Identifier) {
|
||||||
|
try m.fail(c, "unable to translate C expr: expected Identifier instead got: {s}", .{@tagName(next_id)});
|
||||||
|
return error.ParseError;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
|
||||||
|
return try Tag.identifier.create(c.arena, name);
|
||||||
|
},
|
||||||
|
.Keyword_complex => {}, // TODO
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
m.i -= 1;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, scope: *Scope, node: Node) ParseError!Node {
|
||||||
|
switch (m.next().?) {
|
||||||
|
.Asterisk => {
|
||||||
|
// last token of `node`
|
||||||
|
const prev_id = m.list[m.i - 1].id;
|
||||||
|
|
||||||
|
if (prev_id == .Keyword_void) {
|
||||||
|
const ptr = try Tag.single_pointer.create(c.arena, .{
|
||||||
|
.is_const = false,
|
||||||
|
.is_volatile = false,
|
||||||
|
.elem_type = node,
|
||||||
|
});
|
||||||
|
return Tag.optional_type.create(c.arena, ptr);
|
||||||
|
} else {
|
||||||
|
return Tag.c_pointer.create(c.arena, .{
|
||||||
|
.is_const = false,
|
||||||
|
.is_volatile = false,
|
||||||
|
.elem_type = node,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
m.i -= 1;
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node) ParseError!Node {
|
||||||
|
var node = type_name orelse try parseCPrimaryExpr(c, m, scope);
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (m.next().?) {
|
switch (m.next().?) {
|
||||||
.Period => {
|
.Period => {
|
||||||
@ -5776,24 +5835,24 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
|||||||
fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
||||||
switch (m.next().?) {
|
switch (m.next().?) {
|
||||||
.Bang => {
|
.Bang => {
|
||||||
const operand = try macroIntToBool(c, try parseCUnaryExpr(c, m, scope));
|
const operand = try macroIntToBool(c, try parseCCastExpr(c, m, scope));
|
||||||
return Tag.not.create(c.arena, operand);
|
return Tag.not.create(c.arena, operand);
|
||||||
},
|
},
|
||||||
.Minus => {
|
.Minus => {
|
||||||
const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
|
const operand = try macroBoolToInt(c, try parseCCastExpr(c, m, scope));
|
||||||
return Tag.negate.create(c.arena, operand);
|
return Tag.negate.create(c.arena, operand);
|
||||||
},
|
},
|
||||||
.Plus => return try parseCUnaryExpr(c, m, scope),
|
.Plus => return try parseCCastExpr(c, m, scope),
|
||||||
.Tilde => {
|
.Tilde => {
|
||||||
const operand = try macroBoolToInt(c, try parseCUnaryExpr(c, m, scope));
|
const operand = try macroBoolToInt(c, try parseCCastExpr(c, m, scope));
|
||||||
return Tag.bit_not.create(c.arena, operand);
|
return Tag.bit_not.create(c.arena, operand);
|
||||||
},
|
},
|
||||||
.Asterisk => {
|
.Asterisk => {
|
||||||
const operand = try parseCUnaryExpr(c, m, scope);
|
const operand = try parseCCastExpr(c, m, scope);
|
||||||
return Tag.deref.create(c.arena, operand);
|
return Tag.deref.create(c.arena, operand);
|
||||||
},
|
},
|
||||||
.Ampersand => {
|
.Ampersand => {
|
||||||
const operand = try parseCUnaryExpr(c, m, scope);
|
const operand = try parseCCastExpr(c, m, scope);
|
||||||
return Tag.address_of.create(c.arena, operand);
|
return Tag.address_of.create(c.arena, operand);
|
||||||
},
|
},
|
||||||
.Keyword_sizeof => {
|
.Keyword_sizeof => {
|
||||||
@ -5834,7 +5893,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
|||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
m.i -= 1;
|
m.i -= 1;
|
||||||
return try parseCPostfixExpr(c, m, scope);
|
return try parseCPostfixExpr(c, m, scope, null);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cases.add("use cast param as macro fn return type",
|
cases.add("use cast param as macro fn return type",
|
||||||
\\#define MEM_PHYSICAL_TO_K0(x) (void*)((u32)(x) + SYS_BASE_CACHED)
|
\\#include <stdint.h>
|
||||||
|
\\#define MEM_PHYSICAL_TO_K0(x) (void*)((uint32_t)(x) + SYS_BASE_CACHED)
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
\\pub inline fn MEM_PHYSICAL_TO_K0(x: anytype) ?*c_void {
|
\\pub inline fn MEM_PHYSICAL_TO_K0(x: anytype) ?*c_void {
|
||||||
\\ return @import("std").meta.cast(?*c_void, @import("std").meta.cast(u32, x) + SYS_BASE_CACHED);
|
\\ return @import("std").meta.cast(?*c_void, @import("std").meta.cast(u32, x) + SYS_BASE_CACHED);
|
||||||
@ -1878,6 +1879,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cases.add("macro pointer cast",
|
cases.add("macro pointer cast",
|
||||||
|
\\typedef struct { int dummy; } NRF_GPIO_Type;
|
||||||
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
|
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
|
||||||
, &[_][]const u8{
|
, &[_][]const u8{
|
||||||
\\pub const NRF_GPIO = @import("std").meta.cast([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
|
\\pub const NRF_GPIO = @import("std").meta.cast([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
|
||||||
@ -3175,6 +3177,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cases.add("macro cast",
|
cases.add("macro cast",
|
||||||
|
\\#include <stdint.h>
|
||||||
\\#define FOO(bar) baz((void *)(baz))
|
\\#define FOO(bar) baz((void *)(baz))
|
||||||
\\#define BAR (void*) a
|
\\#define BAR (void*) a
|
||||||
\\#define BAZ (uint32_t)(2)
|
\\#define BAZ (uint32_t)(2)
|
||||||
@ -3633,4 +3636,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
|||||||
\\ return foo.static.x;
|
\\ return foo.static.x;
|
||||||
\\}
|
\\}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cases.add("macro with nontrivial cast",
|
||||||
|
\\#define MAP_FAILED ((void *) -1)
|
||||||
|
\\typedef long long LONG_PTR;
|
||||||
|
\\#define INVALID_HANDLE_VALUE ((void *)(LONG_PTR)-1)
|
||||||
|
, &[_][]const u8{
|
||||||
|
\\pub const MAP_FAILED = @import("std").meta.cast(?*c_void, -@as(c_int, 1));
|
||||||
|
\\pub const INVALID_HANDLE_VALUE = @import("std").meta.cast(?*c_void, @import("std").meta.cast(LONG_PTR, -@as(c_int, 1)));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user