Merge pull request #4326 from LemonBoy/fix-4181

Generate compilable code for array inits
This commit is contained in:
Andrew Kelley 2020-01-30 16:12:23 -05:00 committed by GitHub
commit 13f7824266
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 14 deletions

View File

@ -1991,6 +1991,29 @@ fn transInitListExprRecord(
return &init_node.base;
}
fn transCreateNodeArrayType(
rp: RestorePoint,
source_loc: ZigClangSourceLocation,
ty: *const ZigClangType,
len: var,
) TransError!*ast.Node {
var node = try transCreateNodePrefixOp(
rp.c,
.{
.ArrayType = .{
.len_expr = undefined,
.sentinel = null,
},
},
.LBracket,
"[",
);
node.op.ArrayType.len_expr = try transCreateNodeInt(rp.c, len);
_ = try appendToken(rp.c, .RBracket, "]");
node.rhs = try transType(rp, ty, source_loc);
return &node.base;
}
fn transInitListExprArray(
rp: RestorePoint,
scope: *Scope,
@ -2011,8 +2034,13 @@ fn transInitListExprArray(
var init_node: *ast.Node.SuffixOp = undefined;
var cat_tok: ast.TokenIndex = undefined;
if (init_count != 0) {
const dot_tok = try appendToken(rp.c, .Period, ".");
init_node = try transCreateNodeContainerInitializer(rp.c, dot_tok);
const ty_node = try transCreateNodeArrayType(
rp,
loc,
ZigClangQualType_getTypePtr(child_qt),
init_count,
);
init_node = try transCreateNodeArrayInitializer(rp.c, ty_node);
var i: c_uint = 0;
while (i < init_count) : (i += 1) {
const elem_expr = ZigClangInitListExpr_getInit(expr, i);
@ -2026,8 +2054,8 @@ fn transInitListExprArray(
cat_tok = try appendToken(rp.c, .PlusPlus, "++");
}
const dot_tok = try appendToken(rp.c, .Period, ".");
var filler_init_node = try transCreateNodeContainerInitializer(rp.c, dot_tok);
const ty_node = try transCreateNodeArrayType(rp, loc, ZigClangQualType_getTypePtr(child_qt), 1);
var filler_init_node = try transCreateNodeArrayInitializer(rp.c, ty_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));
filler_init_node.rtoken = try appendToken(rp.c, .RBrace, "}");
@ -3878,11 +3906,11 @@ fn transCreateNodeBoolLiteral(c: *Context, value: bool) !*ast.Node {
return &node.base;
}
fn transCreateNodeContainerInitializer(c: *Context, dot_tok: ast.TokenIndex) !*ast.Node.SuffixOp {
fn transCreateNodeArrayInitializer(c: *Context, ty: *ast.Node) !*ast.Node.SuffixOp {
_ = try appendToken(c, .LBrace, "{");
const node = try c.a().create(ast.Node.SuffixOp);
node.* = ast.Node.SuffixOp{
.lhs = .{ .dot = dot_tok },
.lhs = .{ .node = ty },
.op = .{
.ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(c.a()),
},

View File

@ -3,6 +3,22 @@ const tests = @import("tests.zig");
const nl = std.cstr.line_sep;
pub fn addCases(cases: *tests.RunTranslatedCContext) void {
cases.add("array initializer",
\\#include <stdlib.h>
\\int main(int argc, char **argv) {
\\ int a0[4] = {1};
\\ int a1[4] = {1,2,3,4};
\\ int s0 = 0, s1 = 0;
\\ for (int i = 0; i < 4; i++) {
\\ s0 += a0[i];
\\ s1 += a1[i];
\\ }
\\ if (s0 != 1) abort();
\\ if (s1 != 10) abort();
\\ return 0;
\\}
, "");
cases.add("forward declarations",
\\#include <stdlib.h>
\\int foo(int);

View File

@ -18,7 +18,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\static const uuid_t UUID_NULL __attribute__ ((unused)) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
, &[_][]const u8{
\\pub const uuid_t = [16]u8;
\\pub const UUID_NULL: uuid_t = .{
\\pub const UUID_NULL: uuid_t = [16]u8{
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
@ -87,7 +87,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ .x = @as(c_int, 1),
\\};
\\pub export var ub: union_unnamed_1 = union_unnamed_1{
\\ .c = .{
\\ .c = [4]u8{
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
@ -1118,12 +1118,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
, &[_][]const u8{
\\pub fn foo() callconv(.C) void {
\\ var arr: [10]u8 = .{
\\ var arr: [10]u8 = [1]u8{
\\ @bitCast(u8, @truncate(i8, @as(c_int, 1))),
\\ } ++ .{0} ** 9;
\\ var arr1: [10][*c]u8 = .{
\\ } ++ [1]u8{0} ** 9;
\\ var arr1: [10][*c]u8 = [1][*c]u8{
\\ null,
\\ } ++ .{null} ** 9;
\\ } ++ [1][*c]u8{null} ** 9;
\\}
});
@ -1570,7 +1570,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("undefined array global",
\\int array[100] = {};
, &[_][]const u8{
\\pub export var array: [100]c_int = .{0} ** 100;
\\pub export var array: [100]c_int = [1]c_int{0} ** 100;
});
cases.add("restrict -> noalias",
@ -1904,7 +1904,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return array[index];
\\}
, &[_][]const u8{
\\pub export var array: [100]c_int = .{0} ** 100;
\\pub export var array: [100]c_int = [1]c_int{0} ** 100;
\\pub export fn foo(arg_index: c_int) c_int {
\\ var index = arg_index;
\\ return array[@intCast(c_uint, index)];