Merge branch 'hryx-translate-c-userland'

master
Andrew Kelley 2019-07-16 00:01:31 -04:00
commit 5345044edf
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
7 changed files with 1224 additions and 45 deletions

View File

@ -1,4 +1,5 @@
pub const struct_ZigClangAPValue = @OpaqueType();
const builtin = @import("builtin");
pub const struct_ZigClangAPSInt = @OpaqueType();
pub const struct_ZigClangAPFloat = @OpaqueType();
pub const struct_ZigClangASTContext = @OpaqueType();
@ -723,6 +724,7 @@ pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: str
pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass;
pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType;
pub extern fn ZigClangQualType_addConst(self: [*c]struct_ZigClangQualType) void;
pub extern fn ZigClangQualType_eq(self: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool;
@ -730,6 +732,7 @@ pub extern fn ZigClangQualType_isConstQualified(self: struct_ZigClangQualType) b
pub extern fn ZigClangQualType_isVolatileQualified(self: struct_ZigClangQualType) bool;
pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType) bool;
pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
@ -894,3 +897,77 @@ pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangS
pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
pub const ZigClangDeclStmt_const_decl_iterator = [*c]const *struct_ZigClangDecl;
pub extern fn ZigClangDeclStmt_decl_begin(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
pub extern fn ZigClangDeclStmt_decl_end(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
pub extern fn ZigClangVarDecl_getType(self: ?*const struct_ZigClangVarDecl) struct_ZigClangQualType;
pub extern fn ZigClangVarDecl_getInit(*const ZigClangVarDecl) ?*const ZigClangExpr;
pub extern fn ZigClangVarDecl_getTLSKind(self: ?*const struct_ZigClangVarDecl) ZigClangVarDecl_TLSKind;
pub const ZigClangVarDecl_TLSKind = extern enum {
None,
Static,
Dynamic,
};
pub extern fn ZigClangImplicitCastExpr_getBeginLoc(*const ZigClangImplicitCastExpr) ZigClangSourceLocation;
pub extern fn ZigClangImplicitCastExpr_getCastKind(*const ZigClangImplicitCastExpr) ZigClangCK;
pub extern fn ZigClangImplicitCastExpr_getSubExpr(*const ZigClangImplicitCastExpr) *const ZigClangExpr;
pub extern fn ZigClangArrayType_getElementType(*const ZigClangArrayType) ZigClangQualType;
pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl;
pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) ZigClangQualType;
pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType;
pub extern fn ZigClangCStyleCastExpr_getBeginLoc(*const ZigClangCStyleCastExpr) ZigClangSourceLocation;
pub extern fn ZigClangCStyleCastExpr_getSubExpr(*const ZigClangCStyleCastExpr) *const ZigClangExpr;
pub extern fn ZigClangCStyleCastExpr_getType(*const ZigClangCStyleCastExpr) ZigClangQualType;
pub const ZigClangExprEvalResult = struct_ZigClangExprEvalResult;
pub const struct_ZigClangExprEvalResult = extern struct {
HasSideEffects: bool,
HasUndefinedBehavior: bool,
SmallVectorImpl: ?*c_void,
Val: ZigClangAPValue,
};
pub const struct_ZigClangAPValue = extern struct {
Kind: ZigClangAPValue_ValueKind,
Data: if (builtin.os == .windows) [52]u8 else [68]u8,
};
pub const ZigClangAPValue_ValueKind = extern enum {
ZigClangAPValue_ValueKind_Uninitialized,
ZigClangAPValue_ValueKind_Int,
ZigClangAPValue_ValueKind_Float,
ZigClangAPValue_ValueKind_ComplexInt,
ZigClangAPValue_ValueKind_ComplexFloat,
ZigClangAPValue_ValueKind_LValue,
ZigClangAPValue_ValueKind_Vector,
ZigClangAPValue_ValueKind_Array,
ZigClangAPValue_ValueKind_Struct,
ZigClangAPValue_ValueKind_Union,
ZigClangAPValue_ValueKind_MemberPointer,
ZigClangAPValue_ValueKind_AddrLabelDiff,
};
pub extern fn ZigClangIntegerLiteral_EvaluateAsInt(*const ZigClangIntegerLiteral, *ZigClangExprEvalResult, *const ZigClangASTContext) bool;
pub extern fn ZigClangIntegerLiteral_getBeginLoc(*const ZigClangIntegerLiteral) ZigClangSourceLocation;
pub extern fn ZigClangReturnStmt_getRetValue(*const ZigClangReturnStmt) ?*const ZigClangExpr;
pub extern fn ZigClangBinaryOperator_getOpcode(*const ZigClangBinaryOperator) ZigClangBO;
pub extern fn ZigClangBinaryOperator_getBeginLoc(*const ZigClangBinaryOperator) ZigClangSourceLocation;
pub extern fn ZigClangBinaryOperator_getLHS(*const ZigClangBinaryOperator) *const ZigClangExpr;
pub extern fn ZigClangBinaryOperator_getRHS(*const ZigClangBinaryOperator) *const ZigClangExpr;
pub extern fn ZigClangBinaryOperator_getType(*const ZigClangBinaryOperator) ZigClangQualType;
pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigClangStringLiteral_StringKind;
pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;

View File

@ -20,7 +20,7 @@ pub const ClangErrMsg = Stage2ErrorMsg;
pub const Error = error{OutOfMemory};
const TypeError = Error || error{UnsupportedType};
const TransError = Error || error{UnsupportedTranslation};
const TransError = TypeError || error{UnsupportedTranslation};
const DeclTable = std.HashMap(usize, void, addrHash, addrEql);
@ -107,6 +107,8 @@ const Context = struct {
decl_table: DeclTable,
global_scope: *Scope.Root,
mode: Mode,
ptr_params: std.BufSet,
clang_context: *ZigClangASTContext,
fn a(c: *Context) *std.mem.Allocator {
return &c.tree.arena_allocator.allocator;
@ -183,6 +185,8 @@ pub fn translate(
.decl_table = DeclTable.init(arena),
.global_scope = try arena.create(Scope.Root),
.mode = mode,
.ptr_params = std.BufSet.init(arena),
.clang_context = ZigClangASTUnit_getASTContext(ast_unit).?,
};
context.global_scope.* = Scope.Root{
.base = Scope{
@ -195,7 +199,7 @@ pub fn translate(
return context.err;
}
_ = try appendToken(&context, .Eof, "");
tree.root_node.eof_token = try appendToken(&context, .Eof, "");
tree.source = source_buffer.toOwnedSlice();
if (false) {
std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);
@ -257,7 +261,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
.storage_class = storage_class,
.scope = &scope,
.is_export = switch (storage_class) {
.None => has_body,
.None => has_body and c.mode != .import,
.Extern, .Static => false,
.PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern"),
.Auto => unreachable, // Not legal on functions
@ -267,7 +271,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
.FunctionProto => blk: {
const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
error.UnsupportedType => {
return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
},
@ -276,7 +280,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
},
.FunctionNoProto => blk: {
const fn_no_proto_type = @ptrCast(*const ZigClangFunctionType, fn_type);
break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
error.UnsupportedType => {
return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
},
@ -295,7 +299,9 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
error.UnsupportedTranslation => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
error.UnsupportedTranslation,
error.UnsupportedType,
=> return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
};
assert(result.node.id == ast.Node.Id.Block);
proto_node.body_node = result.node;
@ -322,7 +328,15 @@ fn transStmt(
) !TransResult {
const sc = ZigClangStmt_getStmtClass(stmt);
switch (sc) {
.BinaryOperatorClass => return transBinaryOperator(rp, scope, @ptrCast(*const ZigClangBinaryOperator, stmt), result_used),
.CompoundStmtClass => return transCompoundStmt(rp, scope, @ptrCast(*const ZigClangCompoundStmt, stmt)),
.CStyleCastExprClass => return transCStyleCastExprClass(rp, scope, @ptrCast(*const ZigClangCStyleCastExpr, stmt), result_used, lrvalue),
.DeclStmtClass => return transDeclStmt(rp, scope, @ptrCast(*const ZigClangDeclStmt, stmt)),
.DeclRefExprClass => return transDeclRefExpr(rp, scope, @ptrCast(*const ZigClangDeclRefExpr, stmt), lrvalue),
.ImplicitCastExprClass => return transImplicitCastExpr(rp, scope, @ptrCast(*const ZigClangImplicitCastExpr, stmt), result_used),
.IntegerLiteralClass => return transIntegerLiteral(rp, scope, @ptrCast(*const ZigClangIntegerLiteral, stmt), result_used),
.ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const ZigClangReturnStmt, stmt)),
.StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
else => {
return revertAndWarn(
rp,
@ -335,6 +349,87 @@ fn transStmt(
}
}
fn transBinaryOperator(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangBinaryOperator,
result_used: ResultUsed,
) TransError!TransResult {
const op = ZigClangBinaryOperator_getOpcode(stmt);
const qt = ZigClangBinaryOperator_getType(stmt);
switch (op) {
.PtrMemD, .PtrMemI, .Cmp => return revertAndWarn(
rp,
error.UnsupportedTranslation,
ZigClangBinaryOperator_getBeginLoc(stmt),
"TODO: handle more C binary operators: {}",
op,
),
.Assign => return TransResult{
.node = &(try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt))).base,
.child_scope = scope,
.node_scope = scope,
},
.Add => {
const node = if (cIsUnsignedInteger(qt))
try transCreateNodeInfixOp(rp, scope, stmt, .AddWrap, .PlusPercent, "+%", true)
else
try transCreateNodeInfixOp(rp, scope, stmt, .Add, .Plus, "+", true);
return maybeSuppressResult(rp, scope, result_used, TransResult{
.node = node,
.child_scope = scope,
.node_scope = scope,
});
},
.Sub => {
const node = if (cIsUnsignedInteger(qt))
try transCreateNodeInfixOp(rp, scope, stmt, .SubWrap, .MinusPercent, "-%", true)
else
try transCreateNodeInfixOp(rp, scope, stmt, .Sub, .Minus, "-", true);
return maybeSuppressResult(rp, scope, result_used, TransResult{
.node = node,
.child_scope = scope,
.node_scope = scope,
});
},
.Mul,
.Div,
.Rem,
.Shl,
.Shr,
.LT,
.GT,
.LE,
.GE,
.EQ,
.NE,
.And,
.Xor,
.Or,
.LAnd,
.LOr,
.Comma,
=> return revertAndWarn(
rp,
error.UnsupportedTranslation,
ZigClangBinaryOperator_getBeginLoc(stmt),
"TODO: handle more C binary operators: {}",
op,
),
.MulAssign,
.DivAssign,
.RemAssign,
.AddAssign,
.SubAssign,
.ShlAssign,
.ShrAssign,
.AndAssign,
.XorAssign,
.OrAssign,
=> unreachable,
}
}
fn transCompoundStmtInline(
rp: RestorePoint,
parent_scope: *Scope,
@ -345,9 +440,10 @@ fn transCompoundStmtInline(
const end_it = ZigClangCompoundStmt_body_end(stmt);
var scope = parent_scope;
while (it != end_it) : (it += 1) {
const result = try transStmt(rp, scope, it.*, .unused, .r_value);
const result = try transStmt(rp, parent_scope, it.*, .unused, .r_value);
scope = result.child_scope;
try block_node.statements.push(result.node);
if (result.node != &block_node.base)
try block_node.statements.push(result.node);
}
return TransResult{
.node = &block_node.base,
@ -368,6 +464,427 @@ fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompo
};
}
fn transCStyleCastExprClass(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangCStyleCastExpr,
result_used: ResultUsed,
lrvalue: LRValue,
) !TransResult {
const sub_expr = ZigClangCStyleCastExpr_getSubExpr(stmt);
const cast_node = (try transCCast(
rp,
scope,
ZigClangCStyleCastExpr_getBeginLoc(stmt),
ZigClangCStyleCastExpr_getType(stmt),
ZigClangExpr_getType(sub_expr),
(try transExpr(rp, scope, sub_expr, .used, lrvalue)).node,
));
const cast_res = TransResult{
.node = cast_node,
.child_scope = scope,
.node_scope = scope,
};
return maybeSuppressResult(rp, scope, result_used, cast_res);
}
fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDeclStmt) !TransResult {
const c = rp.c;
const block_scope = findBlockScope(parent_scope);
var scope = parent_scope;
var it = ZigClangDeclStmt_decl_begin(stmt);
const end_it = ZigClangDeclStmt_decl_end(stmt);
while (it != end_it) : (it += 1) {
switch (ZigClangDecl_getKind(it.*)) {
.Var => {
const var_decl = @ptrCast(*const ZigClangVarDecl, it.*);
const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None)
null
else
try appendToken(c, .Keyword_threadlocal, "threadlocal");
const qual_type = ZigClangVarDecl_getType(var_decl);
const mut_token = if (ZigClangQualType_isConstQualified(qual_type))
try appendToken(c, .Keyword_const, "const")
else
try appendToken(c, .Keyword_var, "var");
const c_name = try c.str(ZigClangDecl_getName_bytes_begin(
@ptrCast(*const ZigClangDecl, var_decl),
));
const name_token = try appendToken(c, .Identifier, c_name);
const var_scope = try c.a().create(Scope.Var);
var_scope.* = Scope.Var{
.base = Scope{ .id = .Var, .parent = scope },
.c_name = c_name,
.zig_name = c_name, // TODO: getWantedName
};
scope = &var_scope.base;
const colon_token = try appendToken(c, .Colon, ":");
const loc = ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt));
const type_node = try transQualType(rp, qual_type, loc);
const eq_token = try appendToken(c, .Equal, "=");
const init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|
(try transExpr(rp, scope, expr, .used, .r_value)).node
else blk: {
const undefined_token = try appendToken(c, .Keyword_undefined, "undefined");
const undefined_node = try rp.c.a().create(ast.Node.UndefinedLiteral);
undefined_node.* = ast.Node.UndefinedLiteral{
.base = ast.Node{ .id = .UndefinedLiteral },
.token = undefined_token,
};
break :blk &undefined_node.base;
};
const semicolon_token = try appendToken(c, .Semicolon, ";");
const node = try c.a().create(ast.Node.VarDecl);
node.* = ast.Node.VarDecl{
.base = ast.Node{ .id = .VarDecl },
.doc_comments = null,
.visib_token = null,
.thread_local_token = thread_local_token,
.name_token = name_token,
.eq_token = eq_token,
.mut_token = mut_token,
.comptime_token = null,
.extern_export_token = null,
.lib_name = null,
.type_node = type_node,
.align_node = null, // TODO ?*Node,
.section_node = null,
.init_node = init_node,
.semicolon_token = semicolon_token,
};
try block_scope.block_node.statements.push(&node.base);
},
else => |kind| return revertAndWarn(
rp,
error.UnsupportedTranslation,
ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)),
"TODO implement translation of DeclStmt kind {}",
@tagName(kind),
),
}
}
return TransResult{
.node = &block_scope.block_node.base,
.node_scope = scope,
.child_scope = scope,
};
}
fn transDeclRefExpr(
rp: RestorePoint,
scope: *Scope,
expr: *const ZigClangDeclRefExpr,
lrvalue: LRValue,
) !TransResult {
const value_decl = ZigClangDeclRefExpr_getDecl(expr);
const c_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl)));
const zig_name = transLookupZigIdentifier(scope, c_name);
if (lrvalue == .l_value) try rp.c.ptr_params.put(zig_name);
const node = try appendIdentifier(rp.c, zig_name);
return TransResult{
.node = node,
.node_scope = scope,
.child_scope = scope,
};
}
fn transImplicitCastExpr(
rp: RestorePoint,
scope: *Scope,
expr: *const ZigClangImplicitCastExpr,
result_used: ResultUsed,
) !TransResult {
const c = rp.c;
const sub_expr = ZigClangImplicitCastExpr_getSubExpr(expr);
const sub_expr_node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value);
switch (ZigClangImplicitCastExpr_getCastKind(expr)) {
.BitCast => {
const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr));
const src_type = getExprQualType(c, sub_expr);
return TransResult{
.node = try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node.node),
.node_scope = scope,
.child_scope = scope,
};
},
.IntegralCast => {
const dest_type = ZigClangExpr_getType(@ptrCast(*const ZigClangExpr, expr));
const src_type = ZigClangExpr_getType(sub_expr);
return TransResult{
.node = try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node.node),
.node_scope = scope,
.child_scope = scope,
};
},
.FunctionToPointerDecay, .ArrayToPointerDecay => {
return maybeSuppressResult(rp, scope, result_used, sub_expr_node);
},
.LValueToRValue => {
return transExpr(rp, scope, sub_expr, .used, .r_value);
},
else => |kind| return revertAndWarn(
rp,
error.UnsupportedTranslation,
ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, expr)),
"TODO implement translation of CastKind {}",
@tagName(kind),
),
}
}
fn transIntegerLiteral(
rp: RestorePoint,
scope: *Scope,
expr: *const ZigClangIntegerLiteral,
result_used: ResultUsed,
) !TransResult {
var eval_result: ZigClangExprEvalResult = undefined;
if (!ZigClangIntegerLiteral_EvaluateAsInt(expr, &eval_result, rp.c.clang_context)) {
const loc = ZigClangIntegerLiteral_getBeginLoc(expr);
return revertAndWarn(rp, error.UnsupportedTranslation, loc, "invalid integer literal");
}
const node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&eval_result.Val));
const res = TransResult{
.node = node,
.child_scope = scope,
.node_scope = scope,
};
return maybeSuppressResult(rp, scope, result_used, res);
}
fn transReturnStmt(
rp: RestorePoint,
scope: *Scope,
expr: *const ZigClangReturnStmt,
) !TransResult {
const node = try transCreateNodeReturnExpr(rp.c);
if (ZigClangReturnStmt_getRetValue(expr)) |val_expr| {
const ret_node = node.cast(ast.Node.ControlFlowExpression).?;
ret_node.rhs = (try transExpr(rp, scope, val_expr, .used, .r_value)).node;
}
_ = try appendToken(rp.c, .Semicolon, ";");
return TransResult{
.node = node,
.child_scope = scope,
.node_scope = scope,
};
}
fn transStringLiteral(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangStringLiteral,
result_used: ResultUsed,
) !TransResult {
const kind = ZigClangStringLiteral_getKind(stmt);
switch (kind) {
.Ascii, .UTF8 => {
var len: usize = undefined;
const bytes_ptr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &len);
const str = bytes_ptr[0..len];
var char_buf: [4]u8 = undefined;
len = 0;
for (str) |c| len += escapeChar(c, &char_buf).len;
const buf = try rp.c.a().alloc(u8, len + "c\"\"".len);
buf[0] = 'c';
buf[1] = '"';
writeEscapedString(buf[2..], str);
buf[buf.len - 1] = '"';
const token = try appendToken(rp.c, .StringLiteral, buf);
const node = try rp.c.a().create(ast.Node.StringLiteral);
node.* = ast.Node.StringLiteral{
.base = ast.Node{ .id = .StringLiteral },
.token = token,
};
const res = TransResult{
.node = &node.base,
.child_scope = scope,
.node_scope = scope,
};
return maybeSuppressResult(rp, scope, result_used, res);
},
.UTF16, .UTF32, .Wide => return revertAndWarn(
rp,
error.UnsupportedTranslation,
ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)),
"TODO: support string literal kind {}",
kind,
),
}
}
fn escapedStringLen(s: []const u8) usize {
var len: usize = 0;
var char_buf: [4]u8 = undefined;
for (s) |c| len += escapeChar(c, &char_buf).len;
return len;
}
fn writeEscapedString(buf: []u8, s: []const u8) void {
var char_buf: [4]u8 = undefined;
var i: usize = 0;
for (s) |c| {
const escaped = escapeChar(c, &char_buf);
std.mem.copy(u8, buf[i..], escaped);
i += escaped.len;
}
}
// Returns either a string literal or a slice of `buf`.
fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
// TODO: https://github.com/ziglang/zig/issues/2749
const escaped = switch (c) {
// Printable ASCII except for ' " \
' ', '!', '#'...'&', '('...'[', ']'...'~' => ([_]u8{c})[0..],
'\'', '\"', '\\' => ([_]u8{ '\\', c })[0..],
'\n' => return "\\n"[0..],
'\r' => return "\\r"[0..],
'\t' => return "\\t"[0..],
else => return std.fmt.bufPrint(char_buf[0..], "\\x{x:2}", c) catch unreachable,
};
std.mem.copy(u8, char_buf, escaped);
return char_buf[0..escaped.len];
}
fn transCCast(
rp: RestorePoint,
scope: *Scope,
loc: ZigClangSourceLocation,
dst_type: ZigClangQualType,
src_type: ZigClangQualType,
expr: *ast.Node,
) !*ast.Node {
if (ZigClangType_isVoidType(qualTypeCanon(dst_type))) return expr;
if (ZigClangQualType_eq(dst_type, src_type)) return expr;
if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
return transCPtrCast(rp, loc, dst_type, src_type, expr);
if (cIsUnsignedInteger(dst_type) and qualTypeIsPtr(src_type)) {
const cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc));
const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
try builtin_node.params.push(expr);
builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
try cast_node.op.Call.params.push(&builtin_node.base);
cast_node.rtoken = try appendToken(rp.c, .RParen, ")");
return &cast_node.base;
}
if (cIsUnsignedInteger(src_type) and qualTypeIsPtr(dst_type)) {
const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
try builtin_node.params.push(try transQualType(rp, dst_type, loc));
_ = try appendToken(rp.c, .Comma, ",");
try builtin_node.params.push(expr);
builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
return &builtin_node.base;
}
// TODO: maybe widen to increase size
// TODO: maybe bitcast to change sign
// TODO: maybe truncate to reduce size
const cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc));
try cast_node.op.Call.params.push(expr);
cast_node.rtoken = try appendToken(rp.c, .RParen, ")");
return &cast_node.base;
}
fn transExpr(
rp: RestorePoint,
scope: *Scope,
expr: *const ZigClangExpr,
used: ResultUsed,
lrvalue: LRValue,
) TransError!TransResult {
return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue);
}
fn findBlockScope(inner: *Scope) *Scope.Block {
var scope = inner;
while (true) : (scope = scope.parent orelse unreachable) {
if (scope.id == .Block) return @fieldParentPtr(Scope.Block, "base", scope);
}
}
fn transLookupZigIdentifier(inner: *Scope, c_name: []const u8) []const u8 {
var scope = inner;
while (true) : (scope = scope.parent orelse return c_name) {
if (scope.id == .Var) {
const var_scope = @ptrCast(*const Scope.Var, scope);
if (std.mem.eql(u8, var_scope.c_name, c_name)) return var_scope.zig_name;
}
}
}
fn transCPtrCast(
rp: RestorePoint,
loc: ZigClangSourceLocation,
dst_type: ZigClangQualType,
src_type: ZigClangQualType,
expr: *ast.Node,
) !*ast.Node {
const ty = ZigClangQualType_getTypePtr(dst_type);
const child_type = ZigClangType_getPointeeType(ty);
// Implicit downcasting from higher to lower alignment values is forbidden,
// use @alignCast to side-step this problem
const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrCast");
const dst_type_node = try transType(rp, ty, loc);
try ptrcast_node.params.push(dst_type_node);
_ = try appendToken(rp.c, .Comma, ",");
if (ZigClangType_isVoidType(qualTypeCanon(child_type))) {
// void has 1-byte alignment, so @alignCast is not needed
try ptrcast_node.params.push(expr);
} else {
const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignCast");
const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "@alignOf");
const child_type_node = try transQualType(rp, child_type, loc);
try alignof_node.params.push(child_type_node);
alignof_node.rparen_token = try appendToken(rp.c, .RParen, ")");
try aligncast_node.params.push(&alignof_node.base);
_ = try appendToken(rp.c, .Comma, ",");
try aligncast_node.params.push(expr);
aligncast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
try ptrcast_node.params.push(&aligncast_node.base);
}
ptrcast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
return &ptrcast_node.base;
}
fn maybeSuppressResult(
rp: RestorePoint,
scope: *Scope,
used: ResultUsed,
result: TransResult,
) !TransResult {
if (used == .used) return result;
// NOTE: This is backwards, but the semicolon must immediately follow the node.
_ = try appendToken(rp.c, .Semicolon, ";");
const lhs = try appendIdentifier(rp.c, "_");
const op_token = try appendToken(rp.c, .Equal, "=");
const op_node = try rp.c.a().create(ast.Node.InfixOp);
op_node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = .InfixOp },
.op_token = op_token,
.lhs = lhs,
.op = .Assign,
.rhs = result.node,
};
return TransResult{
.node = &op_node.base,
.child_scope = scope,
.node_scope = scope,
};
}
fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: *ast.Node) !void {
try c.tree.root_node.decls.push(decl_node);
}
@ -376,11 +893,263 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou
return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
}
fn qualTypeIsPtr(qt: ZigClangQualType) bool {
return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
}
fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool {
const ty = ZigClangQualType_getTypePtr(qt);
if (ZigClangType_getTypeClass(ty) == .Paren) {
const paren_type = @ptrCast(*const ZigClangParenType, ty);
const inner_type = ZigClangParenType_getInnerType(paren_type);
return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto;
}
if (ZigClangType_getTypeClass(ty) == .Attributed) {
const attr_type = @ptrCast(*const ZigClangAttributedType, ty);
return qualTypeChildIsFnProto(ZigClangAttributedType_getEquivalentType(attr_type));
}
return false;
}
fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {
const canon = ZigClangQualType_getCanonicalType(qt);
return ZigClangQualType_getTypePtr(canon);
}
fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType {
blk: {
// If this is a C `char *`, turn it into a `const char *`
if (ZigClangExpr_getStmtClass(expr) != .ImplicitCastExprClass) break :blk;
const cast_expr = @ptrCast(*const ZigClangImplicitCastExpr, expr);
if (ZigClangImplicitCastExpr_getCastKind(cast_expr) != .ArrayToPointerDecay) break :blk;
const sub_expr = ZigClangImplicitCastExpr_getSubExpr(cast_expr);
if (ZigClangExpr_getStmtClass(sub_expr) != .StringLiteralClass) break :blk;
const array_qt = ZigClangExpr_getType(sub_expr);
const array_type = @ptrCast(*const ZigClangArrayType, ZigClangQualType_getTypePtr(array_qt));
var pointee_qt = ZigClangArrayType_getElementType(array_type);
ZigClangQualType_addConst(&pointee_qt);
return ZigClangASTContext_getPointerType(c.clang_context, pointee_qt);
}
return ZigClangExpr_getType(expr);
}
fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool {
switch (ZigClangType_getTypeClass(ty)) {
.Builtin => {
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
return ZigClangBuiltinType_getKind(builtin_ty) == .Void;
},
.Record => {
const record_ty = @ptrCast(*const ZigClangRecordType, ty);
const record_decl = ZigClangRecordType_getDecl(record_ty);
return (ZigClangRecordDecl_getDefinition(record_decl) == null);
},
.Elaborated => {
const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
const qt = ZigClangElaboratedType_getNamedType(elaborated_ty);
return typeIsOpaque(c, ZigClangQualType_getTypePtr(qt), loc);
},
.Typedef => {
const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
return typeIsOpaque(c, ZigClangQualType_getTypePtr(underlying_type), loc);
},
else => return false,
}
}
fn cIsUnsignedInteger(qt: ZigClangQualType) bool {
const c_type = qualTypeCanon(qt);
if (ZigClangType_getTypeClass(c_type) != .Builtin) return false;
const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type);
return switch (ZigClangBuiltinType_getKind(builtin_ty)) {
.Char_U,
.UChar,
.Char_S,
.UShort,
.UInt,
.ULong,
.ULongLong,
.UInt128,
.WChar_U,
=> true,
else => false,
};
}
fn transCreateNodeAssign(
rp: RestorePoint,
scope: *Scope,
result_used: ResultUsed,
lhs: *const ZigClangExpr,
rhs: *const ZigClangExpr,
) !*ast.Node.InfixOp {
// common case
// c: lhs = rhs
// zig: lhs = rhs
if (result_used == .unused) {
const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
const eq_token = try appendToken(rp.c, .Equal, "=");
const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
_ = try appendToken(rp.c, .Semicolon, ";");
const node = try rp.c.a().create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = .InfixOp },
.op_token = eq_token,
.lhs = lhs_node.node,
.op = .Assign,
.rhs = rhs_node.node,
};
return node;
}
// worst case
// c: lhs = rhs
// zig: (x: {
// zig: const _tmp = rhs;
// zig: lhs = _tmp;
// zig: break :x _tmp
// zig: })
return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangExpr_getBeginLoc(lhs), "TODO: worst case assign op expr");
}
fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.BuiltinCall {
const builtin_token = try appendToken(c, .Builtin, name);
_ = try appendToken(c, .LParen, "(");
const node = try c.a().create(ast.Node.BuiltinCall);
node.* = ast.Node.BuiltinCall{
.base = ast.Node{ .id = .BuiltinCall },
.builtin_token = builtin_token,
.params = ast.Node.BuiltinCall.ParamList.init(c.a()),
.rparen_token = undefined, // set after appending args
};
return node;
}
fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp {
_ = try appendToken(c, .LParen, "(");
const node = try c.a().create(ast.Node.SuffixOp);
node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = .SuffixOp },
.lhs = fn_expr,
.op = ast.Node.SuffixOp.Op{
.Call = ast.Node.SuffixOp.Op.Call{
.params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()),
.async_attr = null,
},
},
.rtoken = undefined, // set after appending args
};
return node;
}
fn transCreateNodePrefixOp(
c: *Context,
op: ast.Node.PrefixOp.Op,
op_tok_id: std.zig.Token.Id,
bytes: []const u8,
) !*ast.Node.PrefixOp {
const node = try c.a().create(ast.Node.PrefixOp);
node.* = ast.Node.PrefixOp{
.base = ast.Node{ .id = .PrefixOp },
.op_token = try appendToken(c, op_tok_id, bytes),
.op = op,
.rhs = undefined, // translate and set afterward
};
return node;
}
fn transCreateNodeInfixOp(
rp: RestorePoint,
scope: *Scope,
stmt: *const ZigClangBinaryOperator,
op: ast.Node.InfixOp.Op,
op_tok_id: std.zig.Token.Id,
bytes: []const u8,
grouped: bool,
) !*ast.Node {
const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;
const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
const op_token = try appendToken(rp.c, op_tok_id, bytes);
const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
const node = try rp.c.a().create(ast.Node.InfixOp);
node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = .InfixOp },
.op_token = op_token,
.lhs = lhs.node,
.op = op,
.rhs = rhs.node,
};
if (!grouped) return &node.base;
const rparen = try appendToken(rp.c, .RParen, ")");
const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression);
grouped_expr.* = ast.Node.GroupedExpression{
.base = ast.Node{ .id = .GroupedExpression },
.lparen = lparen,
.expr = &node.base,
.rparen = rparen,
};
return &grouped_expr.base;
}
fn transCreateNodePtrType(
c: *Context,
is_const: bool,
is_volatile: bool,
op_tok_id: std.zig.Token.Id,
bytes: []const u8,
) !*ast.Node.PrefixOp {
const node = try c.a().create(ast.Node.PrefixOp);
node.* = ast.Node.PrefixOp{
.base = ast.Node{ .id = .PrefixOp },
.op_token = try appendToken(c, op_tok_id, bytes),
.op = ast.Node.PrefixOp.Op{
.PtrType = ast.Node.PrefixOp.PtrInfo{
.allowzero_token = null,
.align_info = null,
.const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,
.volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,
},
},
.rhs = undefined, // translate and set afterward
};
return node;
}
fn transCreateNodeAPInt(c: *Context, int: ?*const ZigClangAPSInt) !*ast.Node {
const num_limbs = ZigClangAPSInt_getNumWords(int.?);
var big = try std.math.big.Int.initCapacity(c.a(), num_limbs);
defer big.deinit();
const data = ZigClangAPSInt_getRawData(int.?);
var i: usize = 0;
while (i < num_limbs) : (i += 1) big.limbs[i] = data[i];
const str = big.toString(c.a(), 10) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => unreachable,
};
const token = try appendToken(c, .IntegerLiteral, str);
const node = try c.a().create(ast.Node.IntegerLiteral);
node.* = ast.Node.IntegerLiteral{
.base = ast.Node{ .id = .IntegerLiteral },
.token = token,
};
return &node.base;
}
fn transCreateNodeReturnExpr(c: *Context) !*ast.Node {
const ltoken = try appendToken(c, .Keyword_return, "return");
const node = try c.a().create(ast.Node.ControlFlowExpression);
node.* = ast.Node.ControlFlowExpression{
.base = ast.Node{ .id = .ControlFlowExpression },
.ltoken = ltoken,
.kind = .Return,
.rhs = null,
};
return &node.base;
}
const RestorePoint = struct {
c: *Context,
token_index: ast.TokenIndex,
@ -429,9 +1198,43 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
},
.FunctionProto => {
const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null);
const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, false);
return &fn_proto.base;
},
.Paren => {
const paren_ty = @ptrCast(*const ZigClangParenType, ty);
return transQualType(rp, ZigClangParenType_getInnerType(paren_ty), source_loc);
},
.Pointer => {
const child_qt = ZigClangType_getPointeeType(ty);
if (qualTypeChildIsFnProto(child_qt)) {
const optional_node = try transCreateNodePrefixOp(rp.c, .OptionalType, .QuestionMark, "?");
optional_node.rhs = try transQualType(rp, child_qt, source_loc);
return &optional_node.base;
}
if (typeIsOpaque(rp.c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
const optional_node = try transCreateNodePrefixOp(rp.c, .OptionalType, .QuestionMark, "?");
const pointer_node = try transCreateNodePtrType(
rp.c,
ZigClangQualType_isConstQualified(child_qt),
ZigClangQualType_isVolatileQualified(child_qt),
.Asterisk,
"*",
);
optional_node.rhs = &pointer_node.base;
pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
return &optional_node.base;
}
const pointer_node = try transCreateNodePtrType(
rp.c,
ZigClangQualType_isConstQualified(child_qt),
ZigClangQualType_isVolatileQualified(child_qt),
.BracketStarCBracket,
"[*c]",
);
pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
return &pointer_node.base;
},
else => {
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", type_name);
@ -465,6 +1268,7 @@ fn transFnProto(
fn_proto_ty: *const ZigClangFunctionProtoType,
source_loc: ZigClangSourceLocation,
fn_decl_context: ?FnDeclContext,
is_pub: bool,
) !*ast.Node.FnProto {
const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
const cc = try transCC(rp, fn_ty, source_loc);
@ -475,7 +1279,7 @@ fn transFnProto(
return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO: implement parameters for FunctionProto in transType");
}
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
}
fn transFnNoProto(
@ -483,10 +1287,11 @@ fn transFnNoProto(
fn_ty: *const ZigClangFunctionType,
source_loc: ZigClangSourceLocation,
fn_decl_context: ?FnDeclContext,
is_pub: bool,
) !*ast.Node.FnProto {
const cc = try transCC(rp, fn_ty, source_loc);
const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
}
fn finishTransFnProto(
@ -496,18 +1301,20 @@ fn finishTransFnProto(
fn_decl_context: ?FnDeclContext,
is_var_args: bool,
cc: CallingConvention,
is_pub: bool,
) !*ast.Node.FnProto {
const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
const is_extern = if (fn_decl_context) |ctx| !ctx.has_body else true;
// TODO check for always_inline attribute
// TODO check for align attribute
// pub extern fn name(...) T
const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub");
const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null;
const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
const extern_export_inline_tok = if (is_export)
try appendToken(rp.c, .Keyword_export, "export")
else if (cc == .C)
else if (cc == .C and is_extern)
try appendToken(rp.c, .Keyword_extern, "extern")
else
null;
@ -657,7 +1464,7 @@ fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8,
.start = start_index,
.end = end_index,
};
try c.source_buffer.appendByte('\n');
try c.source_buffer.appendByte(' ');
return token_index;
}

View File

@ -444,9 +444,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
const char *extern_str = extern_string(node->data.fn_proto.is_extern);
const char *export_str = export_string(node->data.fn_proto.is_export);
const char *inline_str = inline_string(node->data.fn_proto.is_inline);
fprintf(ar->f, "%s%s%s%sfn", pub_str, inline_str, export_str, extern_str);
fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str);
if (node->data.fn_proto.name != nullptr) {
fprintf(ar->f, " ");
print_symbol(ar, node->data.fn_proto.name);
}
fprintf(ar->f, "(");

View File

@ -3837,7 +3837,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
return result_loc;
} else if (handle_is_ptr(src_return_type)) {
LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
LLVMSetAlignment(store_instr, LLVMGetAlignment(result_loc));
LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));
return result_loc;
} else {
return result;

View File

@ -21,6 +21,7 @@
#include <clang/Frontend/ASTUnit.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/AST/APValue.h>
#include <clang/AST/Expr.h>
#if __GNUC__ >= 8
@ -1287,6 +1288,20 @@ static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind
static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF16 == clang::StringLiteral::UTF16, "");
static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF32 == clang::StringLiteral::UTF32, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Uninitialized == clang::APValue::ValueKind::Uninitialized, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Int == clang::APValue::ValueKind::Int, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Float == clang::APValue::ValueKind::Float, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_ComplexInt == clang::APValue::ValueKind::ComplexInt, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_ComplexFloat == clang::APValue::ValueKind::ComplexFloat, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_LValue == clang::APValue::ValueKind::LValue, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Vector == clang::APValue::ValueKind::Vector, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Array == clang::APValue::ValueKind::Array, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Struct == clang::APValue::ValueKind::Struct, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_Union == clang::APValue::ValueKind::Union, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_MemberPointer == clang::APValue::ValueKind::MemberPointer, "");
static_assert((clang::APValue::ValueKind)ZigClangAPValue_ValueKind_AddrLabelDiff == clang::APValue::ValueKind::AddrLabelDiff, "");
static_assert(sizeof(ZigClangAPValue) == sizeof(clang::APValue), "");
static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
@ -1312,6 +1327,13 @@ static clang::QualType bitcast(ZigClangQualType src) {
return dest;
}
static_assert(sizeof(ZigClangExprEvalResult) == sizeof(clang::Expr::EvalResult), "");
static ZigClangExprEvalResult bitcast(clang::Expr::EvalResult src) {
ZigClangExprEvalResult dest;
memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangExprEvalResult));
return dest;
}
static_assert(sizeof(ZigClangAPValueLValueBase) == sizeof(clang::APValue::LValueBase), "");
static ZigClangAPValueLValueBase bitcast(clang::APValue::LValueBase src) {
ZigClangAPValueLValueBase dest;
@ -1331,6 +1353,12 @@ static ZigClangCompoundStmt_const_body_iterator bitcast(clang::CompoundStmt::con
return dest;
}
static_assert(sizeof(ZigClangDeclStmt_const_decl_iterator) == sizeof(clang::DeclStmt::const_decl_iterator), "");
static ZigClangDeclStmt_const_decl_iterator bitcast(clang::DeclStmt::const_decl_iterator src) {
ZigClangDeclStmt_const_decl_iterator dest;
memcpy(&dest, static_cast<void *>(&src), sizeof(ZigClangDeclStmt_const_decl_iterator));
return dest;
}
ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
ZigClangSourceLocation Loc)
@ -1381,7 +1409,7 @@ ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) {
return reinterpret_cast<ZigClangSourceManager *>(result);
}
bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
bool (*Fn)(void *context, const ZigClangDecl *decl))
{
return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context,
@ -1540,6 +1568,11 @@ const ZigClangType *ZigClangQualType_getTypePtr(ZigClangQualType self) {
return reinterpret_cast<const ZigClangType *>(ty);
}
ZigClangTypeClass ZigClangQualType_getTypeClass(ZigClangQualType self) {
clang::QualType ty = bitcast(self);
return (ZigClangTypeClass)(ty->getTypeClass());
}
void ZigClangQualType_addConst(ZigClangQualType *self) {
reinterpret_cast<clang::QualType *>(self)->addConst();
}
@ -1815,6 +1848,21 @@ void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
delete reinterpret_cast<clang::ASTUnit *>(self);
}
struct ZigClangQualType ZigClangVarDecl_getType(const struct ZigClangVarDecl *self) {
auto casted = reinterpret_cast<const clang::VarDecl *>(self);
return bitcast(casted->getType());
}
const struct ZigClangExpr *ZigClangVarDecl_getInit(const struct ZigClangVarDecl *self) {
auto casted = reinterpret_cast<const clang::VarDecl *>(self);
return reinterpret_cast<const ZigClangExpr *>(casted->getInit());
}
enum ZigClangVarDecl_TLSKind ZigClangVarDecl_getTLSKind(const ZigClangVarDecl *self) {
auto casted = reinterpret_cast<const clang::VarDecl *>(self);
return (ZigClangVarDecl_TLSKind)casted->getTLSKind();
}
enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) {
auto casted = reinterpret_cast<const clang::BuiltinType *>(self);
return (ZigClangBuiltinTypeKind)casted->getKind();
@ -1862,6 +1910,16 @@ ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const str
return bitcast(casted->body_end());
}
ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_begin(const struct ZigClangDeclStmt *self) {
auto casted = reinterpret_cast<const clang::DeclStmt *>(self);
return bitcast(casted->decl_begin());
}
ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_end(const struct ZigClangDeclStmt *self) {
auto casted = reinterpret_cast<const clang::DeclStmt *>(self);
return bitcast(casted->decl_end());
}
unsigned ZigClangAPFloat_convertToHexString(const ZigClangAPFloat *self, char *DST,
unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM)
{
@ -1888,3 +1946,104 @@ const struct ZigClangStringLiteral *ZigClangPredefinedExpr_getFunctionName(
const clang::StringLiteral *result = casted->getFunctionName();
return reinterpret_cast<const struct ZigClangStringLiteral *>(result);
}
ZigClangSourceLocation ZigClangImplicitCastExpr_getBeginLoc(const struct ZigClangImplicitCastExpr *self) {
auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
return bitcast(casted->getBeginLoc());
}
enum ZigClangCK ZigClangImplicitCastExpr_getCastKind(const struct ZigClangImplicitCastExpr *self) {
auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
return (ZigClangCK)casted->getCastKind();
}
const struct ZigClangExpr *ZigClangImplicitCastExpr_getSubExpr(const struct ZigClangImplicitCastExpr *self) {
auto casted = reinterpret_cast<const clang::ImplicitCastExpr *>(self);
return reinterpret_cast<const struct ZigClangExpr *>(casted->getSubExpr());
}
struct ZigClangQualType ZigClangArrayType_getElementType(const struct ZigClangArrayType *self) {
auto casted = reinterpret_cast<const clang::ArrayType *>(self);
return bitcast(casted->getElementType());
}
const struct ZigClangValueDecl *ZigClangDeclRefExpr_getDecl(const struct ZigClangDeclRefExpr *self) {
auto casted = reinterpret_cast<const clang::DeclRefExpr *>(self);
return reinterpret_cast<const struct ZigClangValueDecl *>(casted->getDecl());
}
struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZigClangParenType *self) {
auto casted = reinterpret_cast<const clang::ParenType *>(self);
return bitcast(casted->getInnerType());
}
struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *self) {
auto casted = reinterpret_cast<const clang::AttributedType *>(self);
return bitcast(casted->getEquivalentType());
}
struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {
auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);
return bitcast(casted->getNamedType());
}
struct ZigClangSourceLocation ZigClangCStyleCastExpr_getBeginLoc(const struct ZigClangCStyleCastExpr *self) {
auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
return bitcast(casted->getBeginLoc());
}
const struct ZigClangExpr *ZigClangCStyleCastExpr_getSubExpr(const struct ZigClangCStyleCastExpr *self) {
auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
return reinterpret_cast<const struct ZigClangExpr *>(casted->getSubExpr());
}
struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct ZigClangCStyleCastExpr *self) {
auto casted = reinterpret_cast<const clang::CStyleCastExpr *>(self);
return bitcast(casted->getType());
}
bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *self, struct ZigClangExprEvalResult *result, const struct ZigClangASTContext *ctx) {
auto casted_self = reinterpret_cast<const clang::IntegerLiteral *>(self);
auto casted_ctx = reinterpret_cast<const clang::ASTContext *>(ctx);
clang::Expr::EvalResult eval_result;
if (!casted_self->EvaluateAsInt(eval_result, *casted_ctx)) {
return false;
}
*result = bitcast(eval_result);
return true;
}
struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *self) {
auto casted = reinterpret_cast<const clang::IntegerLiteral *>(self);
return bitcast(casted->getBeginLoc());
}
const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *self) {
auto casted = reinterpret_cast<const clang::ReturnStmt *>(self);
return reinterpret_cast<const struct ZigClangExpr *>(casted->getRetValue());
}
enum ZigClangBO ZigClangBinaryOperator_getOpcode(const struct ZigClangBinaryOperator *self) {
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
return (ZigClangBO)casted->getOpcode();
}
struct ZigClangSourceLocation ZigClangBinaryOperator_getBeginLoc(const struct ZigClangBinaryOperator *self) {
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
return bitcast(casted->getBeginLoc());
}
const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const struct ZigClangBinaryOperator *self) {
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
return reinterpret_cast<const struct ZigClangExpr *>(casted->getLHS());
}
const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *self) {
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
return reinterpret_cast<const struct ZigClangExpr *>(casted->getRHS());
}
struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *self) {
auto casted = reinterpret_cast<const clang::BinaryOperator *>(self);
return bitcast(casted->getType());
}

View File

@ -30,6 +30,38 @@ struct ZigClangAPValueLValueBase {
unsigned Version;
};
enum ZigClangAPValue_ValueKind {
ZigClangAPValue_ValueKind_Uninitialized,
ZigClangAPValue_ValueKind_Int,
ZigClangAPValue_ValueKind_Float,
ZigClangAPValue_ValueKind_ComplexInt,
ZigClangAPValue_ValueKind_ComplexFloat,
ZigClangAPValue_ValueKind_LValue,
ZigClangAPValue_ValueKind_Vector,
ZigClangAPValue_ValueKind_Array,
ZigClangAPValue_ValueKind_Struct,
ZigClangAPValue_ValueKind_Union,
ZigClangAPValue_ValueKind_MemberPointer,
ZigClangAPValue_ValueKind_AddrLabelDiff
};
struct ZigClangAPValue {
enum ZigClangAPValue_ValueKind Kind;
// experimentally-derived size of clang::APValue::DataType
#ifdef _WIN32
char Data[52];
#else
char Data[68];
#endif
};
struct ZigClangExprEvalResult {
bool HasSideEffects;
bool HasUndefinedBehavior;
void *SmallVectorImpl;
ZigClangAPValue Val;
};
struct ZigClangAPValue;
struct ZigClangAPSInt;
struct ZigClangAPFloat;
@ -105,6 +137,7 @@ struct ZigClangFunctionType;
struct ZigClangPredefinedExpr;
typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
typedef struct ZigClangDecl *const * ZigClangDeclStmt_const_decl_iterator;
enum ZigClangBO {
ZigClangBO_PtrMemD,
@ -732,6 +765,12 @@ enum ZigClangStringLiteral_StringKind {
ZigClangStringLiteral_StringKind_UTF32,
};
enum ZigClangVarDecl_TLSKind {
ZigClangVarDecl_TLSKind_None,
ZigClangVarDecl_TLSKind_Static,
ZigClangVarDecl_TLSKind_Dynamic,
};
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
struct ZigClangSourceLocation Loc);
ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
@ -754,7 +793,7 @@ ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len
ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);
ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);
ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,
bool (*Fn)(void *context, const struct ZigClangDecl *decl));
ZIG_EXTERN_C const struct ZigClangRecordDecl *ZigClangRecordType_getDecl(const struct ZigClangRecordType *record_ty);
@ -789,6 +828,10 @@ ZIG_EXTERN_C const char *ZigClangDecl_getName_bytes_begin(const struct ZigClangD
ZIG_EXTERN_C enum ZigClangDeclKind ZigClangDecl_getKind(const struct ZigClangDecl *decl);
ZIG_EXTERN_C const char *ZigClangDecl_getDeclKindName(const struct ZigClangDecl *decl);
ZIG_EXTERN_C struct ZigClangQualType ZigClangVarDecl_getType(const struct ZigClangVarDecl *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangVarDecl_getInit(const struct ZigClangVarDecl *var_decl);
ZIG_EXTERN_C enum ZigClangVarDecl_TLSKind ZigClangVarDecl_getTLSKind(const struct ZigClangVarDecl *var_decl);
ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b);
ZIG_EXTERN_C const struct ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const struct ZigClangTypedefType *);
@ -796,6 +839,7 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangTypedefNameDecl_getUnderlyingType(c
ZIG_EXTERN_C struct ZigClangQualType ZigClangQualType_getCanonicalType(struct ZigClangQualType);
ZIG_EXTERN_C const struct ZigClangType *ZigClangQualType_getTypePtr(struct ZigClangQualType);
ZIG_EXTERN_C enum ZigClangTypeClass ZigClangQualType_getTypeClass(struct ZigClangQualType);
ZIG_EXTERN_C void ZigClangQualType_addConst(struct ZigClangQualType *);
ZIG_EXTERN_C bool ZigClangQualType_eq(struct ZigClangQualType, struct ZigClangQualType);
ZIG_EXTERN_C bool ZigClangQualType_isConstQualified(struct ZigClangQualType);
@ -846,6 +890,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionProtoType_getParamType(cons
ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_begin(const struct ZigClangCompoundStmt *self);
ZIG_EXTERN_C ZigClangCompoundStmt_const_body_iterator ZigClangCompoundStmt_body_end(const struct ZigClangCompoundStmt *self);
ZIG_EXTERN_C ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_begin(const struct ZigClangDeclStmt *self);
ZIG_EXTERN_C ZigClangDeclStmt_const_decl_iterator ZigClangDeclStmt_decl_end(const struct ZigClangDeclStmt *self);
ZIG_EXTERN_C unsigned ZigClangAPFloat_convertToHexString(const struct ZigClangAPFloat *self, char *DST,
unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM);
@ -855,4 +902,34 @@ ZIG_EXTERN_C const char *ZigClangStringLiteral_getString_bytes_begin_size(const
ZIG_EXTERN_C const struct ZigClangStringLiteral *ZigClangPredefinedExpr_getFunctionName(
const struct ZigClangPredefinedExpr *self);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangImplicitCastExpr_getBeginLoc(const struct ZigClangImplicitCastExpr *);
ZIG_EXTERN_C enum ZigClangCK ZigClangImplicitCastExpr_getCastKind(const struct ZigClangImplicitCastExpr *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangImplicitCastExpr_getSubExpr(const struct ZigClangImplicitCastExpr *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangArrayType_getElementType(const struct ZigClangArrayType *);
ZIG_EXTERN_C const struct ZigClangValueDecl *ZigClangDeclRefExpr_getDecl(const struct ZigClangDeclRefExpr *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZigClangParenType *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangCStyleCastExpr_getBeginLoc(const struct ZigClangCStyleCastExpr *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangCStyleCastExpr_getSubExpr(const struct ZigClangCStyleCastExpr *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct ZigClangCStyleCastExpr *);
ZIG_EXTERN_C bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *, struct ZigClangExprEvalResult *, const struct ZigClangASTContext *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *);
ZIG_EXTERN_C enum ZigClangBO ZigClangBinaryOperator_getOpcode(const struct ZigClangBinaryOperator *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangBinaryOperator_getBeginLoc(const struct ZigClangBinaryOperator *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const struct ZigClangBinaryOperator *);
ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *);
#endif

View File

@ -18,28 +18,80 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub extern fn bar() c_int;
);
cases.add_both("simple var decls",
\\void foo(void) {
\\ int a;
\\ char b = 123;
\\ const int c;
\\ const unsigned d = 440;
\\}
,
\\pub fn foo() void {
\\ var a: c_int = undefined;
\\ var b: u8 = u8(123);
\\ const c: c_int = undefined;
\\ const d: c_uint = c_uint(440);
\\}
);
cases.add_both("ignore result, explicit function arguments",
\\void foo(void) {
\\ int a;
\\ 1;
\\ "hey";
\\ 1 + 1;
\\ 1 - 1;
\\ a = 1;
\\}
,
\\pub fn foo() void {
\\ var a: c_int = undefined;
\\ _ = 1;
\\ _ = c"hey";
\\ _ = (1 + 1);
\\ _ = (1 - 1);
\\ a = 1;
\\}
);
/////////////// Cases that pass for only stage2 ////////////////
cases.add_2("Parameterless function prototypes",
// TODO: restore these tests after removing "import mode" concept
// https://github.com/ziglang/zig/issues/2780
// cases.add_2("Parameterless function prototypes",
// \\void a() {}
// \\void b(void) {}
// \\void c();
// \\void d(void);
// ,
// \\pub export fn a() void {}
// \\pub export fn b() void {}
// \\pub extern fn c(...) void;
// \\pub extern fn d() void;
// );
// cases.add_2("simple function definition",
// \\void foo(void) {}
// \\static void bar(void) {}
// ,
// \\pub export fn foo() void {}
// \\pub extern fn bar() void {}
// );
cases.add_2("parameterless function prototypes",
\\void a() {}
\\void b(void) {}
\\void c();
\\void d(void);
,
\\pub export fn a() void {}
\\pub export fn b() void {}
\\pub fn a(...) void {}
\\pub fn b() void {}
\\pub extern fn c(...) void;
\\pub extern fn d() void;
);
cases.add_2("simple function definition",
\\void foo(void) {}
\\static void bar(void) {}
,
\\pub export fn foo() void {}
\\pub extern fn bar() void {}
);
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
cases.add("typedef of function in struct field",
\\typedef void lws_callback_function(void);
\\struct Foo {
@ -47,9 +99,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ lws_callback_function *callback_http;
\\};
,
\\pub const lws_callback_function = extern fn() void;
\\pub const lws_callback_function = extern fn () void;
\\pub const struct_Foo = extern struct {
\\ func: ?extern fn() void,
\\ func: ?extern fn () void,
\\ callback_http: ?lws_callback_function,
\\};
);
@ -68,13 +120,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
);
cases.add_both("simple function definition",
\\void foo(void) {}
\\static void bar(void) {}
,
\\pub fn foo() void {}
\\pub fn bar() void {}
);
cases.add("macro with left shift",
\\#define REDISMODULE_READ (1<<0)
,
\\pub const REDISMODULE_READ = 1 << 0;
);
cases.add("casting pointers to ints and ints to pointers",
cases.add_both("casting pointers to ints and ints to pointers",
\\void foo(void);
\\void bar(void) {
\\ void *func_ptr = foo;
@ -84,7 +144,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub extern fn foo() void;
\\pub fn bar() void {
\\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
\\ var typed_func_ptr: ?extern fn() void = @intToPtr(?extern fn() void, c_ulong(@ptrToInt(func_ptr)));
\\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, c_ulong(@ptrToInt(func_ptr)));
\\}
);
@ -159,7 +219,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
);
cases.add("ignore result",
cases.add("ignore result, no function arguments",
\\void foo() {
\\ int a;
\\ 1;
@ -260,7 +320,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
);
cases.add("noreturn attribute",
cases.add_both("noreturn attribute",
\\void foo(void) __attribute__((noreturn));
,
\\pub extern fn foo() noreturn;
@ -384,7 +444,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
,
\\pub const struct_Foo = extern struct {
\\ derp: ?extern fn([*c]struct_Foo) void,
\\ derp: ?extern fn ([*c]struct_Foo) void,
\\};
,
\\pub const Foo = struct_Foo;
@ -467,13 +527,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\extern char (*fn_ptr2)(int, float);
\\#define bar fn_ptr2
,
\\pub extern var fn_ptr: ?extern fn() void;
\\pub extern var fn_ptr: ?extern fn () void;
,
\\pub inline fn foo() void {
\\ return fn_ptr.?();
\\}
,
\\pub extern var fn_ptr2: ?extern fn(c_int, f32) u8;
\\pub extern var fn_ptr2: ?extern fn (c_int, f32) u8;
,
\\pub inline fn bar(arg0: c_int, arg1: f32) u8 {
\\ return fn_ptr2.?(arg0, arg1);
@ -489,7 +549,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("__cdecl doesn't mess up function pointers",
\\void foo(void (__cdecl *fn_ptr)(void));
,
\\pub extern fn foo(fn_ptr: ?extern fn() void) void;
\\pub extern fn foo(fn_ptr: ?extern fn () void) void;
);
cases.add("comment after integer literal",
@ -1236,8 +1296,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return 0;
\\}
\\pub export fn bar() void {
\\ var f: ?extern fn() void = foo;
\\ var b: ?extern fn() c_int = baz;
\\ var f: ?extern fn () void = foo;
\\ var b: ?extern fn () c_int = baz;
\\ f.?();
\\ f.?();
\\ foo();
@ -1372,9 +1432,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub const GLbitfield = c_uint;
,
\\pub const PFNGLCLEARPROC = ?extern fn(GLbitfield) void;
\\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;
,
\\pub const OpenGLProc = ?extern fn() void;
\\pub const OpenGLProc = ?extern fn () void;
,
\\pub const union_OpenGLProcs = extern union {
\\ ptr: [1]OpenGLProc,