diff --git a/src/clang.zig b/src/clang.zig index 04261f06f0..f368bb0c3c 100644 --- a/src/clang.zig +++ b/src/clang.zig @@ -460,6 +460,9 @@ pub const Expr = opaque { pub const evaluateAsConstantExpr = ZigClangExpr_EvaluateAsConstantExpr; extern fn ZigClangExpr_EvaluateAsConstantExpr(*const Expr, *ExprEvalResult, Expr_ConstantExprKind, *const ASTContext) bool; + + pub const castToStringLiteral = ZigClangExpr_castToStringLiteral; + extern fn ZigClangExpr_castToStringLiteral(*const Expr) ?*const StringLiteral; }; pub const FieldDecl = opaque { @@ -1053,6 +1056,12 @@ pub const InitListExpr = opaque { pub const getArrayFiller = ZigClangInitListExpr_getArrayFiller; extern fn ZigClangInitListExpr_getArrayFiller(*const InitListExpr) *const Expr; + pub const hasArrayFiller = ZigClangInitListExpr_hasArrayFiller; + extern fn ZigClangInitListExpr_hasArrayFiller(*const InitListExpr) bool; + + pub const isStringLiteralInit = ZigClangInitListExpr_isStringLiteralInit; + extern fn ZigClangInitListExpr_isStringLiteralInit(*const InitListExpr) bool; + pub const getNumInits = ZigClangInitListExpr_getNumInits; extern fn ZigClangInitListExpr_getNumInits(*const InitListExpr) c_uint; diff --git a/src/translate_c.zig b/src/translate_c.zig index 45b9f38b75..9d8dcd80b9 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -2697,6 +2697,13 @@ fn transInitListExprArray( return Tag.empty_array.create(c.arena, child_type); } + if (expr.isStringLiteralInit()) { + assert(init_count == 1); + const init_expr = expr.getInit(0); + const string_literal = init_expr.castToStringLiteral().?; + return try transStringLiteral(c, scope, string_literal, .used); + } + const init_node = if (init_count != 0) blk: { const init_list = try c.arena.alloc(Node, init_count); @@ -2714,6 +2721,7 @@ fn transInitListExprArray( break :blk init_node; } else null; + assert(expr.hasArrayFiller()); const filler_val_expr = expr.getArrayFiller(); const filler_node = try Tag.array_filler.create(c.arena, .{ .type = child_type, @@ -4176,6 +4184,17 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void { try c.global_scope.nodes.append(decl_node); } +fn transQualTypeInitializedStringLiteral(c: *Context, elem_ty: Node, string_lit: *const clang.StringLiteral) TypeError!Node { + const string_lit_size = string_lit.getLength(); + const array_size = @intCast(usize, string_lit_size); + + // incomplete array initialized with empty string, will be translated as [1]T{0} + // see https://github.com/ziglang/zig/issues/8256 + if (array_size == 0) return Tag.array_type.create(c.arena, .{ .len = 1, .elem_type = elem_ty }); + + return Tag.null_sentinel_array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty }); +} + /// Translate a qualtype for a variable with an initializer. This only matters /// for incomplete arrays, since the initializer determines the size of the array. fn transQualTypeInitialized( @@ -4193,18 +4212,18 @@ fn transQualTypeInitialized( switch (decl_init.getStmtClass()) { .StringLiteralClass => { const string_lit = @ptrCast(*const clang.StringLiteral, decl_init); - const string_lit_size = string_lit.getLength(); - const array_size = @intCast(usize, string_lit_size); - - // incomplete array initialized with empty string, will be translated as [1]T{0} - // see https://github.com/ziglang/zig/issues/8256 - if (array_size == 0) return Tag.array_type.create(c.arena, .{ .len = 1, .elem_type = elem_ty }); - - return Tag.null_sentinel_array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty }); + return transQualTypeInitializedStringLiteral(c, elem_ty, string_lit); }, .InitListExprClass => { const init_expr = @ptrCast(*const clang.InitListExpr, decl_init); const size = init_expr.getNumInits(); + + if (init_expr.isStringLiteralInit()) { + assert(size == 1); + const string_lit = init_expr.getInit(0).castToStringLiteral().?; + return transQualTypeInitializedStringLiteral(c, elem_ty, string_lit); + } + return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_ty }); }, else => {}, diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index ccc4453cdf..699431009f 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -2382,6 +2382,12 @@ bool ZigClangExpr_EvaluateAsConstantExpr(const ZigClangExpr *self, ZigClangExprE return true; } +const ZigClangStringLiteral *ZigClangExpr_castToStringLiteral(const struct ZigClangExpr *self) { + auto casted_self = reinterpret_cast(self); + auto cast = clang::dyn_cast(casted_self); + return reinterpret_cast(cast); +} + const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *self, unsigned i) { auto casted = reinterpret_cast(self); const clang::Expr *result = casted->getInit(i); @@ -2394,6 +2400,16 @@ const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListEx return reinterpret_cast(result); } +bool ZigClangInitListExpr_hasArrayFiller(const ZigClangInitListExpr *self) { + auto casted = reinterpret_cast(self); + return casted->hasArrayFiller(); +} + +bool ZigClangInitListExpr_isStringLiteralInit(const ZigClangInitListExpr *self) { + auto casted = reinterpret_cast(self); + return casted->isStringLiteralInit(); +} + const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self) { auto casted = reinterpret_cast(self); const clang::FieldDecl *result = casted->getInitializedFieldInUnion(); diff --git a/src/zig_clang.h b/src/zig_clang.h index 2fd91163f7..6efde35932 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -1220,9 +1220,12 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsFloat(const struct ZigClangExpr *self, ZigClangAPFloat **result, const struct ZigClangASTContext *ctx); ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr *, struct ZigClangExprEvalResult *, ZigClangExpr_ConstantExprKind, const struct ZigClangASTContext *); +ZIG_EXTERN_C const struct ZigClangStringLiteral *ZigClangExpr_castToStringLiteral(const struct ZigClangExpr *self); ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned); ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *); +ZIG_EXTERN_C bool ZigClangInitListExpr_hasArrayFiller(const ZigClangInitListExpr *); +ZIG_EXTERN_C bool ZigClangInitListExpr_isStringLiteralInit(const ZigClangInitListExpr *); ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *); ZIG_EXTERN_C const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self); diff --git a/test/translate_c.zig b/test/translate_c.zig index f4cd374a06..7534226881 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3956,4 +3956,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ .name = "foo", \\}); }); + + cases.add("string array initializer", + \\static const char foo[] = {"bar"}; + , &[_][]const u8{ + \\pub const foo: [3:0]u8 = "bar"; + }); }