commit 21a85d4fb643cf14cf4afbcfc7ecfd359b910097 (tree)
parent e54c49be9b4b1a97805a3ffaab3f21bac48b8851
Author: Andrew Kelley <andrew@ziglang.org>
Date: Fri, 13 Dec 2019 15:48:10 -0500
Merge pull request #3896 from Vexu/translate-c-2
Translate-c self-hosted var decl and remove translate mode
Diffstat:
13 files changed, 493 insertions(+), 214 deletions(-)
diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig
@@ -1,5 +1,6 @@
const builtin = @import("builtin");
+pub const struct_ZigClangAPInt = @OpaqueType();
pub const struct_ZigClangAPSInt = @OpaqueType();
pub const struct_ZigClangAPFloat = @OpaqueType();
pub const struct_ZigClangASTContext = @OpaqueType();
@@ -73,6 +74,7 @@ pub const struct_ZigClangVarDecl = @OpaqueType();
pub const struct_ZigClangWhileStmt = @OpaqueType();
pub const struct_ZigClangFunctionType = @OpaqueType();
pub const struct_ZigClangPredefinedExpr = @OpaqueType();
+pub const struct_ZigClangInitListExpr = @OpaqueType();
pub const ZigClangBO = extern enum {
PtrMemD,
@@ -733,7 +735,7 @@ pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const s
pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
-pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
+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;
@@ -747,17 +749,19 @@ pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigCl
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) [*:0]const u8;
+pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;
pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
+pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr;
+pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;
+pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint;
pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
-pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue;
-pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue;
pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
@@ -766,6 +770,8 @@ pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const
pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
+
+pub extern fn ZigClangAPInt_getLimitedValue(self: *const struct_ZigClangAPInt, limit: u64) u64;
pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
pub extern fn ZigClangASTUnit_delete(self: ?*struct_ZigClangASTUnit) void;
@@ -863,6 +869,7 @@ pub const ZigClangVarDecl = struct_ZigClangVarDecl;
pub const ZigClangWhileStmt = struct_ZigClangWhileStmt;
pub const ZigClangFunctionType = struct_ZigClangFunctionType;
pub const ZigClangPredefinedExpr = struct_ZigClangPredefinedExpr;
+pub const ZigClangInitListExpr = struct_ZigClangInitListExpr;
pub const struct_ZigClangSourceLocation = extern struct {
ID: c_uint,
@@ -916,6 +923,9 @@ 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_getLocation(self: *const struct_ZigClangVarDecl) ZigClangSourceLocation;
+pub extern fn ZigClangVarDecl_hasInit(self: *const struct_ZigClangVarDecl) bool;
+pub extern fn ZigClangVarDecl_getStorageClass(self: *const ZigClangVarDecl) ZigClangStorageClass;
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;
@@ -930,7 +940,10 @@ pub extern fn ZigClangImplicitCastExpr_getCastKind(*const ZigClangImplicitCastEx
pub extern fn ZigClangImplicitCastExpr_getSubExpr(*const ZigClangImplicitCastExpr) *const ZigClangExpr;
pub extern fn ZigClangArrayType_getElementType(*const ZigClangArrayType) ZigClangQualType;
+pub extern fn ZigClangIncompleteArrayType_getElementType(*const ZigClangIncompleteArrayType) ZigClangQualType;
+pub extern fn ZigClangConstantArrayType_getElementType(self: *const struct_ZigClangConstantArrayType) ZigClangQualType;
+pub extern fn ZigClangConstantArrayType_getSize(self: *const struct_ZigClangConstantArrayType) *const struct_ZigClangAPInt;
pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl;
pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
@@ -957,6 +970,7 @@ pub const struct_ZigClangAPValue = extern struct {
Kind: ZigClangAPValueKind,
Data: if (builtin.os == .windows and builtin.abi == .msvc) [52]u8 else [68]u8,
};
+pub extern fn ZigClangVarDecl_getTypeSourceInfo_getType(self: *const struct_ZigClangVarDecl) struct_ZigClangQualType;
pub extern fn ZigClangIntegerLiteral_EvaluateAsInt(*const ZigClangIntegerLiteral, *ZigClangExprEvalResult, *const ZigClangASTContext) bool;
pub extern fn ZigClangIntegerLiteral_getBeginLoc(*const ZigClangIntegerLiteral) ZigClangSourceLocation;
diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig
@@ -34,12 +34,6 @@ export fn stage2_panic(ptr: [*]const u8, len: usize) void {
}
// ABI warning
-const TranslateMode = extern enum {
- import,
- translate,
-};
-
-// ABI warning
const Error = extern enum {
None,
OutOfMemory,
@@ -99,14 +93,10 @@ export fn stage2_translate_c(
out_errors_len: *usize,
args_begin: [*]?[*]const u8,
args_end: [*]?[*]const u8,
- mode: TranslateMode,
resources_path: [*]const u8,
) Error {
var errors: []translate_c.ClangErrMsg = undefined;
- out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, switch (mode) {
- .import => translate_c.Mode.import,
- .translate => translate_c.Mode.translate,
- }, &errors, resources_path) catch |err| switch (err) {
+ out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
error.SemanticAnalyzeFail => {
out_errors_ptr.* = errors.ptr;
out_errors_len.* = errors.len;
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
@@ -7,11 +7,6 @@ const ast = std.zig.ast;
const Token = std.zig.Token;
usingnamespace @import("clang.zig");
-pub const Mode = enum {
- import,
- translate,
-};
-
const CallingConvention = std.builtin.TypeInfo.CallingConvention;
pub const ClangErrMsg = Stage2ErrorMsg;
@@ -104,7 +99,6 @@ const Context = struct {
source_manager: *ZigClangSourceManager,
decl_table: DeclTable,
global_scope: *Scope.Root,
- mode: Mode,
ptr_params: std.BufSet,
clang_context: *ZigClangASTContext,
@@ -133,7 +127,6 @@ pub fn translate(
backing_allocator: *std.mem.Allocator,
args_begin: [*]?[*]const u8,
args_end: [*]?[*]const u8,
- mode: Mode,
errors: *[]ClangErrMsg,
resources_path: [*]const u8,
) !*ast.Tree {
@@ -185,7 +178,6 @@ pub fn translate(
.err = undefined,
.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).?,
};
@@ -228,7 +220,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
},
.Typedef => {
- try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs", .{});
+ try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
},
.Enum => {
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums", .{});
@@ -237,7 +229,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs", .{});
},
.Var => {
- try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for variables", .{});
+ return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));
},
else => {
const decl_name = try c.str(ZigClangDecl_getDeclKindName(decl));
@@ -262,7 +254,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 and c.mode != .import,
+ .None => has_body,
.Extern, .Static => false,
.PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
.Auto => unreachable, // Not legal on functions
@@ -310,6 +302,130 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
return addTopLevelDecl(c, fn_name, &proto_node.base);
}
+fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
+ if (try c.decl_table.put(@ptrToInt(var_decl), {})) |_| return; // Avoid processing this decl twice
+ const rp = makeRestorePoint(c);
+ const visib_tok = try appendToken(c, .Keyword_pub, "pub");
+
+ const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None)
+ null
+ else
+ try appendToken(c, .Keyword_threadlocal, "threadlocal");
+
+ var scope = &c.global_scope.base;
+ const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));
+ const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
+
+ const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
+ const storage_class = ZigClangVarDecl_getStorageClass(var_decl);
+ const is_const = ZigClangQualType_isConstQualified(qual_type);
+
+ const extern_tok = if (storage_class == .Extern)
+ try appendToken(c, .Keyword_extern, "extern")
+ else if (storage_class != .Static)
+ try appendToken(c, .Keyword_export, "export")
+ else
+ null;
+
+ const mut_tok = if (is_const)
+ try appendToken(c, .Keyword_const, "const")
+ else
+ try appendToken(c, .Keyword_var, "var");
+
+ const name_tok = try appendToken(c, .Identifier, var_name);
+
+ _ = try appendToken(c, .Colon, ":");
+ const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) {
+ error.UnsupportedType => {
+ return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{});
+ },
+ error.OutOfMemory => |e| return e,
+ };
+
+ var eq_tok: ast.TokenIndex = undefined;
+ var init_node: ?*ast.Node = null;
+
+ if (ZigClangVarDecl_hasInit(var_decl)) {
+ eq_tok = try appendToken(c, .Equal, "=");
+ init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| blk: {
+ var res = transExpr(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) {
+ error.UnsupportedTranslation,
+ error.UnsupportedType,
+ => {
+ return failDecl(c, var_decl_loc, var_name, "unable to translate initializer", .{});
+ },
+ error.OutOfMemory => |e| return e,
+ };
+ break :blk res.node;
+ } else
+ try transCreateNodeUndefinedLiteral(c);
+ } else if (storage_class != .Extern) {
+ return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{});
+ }
+
+ const node = try c.a().create(ast.Node.VarDecl);
+ node.* = ast.Node.VarDecl{
+ .base = ast.Node{ .id = .VarDecl },
+ .doc_comments = null,
+ .visib_token = visib_tok,
+ .thread_local_token = thread_local_token,
+ .name_token = name_tok,
+ .eq_token = eq_tok,
+ .mut_token = mut_tok,
+ .comptime_token = null,
+ .extern_export_token = extern_tok,
+ .lib_name = null,
+ .type_node = type_node,
+ .align_node = null,
+ .section_node = null,
+ .init_node = init_node,
+ .semicolon_token = try appendToken(c, .Semicolon, ";"),
+ };
+ return addTopLevelDecl(c, var_name, &node.base);
+}
+
+fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
+ if (try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), {})) |_| return; // Avoid processing this decl twice
+ const rp = makeRestorePoint(c);
+ const visib_tok = try appendToken(c, .Keyword_pub, "pub");
+ const const_tok = try appendToken(c, .Keyword_const, "const");
+
+ const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
+ const name_tok = try appendToken(c, .Identifier, typedef_name);
+ const eq_tok = try appendToken(c, .Equal, "=");
+
+ const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
+ const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
+ const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
+ error.UnsupportedType => {
+ const node = try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
+ _ = try c.decl_table.put(@ptrToInt(typedef_decl), node);
+ return node;
+ },
+ error.OutOfMemory => |e| return e,
+ };
+
+ const node = try c.a().create(ast.Node.VarDecl);
+ node.* = ast.Node.VarDecl{
+ .base = ast.Node{ .id = .VarDecl },
+ .doc_comments = null,
+ .visib_token = visib_tok,
+ .thread_local_token = null,
+ .name_token = name_tok,
+ .eq_token = eq_tok,
+ .mut_token = const_tok,
+ .comptime_token = null,
+ .extern_export_token = null,
+ .lib_name = null,
+ .type_node = null,
+ .align_node = null,
+ .section_node = null,
+ .init_node = type_node,
+ .semicolon_token = try appendToken(c, .Semicolon, ";"),
+ };
+ try addTopLevelDecl(c, typedef_name, &node.base);
+}
+
const ResultUsed = enum {
used,
unused,
@@ -339,6 +455,7 @@ fn transStmt(
.ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const ZigClangReturnStmt, stmt)),
.StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
.ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
+ .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
else => {
return revertAndWarn(
rp,
@@ -564,7 +681,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe
null
else
try appendToken(c, .Keyword_threadlocal, "threadlocal");
- const qual_type = ZigClangVarDecl_getType(var_decl);
+ const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
const mut_token = if (ZigClangQualType_isConstQualified(qual_type))
try appendToken(c, .Keyword_const, "const")
else
@@ -589,15 +706,8 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe
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;
- };
+ else
+ try transCreateNodeUndefinedLiteral(c);
const semicolon_token = try appendToken(c, .Semicolon, ";");
const node = try c.a().create(ast.Node.VarDecl);
@@ -687,7 +797,7 @@ fn transImplicitCastExpr(
.FunctionToPointerDecay, .ArrayToPointerDecay => {
return maybeSuppressResult(rp, scope, result_used, sub_expr_node);
},
- .LValueToRValue => {
+ .LValueToRValue, .NoOp => {
return transExpr(rp, scope, sub_expr, .used, .r_value);
},
else => |kind| return revertAndWarn(
@@ -868,6 +978,88 @@ fn transExpr(
return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue);
}
+fn transInitListExpr(
+ rp: RestorePoint,
+ scope: *Scope,
+ expr: *const ZigClangInitListExpr,
+ used: ResultUsed,
+) TransError!TransResult {
+ // TODO use anon literals once they work properly
+ const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr));
+ const qual_type = ZigClangQualType_getTypePtr(qt);
+ const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr));
+ const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type);
+ const child_qt = ZigClangArrayType_getElementType(arr_type);
+ const init_count = ZigClangInitListExpr_getNumInits(expr);
+ const all_count = 200; //ZigClangArrayType_getSize(arr_type);
+ const leftover_count = all_count - init_count;
+
+ var init_node: *ast.Node.SuffixOp = undefined;
+ var cat_tok: ast.TokenIndex = undefined;
+ if (init_count != 0) {
+ var type_node = try transQualType(rp, qt, source_loc);
+ init_node = try transCreateNodeArrayInitializer(rp.c, type_node);
+ var i: c_uint = 0;
+ while (i < init_count) : (i += 1) {
+ const elem_expr = ZigClangInitListExpr_getInit(expr, i);
+ try init_node.op.ArrayInitializer.push((try transExpr(rp, scope, elem_expr, .used, .r_value)).node);
+ _ = try appendToken(rp.c, .Comma, ",");
+ }
+ init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
+ if (leftover_count == 0) {
+ return TransResult{
+ .node = &init_node.base,
+ .child_scope = scope,
+ .node_scope = scope,
+ };
+ }
+ cat_tok = try appendToken(rp.c, .PlusPlus, "++");
+ }
+
+ var filler_type_node = try transQualType(rp, qt, source_loc);
+ var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node);
+ const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr);
+ try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node);
+ filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
+
+ const rhs_node = if (leftover_count == 1)
+ &filler_init_node.base
+ else blk: {
+ const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**");
+ const mul_node = try rp.c.a().create(ast.Node.InfixOp);
+ mul_node.* = .{
+ .base = .{ .id = .InfixOp },
+ .op_token = mul_tok,
+ .lhs = &filler_init_node.base,
+ .op = .ArrayMult,
+ .rhs = try transCreateNodeInt(rp.c, leftover_count),
+ };
+ break :blk &mul_node.base;
+ };
+
+ if (init_count == 0) {
+ return TransResult{
+ .node = rhs_node,
+ .child_scope = scope,
+ .node_scope = scope,
+ };
+ }
+
+ const cat_node = try rp.c.a().create(ast.Node.InfixOp);
+ cat_node.* = .{
+ .base = .{ .id = .InfixOp },
+ .op_token = cat_tok,
+ .lhs = &init_node.base,
+ .op = .ArrayCat,
+ .rhs = rhs_node,
+ };
+ return TransResult{
+ .node = &cat_node.base,
+ .child_scope = scope,
+ .node_scope = scope,
+ };
+}
+
fn findBlockScope(inner: *Scope) *Scope.Block {
var scope = inner;
while (true) : (scope = scope.parent orelse unreachable) {
@@ -1233,6 +1425,40 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node {
return &node.base;
}
+fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {
+ const token = try appendToken(c, .Keyword_undefined, "undefined");
+ const node = try c.a().create(ast.Node.UndefinedLiteral);
+ node.* = ast.Node.UndefinedLiteral{
+ .base = ast.Node{ .id = .UndefinedLiteral },
+ .token = token,
+ };
+ return &node.base;
+}
+
+fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node.SuffixOp {
+ _ = try appendToken(c, .LBrace, "{");
+ const node = try c.a().create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
+ .base = ast.Node{ .id = .SuffixOp },
+ .lhs = .{ .node = type_node },
+ .op = .{
+ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()),
+ },
+ .rtoken = undefined, // set after appending values
+ };
+ return node;
+}
+
+fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
+ const token = try appendToken(c, .IntegerLiteral, try std.fmt.allocPrint(c.a(), "{}", .{int}));
+ const node = try c.a().create(ast.Node.IntegerLiteral);
+ node.* = ast.Node.IntegerLiteral{
+ .base = ast.Node{ .id = .IntegerLiteral },
+ .token = token,
+ };
+ return &node.base;
+}
+
const RestorePoint = struct {
c: *Context,
token_index: ast.TokenIndex,
@@ -1316,6 +1542,47 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
return &pointer_node.base;
},
+ .ConstantArray => {
+ const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty);
+
+ const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
+ const size = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize));
+ var node = try transCreateNodePrefixOp(
+ rp.c,
+ .{
+ .ArrayType = .{
+ .len_expr = undefined,
+ .sentinel = null,
+ },
+ },
+ .LBracket,
+ "[",
+ );
+ node.op.ArrayType.len_expr = try transCreateNodeInt(rp.c, size);
+ _ = try appendToken(rp.c, .RBracket, "]");
+ node.rhs = try transQualType(rp, ZigClangConstantArrayType_getElementType(const_arr_ty), source_loc);
+ return &node.base;
+ },
+ .IncompleteArray => {
+ const incomplete_array_ty = @ptrCast(*const ZigClangIncompleteArrayType, ty);
+
+ const child_qt = ZigClangIncompleteArrayType_getElementType(incomplete_array_ty);
+ var node = try transCreateNodePtrType(
+ rp.c,
+ ZigClangQualType_isConstQualified(child_qt),
+ ZigClangQualType_isVolatileQualified(child_qt),
+ .Identifier,
+ );
+ node.rhs = try transQualType(rp, child_qt, source_loc);
+ return &node.base;
+ },
+ .Typedef => {
+ const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
+
+ const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
+ const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
+ return appendIdentifier(rp.c, typedef_name);
+ },
else => {
const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported type: '{}'", .{type_name});
@@ -1323,6 +1590,15 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
}
}
+fn isCVoid(qt: ZigClangQualType) bool {
+ const ty = ZigClangQualType_getTypePtr(qt);
+ if (ZigClangType_getTypeClass(ty) == .Builtin) {
+ const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
+ return ZigClangBuiltinType_getKind(builtin_ty) == .Void;
+ }
+ return false;
+}
+
const FnDeclContext = struct {
fn_name: []const u8,
has_body: bool,
@@ -1473,7 +1749,8 @@ fn finishTransFnProto(
break :blk try appendIdentifier(rp.c, "noreturn");
} else {
const return_qt = ZigClangFunctionType_getReturnType(fn_ty);
- if (ZigClangType_isVoidType(qualTypeCanon(return_qt))) {
+ if (isCVoid(return_qt)) {
+ // convert primitive c_void to actual void (only for return type)
break :blk try appendIdentifier(rp.c, "void");
} else {
break :blk transQualType(rp, return_qt, source_loc) catch |err| switch (err) {
@@ -1568,7 +1845,7 @@ fn failDecl(c: *Context, loc: ZigClangSourceLocation, name: []const u8, comptime
.init_node = &call_node.base,
.semicolon_token = semi_tok,
};
- try c.tree.root_node.decls.push(&var_decl_node.base);
+ try addTopLevelDecl(c, name, &var_decl_node.base);
}
fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex {
diff --git a/src/codegen.cpp b/src/codegen.cpp
@@ -9016,8 +9016,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
init(g);
- Stage2TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
- Stage2TranslateModeImport : Stage2TranslateModeTranslate;
+ TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
+ TranslateModeImport : TranslateModeTranslate;
ZigList<const char *> clang_argv = {0};
@@ -9043,7 +9043,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
if (use_userland_implementation) {
err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
- &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path);
+ &clang_argv.at(0), &clang_argv.last(), resources_path);
} else {
err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
trans_mode, resources_path);
diff --git a/src/ir.cpp b/src/ir.cpp
@@ -23303,7 +23303,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
- &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path)))
+ &clang_argv.at(0), &clang_argv.last(), TranslateModeImport, resources_path)))
{
if (err != ErrorCCompileErrors) {
ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
@@ -64,7 +64,6 @@ struct TransScopeWhile {
struct Context {
AstNode *root;
- VisibMod visib_mod;
bool want_export;
HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
@@ -367,7 +366,7 @@ static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool
static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
AstNode *init_node)
{
- return trans_create_node_var_decl(c, c->visib_mod, is_const, var_name, type_node, init_node);
+ return trans_create_node_var_decl(c, VisibModPub, is_const, var_name, type_node, init_node);
}
static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
@@ -379,7 +378,7 @@ static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf
static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *ref_node, AstNode *src_proto_node) {
AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
- fn_proto->data.fn_proto.visib_mod = c->visib_mod;
+ fn_proto->data.fn_proto.visib_mod = VisibModPub;
fn_proto->data.fn_proto.name = fn_name;
fn_proto->data.fn_proto.fn_inline = FnInlineAlways;
fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
@@ -4091,10 +4090,10 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl);
if (sc == ZigClangStorageClass_None) {
- proto_node->data.fn_proto.visib_mod = c->visib_mod;
+ proto_node->data.fn_proto.visib_mod = VisibModPub;
proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false;
} else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) {
- proto_node->data.fn_proto.visib_mod = c->visib_mod;
+ proto_node->data.fn_proto.visib_mod = VisibModPub;
} else if (sc == ZigClangStorageClass_PrivateExtern) {
emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
return;
@@ -5113,16 +5112,14 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *unit) {
Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
Stage2ErrorMsg **errors_ptr, size_t *errors_len,
const char **args_begin, const char **args_end,
- Stage2TranslateMode mode, const char *resources_path)
+ TranslateMode mode, const char *resources_path)
{
Context context = {0};
Context *c = &context;
c->warnings_on = codegen->verbose_cimport;
- if (mode == Stage2TranslateModeImport) {
- c->visib_mod = VisibModPub;
+ if (mode == TranslateModeImport) {
c->want_export = false;
} else {
- c->visib_mod = VisibModPub;
c->want_export = true;
}
c->decl_table.init(8);
diff --git a/src/translate_c.hpp b/src/translate_c.hpp
@@ -11,9 +11,14 @@
#include "all_types.hpp"
+enum TranslateMode {
+ TranslateModeImport,
+ TranslateModeTranslate,
+};
+
Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
Stage2ErrorMsg **errors_ptr, size_t *errors_len,
const char **args_begin, const char **args_end,
- Stage2TranslateMode mode, const char *resources_path);
+ TranslateMode mode, const char *resources_path);
#endif
diff --git a/src/userland.cpp b/src/userland.cpp
@@ -9,8 +9,7 @@
Error stage2_translate_c(struct Stage2Ast **out_ast,
struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
- const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
- const char *resources_path)
+ const char **args_begin, const char **args_end, const char *resources_path)
{
const char *msg = "stage0 called stage2_translate_c";
stage2_panic(msg, strlen(msg));
diff --git a/src/userland.h b/src/userland.h
@@ -81,12 +81,6 @@ enum Error {
};
// ABI warning
-enum Stage2TranslateMode {
- Stage2TranslateModeImport,
- Stage2TranslateModeTranslate,
-};
-
-// ABI warning
struct Stage2ErrorMsg {
const char *filename_ptr; // can be null
size_t filename_len;
@@ -104,8 +98,7 @@ struct Stage2Ast;
// ABI warning
ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
- const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
- const char *resources_path);
+ const char **args_begin, const char **args_end, const char *resources_path);
// ABI warning
ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
@@ -1825,6 +1825,23 @@ bool ZigClangExpr_EvaluateAsConstantExpr(const ZigClangExpr *self, ZigClangExprE
return true;
}
+const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *self, unsigned i) {
+ auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
+ const clang::Expr *result = casted->getInit(i);
+ return reinterpret_cast<const ZigClangExpr *>(result);
+}
+
+const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *self) {
+ auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
+ const clang::Expr *result = casted->getArrayFiller();
+ return reinterpret_cast<const ZigClangExpr *>(result);
+}
+
+unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *self) {
+ auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
+ return casted->getNumInits();
+}
+
ZigClangAPValueKind ZigClangAPValue_getKind(const ZigClangAPValue *self) {
auto casted = reinterpret_cast<const clang::APValue *>(self);
return (ZigClangAPValueKind)casted->getKind();
@@ -2065,6 +2082,11 @@ const ZigClangAPValue * ZigClangVarDecl_evaluateValue(const struct ZigClangVarDe
return reinterpret_cast<const ZigClangAPValue *>(result);
}
+enum ZigClangStorageClass ZigClangVarDecl_getStorageClass(const struct ZigClangVarDecl *self) {
+ auto casted = reinterpret_cast<const clang::VarDecl *>(self);
+ return (ZigClangStorageClass)casted->getStorageClass();
+}
+
enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) {
auto casted = reinterpret_cast<const clang::BuiltinType *>(self);
return (ZigClangBuiltinTypeKind)casted->getKind();
diff --git a/src/zig_clang.h b/src/zig_clang.h
@@ -144,6 +144,7 @@ struct ZigClangUnaryOperator;
struct ZigClangValueDecl;
struct ZigClangVarDecl;
struct ZigClangWhileStmt;
+struct ZigClangInitListExpr;
typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
typedef struct ZigClangDecl *const * ZigClangDeclStmt_const_decl_iterator;
@@ -904,6 +905,7 @@ ZIG_EXTERN_C bool ZigClangVarDecl_isFileVarDecl(const struct ZigClangVarDecl *);
ZIG_EXTERN_C bool ZigClangVarDecl_hasInit(const struct ZigClangVarDecl *);
ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangVarDecl_evaluateValue(const struct ZigClangVarDecl *);
ZIG_EXTERN_C struct ZigClangQualType ZigClangVarDecl_getTypeSourceInfo_getType(const struct ZigClangVarDecl *);
+ZIG_EXTERN_C enum ZigClangStorageClass ZigClangVarDecl_getStorageClass(const struct ZigClangVarDecl *self);
ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b);
@@ -939,6 +941,10 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsFloat(const struct ZigClangExpr *self,
ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr *,
struct ZigClangExprEvalResult *, ZigClangExpr_ConstExprUsage, const struct ZigClangASTContext *);
+ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned);
+ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *);
+ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *);
+
ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self);
ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self);
ZIG_EXTERN_C unsigned ZigClangAPValue_getArrayInitializedElts(const struct ZigClangAPValue *self);
diff --git a/test/tests.zig b/test/tests.zig
@@ -1651,17 +1651,6 @@ pub const TranslateCContext = struct {
self.addCase(tc);
}
- pub fn addC_2(
- self: *TranslateCContext,
- name: []const u8,
- source: []const u8,
- expected_lines: []const []const u8,
- ) void {
- const tc = self.create(false, "source.c", name, source, expected_lines);
- tc.stage2 = true;
- self.addCase(tc);
- }
-
pub fn addAllowWarnings(
self: *TranslateCContext,
name: []const u8,
diff --git a/test/translate_c.zig b/test/translate_c.zig
@@ -3,10 +3,9 @@ const builtin = @import("builtin");
// add_both - test for stage1 and stage2, in #include mode
// add - test stage1 only, in #include mode
-// add_2 - test stage2 only, in #include mode
+// add_2 - test stage2 only
// addC_both - test for stage1 and stage2, in -c mode
// addC - test stage1 only, in -c mode
-// addC_2 - test stage2 only, in -c mode
pub fn addCases(cases: *tests.TranslateCContext) void {
/////////////// Cases that pass for both stage1/stage2 ////////////////
@@ -18,7 +17,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub extern fn bar() c_int;
});
- cases.add_both("simple var decls",
+ cases.addC_both("simple var decls",
\\void foo(void) {
\\ int a;
\\ char b = 123;
@@ -26,7 +25,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ const unsigned d = 440;
\\}
, &[_][]const u8{
- \\pub fn foo() void {
+ \\pub export fn foo() void {
\\ var a: c_int = undefined;
\\ var b: u8 = @as(u8, 123);
\\ const c: c_int = undefined;
@@ -34,7 +33,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
- cases.add_both("ignore result, explicit function arguments",
+ cases.addC_both("ignore result, explicit function arguments",
\\void foo(void) {
\\ int a;
\\ 1;
@@ -44,7 +43,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ a = 1;
\\}
, &[_][]const u8{
- \\pub fn foo() void {
+ \\pub export fn foo() void {
\\ var a: c_int = undefined;
\\ _ = 1;
\\ _ = "hey";
@@ -54,42 +53,139 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
+ cases.addC_both("variables",
+ \\extern int extern_var;
+ \\static const int int_var = 13;
+ , &[_][]const u8{
+ \\pub extern var extern_var: c_int;
+ ,
+ \\pub const int_var: c_int = 13;
+ });
+
+ cases.add_both("const ptr initializer",
+ \\static const char *v0 = "0.0.0";
+ , &[_][]const u8{
+ \\pub var v0: [*c]const u8 = "0.0.0";
+ });
+
+ cases.addC_both("static incomplete array inside function",
+ \\void foo(void) {
+ \\ static const char v2[] = "2.2.2";
+ \\}
+ , &[_][]const u8{
+ \\pub export fn foo() void {
+ \\ const v2: [*c]const u8 = "2.2.2";
+ \\}
+ });
+
+ cases.addC_both("simple function definition",
+ \\void foo(void) {}
+ \\static void bar(void) {}
+ , &[_][]const u8{
+ \\pub export fn foo() void {}
+ \\pub fn bar() void {}
+ });
+
+ cases.add_both("typedef void",
+ \\typedef void Foo;
+ \\Foo fun(Foo *a);
+ , &[_][]const u8{
+ \\pub const Foo = c_void;
+ ,
+ \\pub extern fn fun(a: ?*Foo) Foo;
+ });
+
+ cases.add_both("duplicate typedef",
+ \\typedef long foo;
+ \\typedef int bar;
+ \\typedef long foo;
+ \\typedef int baz;
+ , &[_][]const u8{
+ \\pub const foo = c_long;
+ \\pub const bar = c_int;
+ \\pub const baz = c_int;
+ });
+
+ cases.addC_both("casting pointers to ints and ints to pointers",
+ \\void foo(void);
+ \\void bar(void) {
+ \\ void *func_ptr = foo;
+ \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
+ \\}
+ , &[_][]const u8{
+ \\pub extern fn foo() void;
+ \\pub export fn bar() void {
+ \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
+ \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr)));
+ \\}
+ });
+
+ cases.add_both("noreturn attribute",
+ \\void foo(void) __attribute__((noreturn));
+ , &[_][]const u8{
+ \\pub extern fn foo() noreturn;
+ });
+
+ cases.addC_both("add, sub, mul, div, rem",
+ \\int s(int a, int b) {
+ \\ int c;
+ \\ c = a + b;
+ \\ c = a - b;
+ \\ c = a * b;
+ \\ c = a / b;
+ \\ c = a % b;
+ \\}
+ \\unsigned u(unsigned a, unsigned b) {
+ \\ unsigned c;
+ \\ c = a + b;
+ \\ c = a - b;
+ \\ c = a * b;
+ \\ c = a / b;
+ \\ c = a % b;
+ \\}
+ , &[_][]const u8{
+ \\pub export fn s(a: c_int, b: c_int) c_int {
+ \\ var c: c_int = undefined;
+ \\ c = (a + b);
+ \\ c = (a - b);
+ \\ c = (a * b);
+ \\ c = @divTrunc(a, b);
+ \\ c = @rem(a, b);
+ \\}
+ \\pub export fn u(a: c_uint, b: c_uint) c_uint {
+ \\ var c: c_uint = undefined;
+ \\ c = (a +% b);
+ \\ c = (a -% b);
+ \\ c = (a *% b);
+ \\ c = (a / b);
+ \\ c = (a % b);
+ \\}
+ });
+
/////////////// Cases that pass for only stage2 ////////////////
- // 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",
+
+ cases.add_2("Parameterless function prototypes",
\\void a() {}
\\void b(void) {}
\\void c();
\\void d(void);
, &[_][]const u8{
- \\pub fn a(...) void {}
- \\pub fn b() void {}
+ \\pub export fn a() void {}
+ \\pub export fn b() void {}
\\pub extern fn c(...) void;
\\pub extern fn d() void;
});
+ cases.add_2("variable declarations",
+ \\extern char arr0[] = "hello";
+ \\static char arr1[] = "hello";
+ \\char arr2[] = "hello";
+ , &[_][]const u8{
+ \\pub extern var arr0: [*c]u8 = "hello";
+ \\pub var arr1: [*c]u8 = "hello";
+ \\pub export var arr2: [*c]u8 = "hello";
+ });
+
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
cases.add("typedef of function in struct field",
@@ -120,34 +216,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
});
- cases.add_both("simple function definition",
- \\void foo(void) {}
- \\static void bar(void) {}
- , &[_][]const u8{
- \\pub fn foo() void {}
- \\pub fn bar() void {}
- });
-
cases.add("macro with left shift",
\\#define REDISMODULE_READ (1<<0)
, &[_][]const u8{
\\pub const REDISMODULE_READ = 1 << 0;
});
- cases.add_both("casting pointers to ints and ints to pointers",
- \\void foo(void);
- \\void bar(void) {
- \\ void *func_ptr = foo;
- \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
- \\}
- , &[_][]const u8{
- \\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, @as(c_ulong, @ptrToInt(func_ptr)));
- \\}
- });
-
if (builtin.os != builtin.Os.windows) {
// Windows treats this as an enum with type c_int
cases.add("big negative enum init values when C ABI supports long long enums",
@@ -320,12 +394,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
});
- cases.add_both("noreturn attribute",
- \\void foo(void) __attribute__((noreturn));
- , &[_][]const u8{
- \\pub extern fn foo() noreturn;
- });
-
cases.addC("simple function",
\\int abs(int a) {
\\ return a < 0 ? -a : a;
@@ -482,15 +550,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const THING2 = THING1;
});
- cases.add("variables",
- \\extern int extern_var;
- \\static const int int_var = 13;
- , &[_][]const u8{
- \\pub extern var extern_var: c_int;
- ,
- \\pub const int_var: c_int = 13;
- });
-
cases.add("circular struct definitions",
\\struct Bar;
\\
@@ -511,15 +570,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
});
- cases.add("typedef void",
- \\typedef void Foo;
- \\Foo fun(Foo *a);
- , &[_][]const u8{
- \\pub const Foo = c_void;
- ,
- \\pub extern fn fun(a: ?*Foo) Foo;
- });
-
cases.add("generate inline func for #define global extern fn",
\\extern void (*fn_ptr)(void);
\\#define foo fn_ptr
@@ -719,42 +769,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
- cases.addC_both("add, sub, mul, div, rem",
- \\int s(int a, int b) {
- \\ int c;
- \\ c = a + b;
- \\ c = a - b;
- \\ c = a * b;
- \\ c = a / b;
- \\ c = a % b;
- \\}
- \\unsigned u(unsigned a, unsigned b) {
- \\ unsigned c;
- \\ c = a + b;
- \\ c = a - b;
- \\ c = a * b;
- \\ c = a / b;
- \\ c = a % b;
- \\}
- , &[_][]const u8{
- \\pub export fn s(a: c_int, b: c_int) c_int {
- \\ var c: c_int = undefined;
- \\ c = (a + b);
- \\ c = (a - b);
- \\ c = (a * b);
- \\ c = @divTrunc(a, b);
- \\ c = @rem(a, b);
- \\}
- \\pub export fn u(a: c_uint, b: c_uint) c_uint {
- \\ var c: c_uint = undefined;
- \\ c = (a +% b);
- \\ c = (a -% b);
- \\ c = (a *% b);
- \\ c = (a / b);
- \\ c = (a % b);
- \\}
- });
-
cases.addC("bitwise binary operators",
\\int max(int a, int b) {
\\ return (a & b) ^ (a | b);
@@ -1147,17 +1161,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
- cases.addC("duplicate typedef",
- \\typedef long foo;
- \\typedef int bar;
- \\typedef long foo;
- \\typedef int baz;
- , &[_][]const u8{
- \\pub const foo = c_long;
- \\pub const bar = c_int;
- \\pub const baz = c_int;
- });
-
cases.addC("post increment/decrement",
\\void foo(void) {
\\ int i = 0;
@@ -1520,22 +1523,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
});
- cases.add("const ptr initializer",
- \\static const char *v0 = "0.0.0";
- , &[_][]const u8{
- \\pub var v0: [*c]const u8 = "0.0.0";
- });
-
- cases.add("static incomplete array inside function",
- \\void foo(void) {
- \\ static const char v2[] = "2.2.2";
- \\}
- , &[_][]const u8{
- \\pub fn foo() void {
- \\ const v2: [*c]const u8 = "2.2.2";
- \\}
- });
-
cases.add("macro pointer cast",
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
, &[_][]const u8{