authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-13 15:48:10-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-12-13 15:48:10-05:00
log21a85d4fb643cf14cf4afbcfc7ecfd359b910097
tree34121806cdb748b441e2904f688fb90b78b0b5e1
parente54c49be9b4b1a97805a3ffaab3f21bac48b8851
parent45abfa9e7189e5d87d4d49763399531973c2f899
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3896 from Vexu/translate-c-2

Translate-c self-hosted var decl and remove translate mode

13 files changed, 493 insertions(+), 214 deletions(-)

src-self-hosted/clang.zig+17-3
......@@ -1,5 +1,6 @@
11const builtin = @import("builtin");
22
3pub const struct_ZigClangAPInt = @OpaqueType();
34pub const struct_ZigClangAPSInt = @OpaqueType();
45pub const struct_ZigClangAPFloat = @OpaqueType();
56pub const struct_ZigClangASTContext = @OpaqueType();
......@@ -73,6 +74,7 @@ pub const struct_ZigClangVarDecl = @OpaqueType();
7374pub const struct_ZigClangWhileStmt = @OpaqueType();
7475pub const struct_ZigClangFunctionType = @OpaqueType();
7576pub const struct_ZigClangPredefinedExpr = @OpaqueType();
77pub const struct_ZigClangInitListExpr = @OpaqueType();
7678
7779pub const ZigClangBO = extern enum {
7880 PtrMemD,
......@@ -733,7 +735,7 @@ pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const s
733735pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
734736pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
735737pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
736pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
738pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) *const struct_ZigClangTypedefNameDecl;
737739pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
738740pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
739741pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass;
......@@ -747,17 +749,19 @@ pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigCl
747749pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
748750pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
749751pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;
752pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;
750753pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
751754pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
752755pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
753756pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
754757pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
755758pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
759pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr;
760pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;
761pub extern fn ZigClangInitListExpr_getNumInits(self: ?*const struct_ZigClangInitListExpr) c_uint;
756762pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
757763pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
758764pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
759pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue;
760pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue;
761765pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
762766pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
763767pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
......@@ -766,6 +770,8 @@ pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const
766770pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
767771pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
768772pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
773
774pub extern fn ZigClangAPInt_getLimitedValue(self: *const struct_ZigClangAPInt, limit: u64) u64;
769775pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
770776pub extern fn ZigClangASTUnit_delete(self: ?*struct_ZigClangASTUnit) void;
771777
......@@ -863,6 +869,7 @@ pub const ZigClangVarDecl = struct_ZigClangVarDecl;
863869pub const ZigClangWhileStmt = struct_ZigClangWhileStmt;
864870pub const ZigClangFunctionType = struct_ZigClangFunctionType;
865871pub const ZigClangPredefinedExpr = struct_ZigClangPredefinedExpr;
872pub const ZigClangInitListExpr = struct_ZigClangInitListExpr;
866873
867874pub const struct_ZigClangSourceLocation = extern struct {
868875 ID: c_uint,
......@@ -916,6 +923,9 @@ pub const ZigClangDeclStmt_const_decl_iterator = [*c]const *struct_ZigClangDecl;
916923pub extern fn ZigClangDeclStmt_decl_begin(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
917924pub extern fn ZigClangDeclStmt_decl_end(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
918925
926pub extern fn ZigClangVarDecl_getLocation(self: *const struct_ZigClangVarDecl) ZigClangSourceLocation;
927pub extern fn ZigClangVarDecl_hasInit(self: *const struct_ZigClangVarDecl) bool;
928pub extern fn ZigClangVarDecl_getStorageClass(self: *const ZigClangVarDecl) ZigClangStorageClass;
919929pub extern fn ZigClangVarDecl_getType(self: ?*const struct_ZigClangVarDecl) struct_ZigClangQualType;
920930pub extern fn ZigClangVarDecl_getInit(*const ZigClangVarDecl) ?*const ZigClangExpr;
921931pub extern fn ZigClangVarDecl_getTLSKind(self: ?*const struct_ZigClangVarDecl) ZigClangVarDecl_TLSKind;
......@@ -930,7 +940,10 @@ pub extern fn ZigClangImplicitCastExpr_getCastKind(*const ZigClangImplicitCastEx
930940pub extern fn ZigClangImplicitCastExpr_getSubExpr(*const ZigClangImplicitCastExpr) *const ZigClangExpr;
931941
932942pub extern fn ZigClangArrayType_getElementType(*const ZigClangArrayType) ZigClangQualType;
943pub extern fn ZigClangIncompleteArrayType_getElementType(*const ZigClangIncompleteArrayType) ZigClangQualType;
933944
945pub extern fn ZigClangConstantArrayType_getElementType(self: *const struct_ZigClangConstantArrayType) ZigClangQualType;
946pub extern fn ZigClangConstantArrayType_getSize(self: *const struct_ZigClangConstantArrayType) *const struct_ZigClangAPInt;
934947pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl;
935948
936949pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
......@@ -957,6 +970,7 @@ pub const struct_ZigClangAPValue = extern struct {
957970 Kind: ZigClangAPValueKind,
958971 Data: if (builtin.os == .windows and builtin.abi == .msvc) [52]u8 else [68]u8,
959972};
973pub extern fn ZigClangVarDecl_getTypeSourceInfo_getType(self: *const struct_ZigClangVarDecl) struct_ZigClangQualType;
960974
961975pub extern fn ZigClangIntegerLiteral_EvaluateAsInt(*const ZigClangIntegerLiteral, *ZigClangExprEvalResult, *const ZigClangASTContext) bool;
962976pub extern fn ZigClangIntegerLiteral_getBeginLoc(*const ZigClangIntegerLiteral) ZigClangSourceLocation;
src-self-hosted/stage1.zig+1-11
......@@ -33,12 +33,6 @@ export fn stage2_panic(ptr: [*]const u8, len: usize) void {
3333 @panic(ptr[0..len]);
3434}
3535
36// ABI warning
37const TranslateMode = extern enum {
38 import,
39 translate,
40};
41
4236// ABI warning
4337const Error = extern enum {
4438 None,
......@@ -99,14 +93,10 @@ export fn stage2_translate_c(
9993 out_errors_len: *usize,
10094 args_begin: [*]?[*]const u8,
10195 args_end: [*]?[*]const u8,
102 mode: TranslateMode,
10396 resources_path: [*]const u8,
10497) Error {
10598 var errors: []translate_c.ClangErrMsg = undefined;
106 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, switch (mode) {
107 .import => translate_c.Mode.import,
108 .translate => translate_c.Mode.translate,
109 }, &errors, resources_path) catch |err| switch (err) {
99 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
110100 error.SemanticAnalyzeFail => {
111101 out_errors_ptr.* = errors.ptr;
112102 out_errors_len.* = errors.len;
src-self-hosted/translate_c.zig+301-24
......@@ -7,11 +7,6 @@ const ast = std.zig.ast;
77const Token = std.zig.Token;
88usingnamespace @import("clang.zig");
99
10pub const Mode = enum {
11 import,
12 translate,
13};
14
1510const CallingConvention = std.builtin.TypeInfo.CallingConvention;
1611
1712pub const ClangErrMsg = Stage2ErrorMsg;
......@@ -104,7 +99,6 @@ const Context = struct {
10499 source_manager: *ZigClangSourceManager,
105100 decl_table: DeclTable,
106101 global_scope: *Scope.Root,
107 mode: Mode,
108102 ptr_params: std.BufSet,
109103 clang_context: *ZigClangASTContext,
110104
......@@ -133,7 +127,6 @@ pub fn translate(
133127 backing_allocator: *std.mem.Allocator,
134128 args_begin: [*]?[*]const u8,
135129 args_end: [*]?[*]const u8,
136 mode: Mode,
137130 errors: *[]ClangErrMsg,
138131 resources_path: [*]const u8,
139132) !*ast.Tree {
......@@ -185,7 +178,6 @@ pub fn translate(
185178 .err = undefined,
186179 .decl_table = DeclTable.init(arena),
187180 .global_scope = try arena.create(Scope.Root),
188 .mode = mode,
189181 .ptr_params = std.BufSet.init(arena),
190182 .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?,
191183 };
......@@ -228,7 +220,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
228220 return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
229221 },
230222 .Typedef => {
231 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs", .{});
223 try resolveTypeDef(c, @ptrCast(*const ZigClangTypedefNameDecl, decl));
232224 },
233225 .Enum => {
234226 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 {
237229 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs", .{});
238230 },
239231 .Var => {
240 try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for variables", .{});
232 return visitVarDecl(c, @ptrCast(*const ZigClangVarDecl, decl));
241233 },
242234 else => {
243235 const decl_name = try c.str(ZigClangDecl_getDeclKindName(decl));
......@@ -262,7 +254,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
262254 .storage_class = storage_class,
263255 .scope = &scope,
264256 .is_export = switch (storage_class) {
265 .None => has_body and c.mode != .import,
257 .None => has_body,
266258 .Extern, .Static => false,
267259 .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
268260 .Auto => unreachable, // Not legal on functions
......@@ -310,6 +302,130 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
310302 return addTopLevelDecl(c, fn_name, &proto_node.base);
311303}
312304
305fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
306 if (try c.decl_table.put(@ptrToInt(var_decl), {})) |_| return; // Avoid processing this decl twice
307 const rp = makeRestorePoint(c);
308 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
309
310 const thread_local_token = if (ZigClangVarDecl_getTLSKind(var_decl) == .None)
311 null
312 else
313 try appendToken(c, .Keyword_threadlocal, "threadlocal");
314
315 var scope = &c.global_scope.base;
316 const var_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, var_decl)));
317 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
318
319 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
320 const storage_class = ZigClangVarDecl_getStorageClass(var_decl);
321 const is_const = ZigClangQualType_isConstQualified(qual_type);
322
323 const extern_tok = if (storage_class == .Extern)
324 try appendToken(c, .Keyword_extern, "extern")
325 else if (storage_class != .Static)
326 try appendToken(c, .Keyword_export, "export")
327 else
328 null;
329
330 const mut_tok = if (is_const)
331 try appendToken(c, .Keyword_const, "const")
332 else
333 try appendToken(c, .Keyword_var, "var");
334
335 const name_tok = try appendToken(c, .Identifier, var_name);
336
337 _ = try appendToken(c, .Colon, ":");
338 const type_node = transQualType(rp, qual_type, var_decl_loc) catch |err| switch (err) {
339 error.UnsupportedType => {
340 return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{});
341 },
342 error.OutOfMemory => |e| return e,
343 };
344
345 var eq_tok: ast.TokenIndex = undefined;
346 var init_node: ?*ast.Node = null;
347
348 if (ZigClangVarDecl_hasInit(var_decl)) {
349 eq_tok = try appendToken(c, .Equal, "=");
350 init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr| blk: {
351 var res = transExpr(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) {
352 error.UnsupportedTranslation,
353 error.UnsupportedType,
354 => {
355 return failDecl(c, var_decl_loc, var_name, "unable to translate initializer", .{});
356 },
357 error.OutOfMemory => |e| return e,
358 };
359 break :blk res.node;
360 } else
361 try transCreateNodeUndefinedLiteral(c);
362 } else if (storage_class != .Extern) {
363 return failDecl(c, var_decl_loc, var_name, "non-extern variable has no initializer", .{});
364 }
365
366 const node = try c.a().create(ast.Node.VarDecl);
367 node.* = ast.Node.VarDecl{
368 .base = ast.Node{ .id = .VarDecl },
369 .doc_comments = null,
370 .visib_token = visib_tok,
371 .thread_local_token = thread_local_token,
372 .name_token = name_tok,
373 .eq_token = eq_tok,
374 .mut_token = mut_tok,
375 .comptime_token = null,
376 .extern_export_token = extern_tok,
377 .lib_name = null,
378 .type_node = type_node,
379 .align_node = null,
380 .section_node = null,
381 .init_node = init_node,
382 .semicolon_token = try appendToken(c, .Semicolon, ";"),
383 };
384 return addTopLevelDecl(c, var_name, &node.base);
385}
386
387fn resolveTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error!void {
388 if (try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), {})) |_| return; // Avoid processing this decl twice
389 const rp = makeRestorePoint(c);
390 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
391 const const_tok = try appendToken(c, .Keyword_const, "const");
392
393 const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
394 const name_tok = try appendToken(c, .Identifier, typedef_name);
395 const eq_tok = try appendToken(c, .Equal, "=");
396
397 const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
398 const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
399 const type_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
400 error.UnsupportedType => {
401 const node = try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
402 _ = try c.decl_table.put(@ptrToInt(typedef_decl), node);
403 return node;
404 },
405 error.OutOfMemory => |e| return e,
406 };
407
408 const node = try c.a().create(ast.Node.VarDecl);
409 node.* = ast.Node.VarDecl{
410 .base = ast.Node{ .id = .VarDecl },
411 .doc_comments = null,
412 .visib_token = visib_tok,
413 .thread_local_token = null,
414 .name_token = name_tok,
415 .eq_token = eq_tok,
416 .mut_token = const_tok,
417 .comptime_token = null,
418 .extern_export_token = null,
419 .lib_name = null,
420 .type_node = null,
421 .align_node = null,
422 .section_node = null,
423 .init_node = type_node,
424 .semicolon_token = try appendToken(c, .Semicolon, ";"),
425 };
426 try addTopLevelDecl(c, typedef_name, &node.base);
427}
428
313429const ResultUsed = enum {
314430 used,
315431 unused,
......@@ -339,6 +455,7 @@ fn transStmt(
339455 .ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const ZigClangReturnStmt, stmt)),
340456 .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
341457 .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
458 .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
342459 else => {
343460 return revertAndWarn(
344461 rp,
......@@ -564,7 +681,7 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe
564681 null
565682 else
566683 try appendToken(c, .Keyword_threadlocal, "threadlocal");
567 const qual_type = ZigClangVarDecl_getType(var_decl);
684 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
568685 const mut_token = if (ZigClangQualType_isConstQualified(qual_type))
569686 try appendToken(c, .Keyword_const, "const")
570687 else
......@@ -589,15 +706,8 @@ fn transDeclStmt(rp: RestorePoint, parent_scope: *Scope, stmt: *const ZigClangDe
589706 const eq_token = try appendToken(c, .Equal, "=");
590707 const init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|
591708 (try transExpr(rp, scope, expr, .used, .r_value)).node
592 else blk: {
593 const undefined_token = try appendToken(c, .Keyword_undefined, "undefined");
594 const undefined_node = try rp.c.a().create(ast.Node.UndefinedLiteral);
595 undefined_node.* = ast.Node.UndefinedLiteral{
596 .base = ast.Node{ .id = .UndefinedLiteral },
597 .token = undefined_token,
598 };
599 break :blk &undefined_node.base;
600 };
709 else
710 try transCreateNodeUndefinedLiteral(c);
601711 const semicolon_token = try appendToken(c, .Semicolon, ";");
602712
603713 const node = try c.a().create(ast.Node.VarDecl);
......@@ -687,7 +797,7 @@ fn transImplicitCastExpr(
687797 .FunctionToPointerDecay, .ArrayToPointerDecay => {
688798 return maybeSuppressResult(rp, scope, result_used, sub_expr_node);
689799 },
690 .LValueToRValue => {
800 .LValueToRValue, .NoOp => {
691801 return transExpr(rp, scope, sub_expr, .used, .r_value);
692802 },
693803 else => |kind| return revertAndWarn(
......@@ -868,6 +978,88 @@ fn transExpr(
868978 return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue);
869979}
870980
981fn transInitListExpr(
982 rp: RestorePoint,
983 scope: *Scope,
984 expr: *const ZigClangInitListExpr,
985 used: ResultUsed,
986) TransError!TransResult {
987 // TODO use anon literals once they work properly
988 const qt = getExprQualType(rp.c, @ptrCast(*const ZigClangExpr, expr));
989 const qual_type = ZigClangQualType_getTypePtr(qt);
990 const source_loc = ZigClangExpr_getBeginLoc(@ptrCast(*const ZigClangExpr, expr));
991 const arr_type = ZigClangType_getAsArrayTypeUnsafe(qual_type);
992 const child_qt = ZigClangArrayType_getElementType(arr_type);
993 const init_count = ZigClangInitListExpr_getNumInits(expr);
994 const all_count = 200; //ZigClangArrayType_getSize(arr_type);
995 const leftover_count = all_count - init_count;
996
997 var init_node: *ast.Node.SuffixOp = undefined;
998 var cat_tok: ast.TokenIndex = undefined;
999 if (init_count != 0) {
1000 var type_node = try transQualType(rp, qt, source_loc);
1001 init_node = try transCreateNodeArrayInitializer(rp.c, type_node);
1002 var i: c_uint = 0;
1003 while (i < init_count) : (i += 1) {
1004 const elem_expr = ZigClangInitListExpr_getInit(expr, i);
1005 try init_node.op.ArrayInitializer.push((try transExpr(rp, scope, elem_expr, .used, .r_value)).node);
1006 _ = try appendToken(rp.c, .Comma, ",");
1007 }
1008 init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
1009 if (leftover_count == 0) {
1010 return TransResult{
1011 .node = &init_node.base,
1012 .child_scope = scope,
1013 .node_scope = scope,
1014 };
1015 }
1016 cat_tok = try appendToken(rp.c, .PlusPlus, "++");
1017 }
1018
1019 var filler_type_node = try transQualType(rp, qt, source_loc);
1020 var filler_init_node = try transCreateNodeArrayInitializer(rp.c, filler_type_node);
1021 const filler_val_expr = ZigClangInitListExpr_getArrayFiller(expr);
1022 try filler_init_node.op.ArrayInitializer.push((try transExpr(rp, scope, filler_val_expr, .used, .r_value)).node);
1023 filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
1024
1025 const rhs_node = if (leftover_count == 1)
1026 &filler_init_node.base
1027 else blk: {
1028 const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**");
1029 const mul_node = try rp.c.a().create(ast.Node.InfixOp);
1030 mul_node.* = .{
1031 .base = .{ .id = .InfixOp },
1032 .op_token = mul_tok,
1033 .lhs = &filler_init_node.base,
1034 .op = .ArrayMult,
1035 .rhs = try transCreateNodeInt(rp.c, leftover_count),
1036 };
1037 break :blk &mul_node.base;
1038 };
1039
1040 if (init_count == 0) {
1041 return TransResult{
1042 .node = rhs_node,
1043 .child_scope = scope,
1044 .node_scope = scope,
1045 };
1046 }
1047
1048 const cat_node = try rp.c.a().create(ast.Node.InfixOp);
1049 cat_node.* = .{
1050 .base = .{ .id = .InfixOp },
1051 .op_token = cat_tok,
1052 .lhs = &init_node.base,
1053 .op = .ArrayCat,
1054 .rhs = rhs_node,
1055 };
1056 return TransResult{
1057 .node = &cat_node.base,
1058 .child_scope = scope,
1059 .node_scope = scope,
1060 };
1061}
1062
8711063fn findBlockScope(inner: *Scope) *Scope.Block {
8721064 var scope = inner;
8731065 while (true) : (scope = scope.parent orelse unreachable) {
......@@ -1233,6 +1425,40 @@ fn transCreateNodeReturnExpr(c: *Context) !*ast.Node {
12331425 return &node.base;
12341426}
12351427
1428fn transCreateNodeUndefinedLiteral(c: *Context) !*ast.Node {
1429 const token = try appendToken(c, .Keyword_undefined, "undefined");
1430 const node = try c.a().create(ast.Node.UndefinedLiteral);
1431 node.* = ast.Node.UndefinedLiteral{
1432 .base = ast.Node{ .id = .UndefinedLiteral },
1433 .token = token,
1434 };
1435 return &node.base;
1436}
1437
1438fn transCreateNodeArrayInitializer(c: *Context, type_node: *ast.Node) !*ast.Node.SuffixOp {
1439 _ = try appendToken(c, .LBrace, "{");
1440 const node = try c.a().create(ast.Node.SuffixOp);
1441 node.* = ast.Node.SuffixOp{
1442 .base = ast.Node{ .id = .SuffixOp },
1443 .lhs = .{ .node = type_node },
1444 .op = .{
1445 .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()),
1446 },
1447 .rtoken = undefined, // set after appending values
1448 };
1449 return node;
1450}
1451
1452fn transCreateNodeInt(c: *Context, int: var) !*ast.Node {
1453 const token = try appendToken(c, .IntegerLiteral, try std.fmt.allocPrint(c.a(), "{}", .{int}));
1454 const node = try c.a().create(ast.Node.IntegerLiteral);
1455 node.* = ast.Node.IntegerLiteral{
1456 .base = ast.Node{ .id = .IntegerLiteral },
1457 .token = token,
1458 };
1459 return &node.base;
1460}
1461
12361462const RestorePoint = struct {
12371463 c: *Context,
12381464 token_index: ast.TokenIndex,
......@@ -1316,6 +1542,47 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
13161542 pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
13171543 return &pointer_node.base;
13181544 },
1545 .ConstantArray => {
1546 const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty);
1547
1548 const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
1549 const size = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize));
1550 var node = try transCreateNodePrefixOp(
1551 rp.c,
1552 .{
1553 .ArrayType = .{
1554 .len_expr = undefined,
1555 .sentinel = null,
1556 },
1557 },
1558 .LBracket,
1559 "[",
1560 );
1561 node.op.ArrayType.len_expr = try transCreateNodeInt(rp.c, size);
1562 _ = try appendToken(rp.c, .RBracket, "]");
1563 node.rhs = try transQualType(rp, ZigClangConstantArrayType_getElementType(const_arr_ty), source_loc);
1564 return &node.base;
1565 },
1566 .IncompleteArray => {
1567 const incomplete_array_ty = @ptrCast(*const ZigClangIncompleteArrayType, ty);
1568
1569 const child_qt = ZigClangIncompleteArrayType_getElementType(incomplete_array_ty);
1570 var node = try transCreateNodePtrType(
1571 rp.c,
1572 ZigClangQualType_isConstQualified(child_qt),
1573 ZigClangQualType_isVolatileQualified(child_qt),
1574 .Identifier,
1575 );
1576 node.rhs = try transQualType(rp, child_qt, source_loc);
1577 return &node.base;
1578 },
1579 .Typedef => {
1580 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
1581
1582 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1583 const typedef_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
1584 return appendIdentifier(rp.c, typedef_name);
1585 },
13191586 else => {
13201587 const type_name = rp.c.str(ZigClangType_getTypeClassName(ty));
13211588 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
13231590 }
13241591}
13251592
1593fn isCVoid(qt: ZigClangQualType) bool {
1594 const ty = ZigClangQualType_getTypePtr(qt);
1595 if (ZigClangType_getTypeClass(ty) == .Builtin) {
1596 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
1597 return ZigClangBuiltinType_getKind(builtin_ty) == .Void;
1598 }
1599 return false;
1600}
1601
13261602const FnDeclContext = struct {
13271603 fn_name: []const u8,
13281604 has_body: bool,
......@@ -1473,7 +1749,8 @@ fn finishTransFnProto(
14731749 break :blk try appendIdentifier(rp.c, "noreturn");
14741750 } else {
14751751 const return_qt = ZigClangFunctionType_getReturnType(fn_ty);
1476 if (ZigClangType_isVoidType(qualTypeCanon(return_qt))) {
1752 if (isCVoid(return_qt)) {
1753 // convert primitive c_void to actual void (only for return type)
14771754 break :blk try appendIdentifier(rp.c, "void");
14781755 } else {
14791756 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
15681845 .init_node = &call_node.base,
15691846 .semicolon_token = semi_tok,
15701847 };
1571 try c.tree.root_node.decls.push(&var_decl_node.base);
1848 try addTopLevelDecl(c, name, &var_decl_node.base);
15721849}
15731850
15741851fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenIndex {
src/codegen.cpp+3-3
......@@ -9016,8 +9016,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
90169016
90179017 init(g);
90189018
9019 Stage2TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
9020 Stage2TranslateModeImport : Stage2TranslateModeTranslate;
9019 TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
9020 TranslateModeImport : TranslateModeTranslate;
90219021
90229022
90239023 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
90439043
90449044 if (use_userland_implementation) {
90459045 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
9046 &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path);
9046 &clang_argv.at(0), &clang_argv.last(), resources_path);
90479047 } else {
90489048 err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
90499049 trans_mode, resources_path);
src/ir.cpp+1-1
......@@ -23303,7 +23303,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
2330323303 const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
2330423304
2330523305 if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
23306 &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path)))
23306 &clang_argv.at(0), &clang_argv.last(), TranslateModeImport, resources_path)))
2330723307 {
2330823308 if (err != ErrorCCompileErrors) {
2330923309 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
src/translate_c.cpp+6-9
......@@ -64,7 +64,6 @@ struct TransScopeWhile {
6464
6565struct Context {
6666 AstNode *root;
67 VisibMod visib_mod;
6867 bool want_export;
6968 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
7069 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
367366static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
368367 AstNode *init_node)
369368{
370 return trans_create_node_var_decl(c, c->visib_mod, is_const, var_name, type_node, init_node);
369 return trans_create_node_var_decl(c, VisibModPub, is_const, var_name, type_node, init_node);
371370}
372371
373372static 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
379378static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *ref_node, AstNode *src_proto_node) {
380379 AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
381380 AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
382 fn_proto->data.fn_proto.visib_mod = c->visib_mod;
381 fn_proto->data.fn_proto.visib_mod = VisibModPub;
383382 fn_proto->data.fn_proto.name = fn_name;
384383 fn_proto->data.fn_proto.fn_inline = FnInlineAlways;
385384 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) {
40914090
40924091 ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl);
40934092 if (sc == ZigClangStorageClass_None) {
4094 proto_node->data.fn_proto.visib_mod = c->visib_mod;
4093 proto_node->data.fn_proto.visib_mod = VisibModPub;
40954094 proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false;
40964095 } else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) {
4097 proto_node->data.fn_proto.visib_mod = c->visib_mod;
4096 proto_node->data.fn_proto.visib_mod = VisibModPub;
40984097 } else if (sc == ZigClangStorageClass_PrivateExtern) {
40994098 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
41004099 return;
......@@ -5113,16 +5112,14 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *unit) {
51135112Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
51145113 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
51155114 const char **args_begin, const char **args_end,
5116 Stage2TranslateMode mode, const char *resources_path)
5115 TranslateMode mode, const char *resources_path)
51175116{
51185117 Context context = {0};
51195118 Context *c = &context;
51205119 c->warnings_on = codegen->verbose_cimport;
5121 if (mode == Stage2TranslateModeImport) {
5122 c->visib_mod = VisibModPub;
5120 if (mode == TranslateModeImport) {
51235121 c->want_export = false;
51245122 } else {
5125 c->visib_mod = VisibModPub;
51265123 c->want_export = true;
51275124 }
51285125 c->decl_table.init(8);
src/translate_c.hpp+6-1
......@@ -11,9 +11,14 @@
1111
1212#include "all_types.hpp"
1313
14enum TranslateMode {
15 TranslateModeImport,
16 TranslateModeTranslate,
17};
18
1419Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
1520 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
1621 const char **args_begin, const char **args_end,
17 Stage2TranslateMode mode, const char *resources_path);
22 TranslateMode mode, const char *resources_path);
1823
1924#endif
src/userland.cpp+1-2
......@@ -9,8 +9,7 @@
99
1010Error stage2_translate_c(struct Stage2Ast **out_ast,
1111 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
12 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
13 const char *resources_path)
12 const char **args_begin, const char **args_end, const char *resources_path)
1413{
1514 const char *msg = "stage0 called stage2_translate_c";
1615 stage2_panic(msg, strlen(msg));
src/userland.h+1-8
......@@ -80,12 +80,6 @@ enum Error {
8080 ErrorImportOutsidePkgPath,
8181};
8282
83// ABI warning
84enum Stage2TranslateMode {
85 Stage2TranslateModeImport,
86 Stage2TranslateModeTranslate,
87};
88
8983// ABI warning
9084struct Stage2ErrorMsg {
9185 const char *filename_ptr; // can be null
......@@ -104,8 +98,7 @@ struct Stage2Ast;
10498// ABI warning
10599ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
106100 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
107 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
108 const char *resources_path);
101 const char **args_begin, const char **args_end, const char *resources_path);
109102
110103// ABI warning
111104ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
src/zig_clang.cpp+22
......@@ -1825,6 +1825,23 @@ bool ZigClangExpr_EvaluateAsConstantExpr(const ZigClangExpr *self, ZigClangExprE
18251825 return true;
18261826}
18271827
1828const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *self, unsigned i) {
1829 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
1830 const clang::Expr *result = casted->getInit(i);
1831 return reinterpret_cast<const ZigClangExpr *>(result);
1832}
1833
1834const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *self) {
1835 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
1836 const clang::Expr *result = casted->getArrayFiller();
1837 return reinterpret_cast<const ZigClangExpr *>(result);
1838}
1839
1840unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *self) {
1841 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
1842 return casted->getNumInits();
1843}
1844
18281845ZigClangAPValueKind ZigClangAPValue_getKind(const ZigClangAPValue *self) {
18291846 auto casted = reinterpret_cast<const clang::APValue *>(self);
18301847 return (ZigClangAPValueKind)casted->getKind();
......@@ -2065,6 +2082,11 @@ const ZigClangAPValue * ZigClangVarDecl_evaluateValue(const struct ZigClangVarDe
20652082 return reinterpret_cast<const ZigClangAPValue *>(result);
20662083}
20672084
2085enum ZigClangStorageClass ZigClangVarDecl_getStorageClass(const struct ZigClangVarDecl *self) {
2086 auto casted = reinterpret_cast<const clang::VarDecl *>(self);
2087 return (ZigClangStorageClass)casted->getStorageClass();
2088}
2089
20682090enum ZigClangBuiltinTypeKind ZigClangBuiltinType_getKind(const struct ZigClangBuiltinType *self) {
20692091 auto casted = reinterpret_cast<const clang::BuiltinType *>(self);
20702092 return (ZigClangBuiltinTypeKind)casted->getKind();
src/zig_clang.h+6
......@@ -144,6 +144,7 @@ struct ZigClangUnaryOperator;
144144struct ZigClangValueDecl;
145145struct ZigClangVarDecl;
146146struct ZigClangWhileStmt;
147struct ZigClangInitListExpr;
147148
148149typedef struct ZigClangStmt *const * ZigClangCompoundStmt_const_body_iterator;
149150typedef struct ZigClangDecl *const * ZigClangDeclStmt_const_decl_iterator;
......@@ -904,6 +905,7 @@ ZIG_EXTERN_C bool ZigClangVarDecl_isFileVarDecl(const struct ZigClangVarDecl *);
904905ZIG_EXTERN_C bool ZigClangVarDecl_hasInit(const struct ZigClangVarDecl *);
905906ZIG_EXTERN_C const struct ZigClangAPValue *ZigClangVarDecl_evaluateValue(const struct ZigClangVarDecl *);
906907ZIG_EXTERN_C struct ZigClangQualType ZigClangVarDecl_getTypeSourceInfo_getType(const struct ZigClangVarDecl *);
908ZIG_EXTERN_C enum ZigClangStorageClass ZigClangVarDecl_getStorageClass(const struct ZigClangVarDecl *self);
907909
908910ZIG_EXTERN_C bool ZigClangSourceLocation_eq(struct ZigClangSourceLocation a, struct ZigClangSourceLocation b);
909911
......@@ -939,6 +941,10 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsFloat(const struct ZigClangExpr *self,
939941ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr *,
940942 struct ZigClangExprEvalResult *, ZigClangExpr_ConstExprUsage, const struct ZigClangASTContext *);
941943
944ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned);
945ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *);
946ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *);
947
942948ZIG_EXTERN_C enum ZigClangAPValueKind ZigClangAPValue_getKind(const struct ZigClangAPValue *self);
943949ZIG_EXTERN_C const struct ZigClangAPSInt *ZigClangAPValue_getInt(const struct ZigClangAPValue *self);
944950ZIG_EXTERN_C unsigned ZigClangAPValue_getArrayInitializedElts(const struct ZigClangAPValue *self);
test/tests.zig-11
......@@ -1651,17 +1651,6 @@ pub const TranslateCContext = struct {
16511651 self.addCase(tc);
16521652 }
16531653
1654 pub fn addC_2(
1655 self: *TranslateCContext,
1656 name: []const u8,
1657 source: []const u8,
1658 expected_lines: []const []const u8,
1659 ) void {
1660 const tc = self.create(false, "source.c", name, source, expected_lines);
1661 tc.stage2 = true;
1662 self.addCase(tc);
1663 }
1664
16651654 pub fn addAllowWarnings(
16661655 self: *TranslateCContext,
16671656 name: []const u8,
test/translate_c.zig+128-141
......@@ -3,10 +3,9 @@ const builtin = @import("builtin");
33
44// add_both - test for stage1 and stage2, in #include mode
55// add - test stage1 only, in #include mode
6// add_2 - test stage2 only, in #include mode
6// add_2 - test stage2 only
77// addC_both - test for stage1 and stage2, in -c mode
88// addC - test stage1 only, in -c mode
9// addC_2 - test stage2 only, in -c mode
109
1110pub fn addCases(cases: *tests.TranslateCContext) void {
1211 /////////////// Cases that pass for both stage1/stage2 ////////////////
......@@ -18,7 +17,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1817 \\pub extern fn bar() c_int;
1918 });
2019
21 cases.add_both("simple var decls",
20 cases.addC_both("simple var decls",
2221 \\void foo(void) {
2322 \\ int a;
2423 \\ char b = 123;
......@@ -26,7 +25,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2625 \\ const unsigned d = 440;
2726 \\}
2827 , &[_][]const u8{
29 \\pub fn foo() void {
28 \\pub export fn foo() void {
3029 \\ var a: c_int = undefined;
3130 \\ var b: u8 = @as(u8, 123);
3231 \\ const c: c_int = undefined;
......@@ -34,7 +33,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3433 \\}
3534 });
3635
37 cases.add_both("ignore result, explicit function arguments",
36 cases.addC_both("ignore result, explicit function arguments",
3837 \\void foo(void) {
3938 \\ int a;
4039 \\ 1;
......@@ -44,7 +43,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
4443 \\ a = 1;
4544 \\}
4645 , &[_][]const u8{
47 \\pub fn foo() void {
46 \\pub export fn foo() void {
4847 \\ var a: c_int = undefined;
4948 \\ _ = 1;
5049 \\ _ = "hey";
......@@ -54,42 +53,139 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
5453 \\}
5554 });
5655
56 cases.addC_both("variables",
57 \\extern int extern_var;
58 \\static const int int_var = 13;
59 , &[_][]const u8{
60 \\pub extern var extern_var: c_int;
61 ,
62 \\pub const int_var: c_int = 13;
63 });
64
65 cases.add_both("const ptr initializer",
66 \\static const char *v0 = "0.0.0";
67 , &[_][]const u8{
68 \\pub var v0: [*c]const u8 = "0.0.0";
69 });
70
71 cases.addC_both("static incomplete array inside function",
72 \\void foo(void) {
73 \\ static const char v2[] = "2.2.2";
74 \\}
75 , &[_][]const u8{
76 \\pub export fn foo() void {
77 \\ const v2: [*c]const u8 = "2.2.2";
78 \\}
79 });
80
81 cases.addC_both("simple function definition",
82 \\void foo(void) {}
83 \\static void bar(void) {}
84 , &[_][]const u8{
85 \\pub export fn foo() void {}
86 \\pub fn bar() void {}
87 });
88
89 cases.add_both("typedef void",
90 \\typedef void Foo;
91 \\Foo fun(Foo *a);
92 , &[_][]const u8{
93 \\pub const Foo = c_void;
94 ,
95 \\pub extern fn fun(a: ?*Foo) Foo;
96 });
97
98 cases.add_both("duplicate typedef",
99 \\typedef long foo;
100 \\typedef int bar;
101 \\typedef long foo;
102 \\typedef int baz;
103 , &[_][]const u8{
104 \\pub const foo = c_long;
105 \\pub const bar = c_int;
106 \\pub const baz = c_int;
107 });
108
109 cases.addC_both("casting pointers to ints and ints to pointers",
110 \\void foo(void);
111 \\void bar(void) {
112 \\ void *func_ptr = foo;
113 \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
114 \\}
115 , &[_][]const u8{
116 \\pub extern fn foo() void;
117 \\pub export fn bar() void {
118 \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
119 \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr)));
120 \\}
121 });
122
123 cases.add_both("noreturn attribute",
124 \\void foo(void) __attribute__((noreturn));
125 , &[_][]const u8{
126 \\pub extern fn foo() noreturn;
127 });
128
129 cases.addC_both("add, sub, mul, div, rem",
130 \\int s(int a, int b) {
131 \\ int c;
132 \\ c = a + b;
133 \\ c = a - b;
134 \\ c = a * b;
135 \\ c = a / b;
136 \\ c = a % b;
137 \\}
138 \\unsigned u(unsigned a, unsigned b) {
139 \\ unsigned c;
140 \\ c = a + b;
141 \\ c = a - b;
142 \\ c = a * b;
143 \\ c = a / b;
144 \\ c = a % b;
145 \\}
146 , &[_][]const u8{
147 \\pub export fn s(a: c_int, b: c_int) c_int {
148 \\ var c: c_int = undefined;
149 \\ c = (a + b);
150 \\ c = (a - b);
151 \\ c = (a * b);
152 \\ c = @divTrunc(a, b);
153 \\ c = @rem(a, b);
154 \\}
155 \\pub export fn u(a: c_uint, b: c_uint) c_uint {
156 \\ var c: c_uint = undefined;
157 \\ c = (a +% b);
158 \\ c = (a -% b);
159 \\ c = (a *% b);
160 \\ c = (a / b);
161 \\ c = (a % b);
162 \\}
163 });
164
57165 /////////////// Cases that pass for only stage2 ////////////////
58 // TODO: restore these tests after removing "import mode" concept
59 // https://github.com/ziglang/zig/issues/2780
60
61 // cases.add_2("Parameterless function prototypes",
62 // \\void a() {}
63 // \\void b(void) {}
64 // \\void c();
65 // \\void d(void);
66 // ,
67 // \\pub export fn a() void {}
68 // \\pub export fn b() void {}
69 // \\pub extern fn c(...) void;
70 // \\pub extern fn d() void;
71 // );
72
73 // cases.add_2("simple function definition",
74 // \\void foo(void) {}
75 // \\static void bar(void) {}
76 // ,
77 // \\pub export fn foo() void {}
78 // \\pub extern fn bar() void {}
79 // );
80
81 cases.add_2("parameterless function prototypes",
166
167 cases.add_2("Parameterless function prototypes",
82168 \\void a() {}
83169 \\void b(void) {}
84170 \\void c();
85171 \\void d(void);
86172 , &[_][]const u8{
87 \\pub fn a(...) void {}
88 \\pub fn b() void {}
173 \\pub export fn a() void {}
174 \\pub export fn b() void {}
89175 \\pub extern fn c(...) void;
90176 \\pub extern fn d() void;
91177 });
92178
179 cases.add_2("variable declarations",
180 \\extern char arr0[] = "hello";
181 \\static char arr1[] = "hello";
182 \\char arr2[] = "hello";
183 , &[_][]const u8{
184 \\pub extern var arr0: [*c]u8 = "hello";
185 \\pub var arr1: [*c]u8 = "hello";
186 \\pub export var arr2: [*c]u8 = "hello";
187 });
188
93189 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
94190
95191 cases.add("typedef of function in struct field",
......@@ -120,34 +216,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
120216 \\};
121217 });
122218
123 cases.add_both("simple function definition",
124 \\void foo(void) {}
125 \\static void bar(void) {}
126 , &[_][]const u8{
127 \\pub fn foo() void {}
128 \\pub fn bar() void {}
129 });
130
131219 cases.add("macro with left shift",
132220 \\#define REDISMODULE_READ (1<<0)
133221 , &[_][]const u8{
134222 \\pub const REDISMODULE_READ = 1 << 0;
135223 });
136224
137 cases.add_both("casting pointers to ints and ints to pointers",
138 \\void foo(void);
139 \\void bar(void) {
140 \\ void *func_ptr = foo;
141 \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
142 \\}
143 , &[_][]const u8{
144 \\pub extern fn foo() void;
145 \\pub fn bar() void {
146 \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
147 \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr)));
148 \\}
149 });
150
151225 if (builtin.os != builtin.Os.windows) {
152226 // Windows treats this as an enum with type c_int
153227 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 {
320394 \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
321395 });
322396
323 cases.add_both("noreturn attribute",
324 \\void foo(void) __attribute__((noreturn));
325 , &[_][]const u8{
326 \\pub extern fn foo() noreturn;
327 });
328
329397 cases.addC("simple function",
330398 \\int abs(int a) {
331399 \\ return a < 0 ? -a : a;
......@@ -482,15 +550,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
482550 \\pub const THING2 = THING1;
483551 });
484552
485 cases.add("variables",
486 \\extern int extern_var;
487 \\static const int int_var = 13;
488 , &[_][]const u8{
489 \\pub extern var extern_var: c_int;
490 ,
491 \\pub const int_var: c_int = 13;
492 });
493
494553 cases.add("circular struct definitions",
495554 \\struct Bar;
496555 \\
......@@ -511,15 +570,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
511570 \\};
512571 });
513572
514 cases.add("typedef void",
515 \\typedef void Foo;
516 \\Foo fun(Foo *a);
517 , &[_][]const u8{
518 \\pub const Foo = c_void;
519 ,
520 \\pub extern fn fun(a: ?*Foo) Foo;
521 });
522
523573 cases.add("generate inline func for #define global extern fn",
524574 \\extern void (*fn_ptr)(void);
525575 \\#define foo fn_ptr
......@@ -719,42 +769,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
719769 \\}
720770 });
721771
722 cases.addC_both("add, sub, mul, div, rem",
723 \\int s(int a, int b) {
724 \\ int c;
725 \\ c = a + b;
726 \\ c = a - b;
727 \\ c = a * b;
728 \\ c = a / b;
729 \\ c = a % b;
730 \\}
731 \\unsigned u(unsigned a, unsigned b) {
732 \\ unsigned c;
733 \\ c = a + b;
734 \\ c = a - b;
735 \\ c = a * b;
736 \\ c = a / b;
737 \\ c = a % b;
738 \\}
739 , &[_][]const u8{
740 \\pub export fn s(a: c_int, b: c_int) c_int {
741 \\ var c: c_int = undefined;
742 \\ c = (a + b);
743 \\ c = (a - b);
744 \\ c = (a * b);
745 \\ c = @divTrunc(a, b);
746 \\ c = @rem(a, b);
747 \\}
748 \\pub export fn u(a: c_uint, b: c_uint) c_uint {
749 \\ var c: c_uint = undefined;
750 \\ c = (a +% b);
751 \\ c = (a -% b);
752 \\ c = (a *% b);
753 \\ c = (a / b);
754 \\ c = (a % b);
755 \\}
756 });
757
758772 cases.addC("bitwise binary operators",
759773 \\int max(int a, int b) {
760774 \\ return (a & b) ^ (a | b);
......@@ -1147,17 +1161,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11471161 \\}
11481162 });
11491163
1150 cases.addC("duplicate typedef",
1151 \\typedef long foo;
1152 \\typedef int bar;
1153 \\typedef long foo;
1154 \\typedef int baz;
1155 , &[_][]const u8{
1156 \\pub const foo = c_long;
1157 \\pub const bar = c_int;
1158 \\pub const baz = c_int;
1159 });
1160
11611164 cases.addC("post increment/decrement",
11621165 \\void foo(void) {
11631166 \\ int i = 0;
......@@ -1520,22 +1523,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15201523 \\}
15211524 });
15221525
1523 cases.add("const ptr initializer",
1524 \\static const char *v0 = "0.0.0";
1525 , &[_][]const u8{
1526 \\pub var v0: [*c]const u8 = "0.0.0";
1527 });
1528
1529 cases.add("static incomplete array inside function",
1530 \\void foo(void) {
1531 \\ static const char v2[] = "2.2.2";
1532 \\}
1533 , &[_][]const u8{
1534 \\pub fn foo() void {
1535 \\ const v2: [*c]const u8 = "2.2.2";
1536 \\}
1537 });
1538
15391526 cases.add("macro pointer cast",
15401527 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
15411528 , &[_][]const u8{