authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-04-22 02:11:16-04:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-04-23 21:45:08+03:00
log42ee364e7b698822a69cba4cd2bda17868657e05
tree4a69da6479fb97502dc83794e5d745e1fe3eb053
parentbc8e1e1de4a2f22c56528240d320f682f1ec4b69

translate-c: support brace-enclosed string initializers (c++20 9.4.2.1)


5 files changed, 61 insertions(+), 8 deletions(-)

src/clang.zig+9
......@@ -460,6 +460,9 @@ pub const Expr = opaque {
460460
461461 pub const evaluateAsConstantExpr = ZigClangExpr_EvaluateAsConstantExpr;
462462 extern fn ZigClangExpr_EvaluateAsConstantExpr(*const Expr, *ExprEvalResult, Expr_ConstantExprKind, *const ASTContext) bool;
463
464 pub const castToStringLiteral = ZigClangExpr_castToStringLiteral;
465 extern fn ZigClangExpr_castToStringLiteral(*const Expr) ?*const StringLiteral;
463466};
464467
465468pub const FieldDecl = opaque {
......@@ -1053,6 +1056,12 @@ pub const InitListExpr = opaque {
10531056 pub const getArrayFiller = ZigClangInitListExpr_getArrayFiller;
10541057 extern fn ZigClangInitListExpr_getArrayFiller(*const InitListExpr) *const Expr;
10551058
1059 pub const hasArrayFiller = ZigClangInitListExpr_hasArrayFiller;
1060 extern fn ZigClangInitListExpr_hasArrayFiller(*const InitListExpr) bool;
1061
1062 pub const isStringLiteralInit = ZigClangInitListExpr_isStringLiteralInit;
1063 extern fn ZigClangInitListExpr_isStringLiteralInit(*const InitListExpr) bool;
1064
10561065 pub const getNumInits = ZigClangInitListExpr_getNumInits;
10571066 extern fn ZigClangInitListExpr_getNumInits(*const InitListExpr) c_uint;
10581067
src/translate_c.zig+27-8
......@@ -2697,6 +2697,13 @@ fn transInitListExprArray(
26972697 return Tag.empty_array.create(c.arena, child_type);
26982698 }
26992699
2700 if (expr.isStringLiteralInit()) {
2701 assert(init_count == 1);
2702 const init_expr = expr.getInit(0);
2703 const string_literal = init_expr.castToStringLiteral().?;
2704 return try transStringLiteral(c, scope, string_literal, .used);
2705 }
2706
27002707 const init_node = if (init_count != 0) blk: {
27012708 const init_list = try c.arena.alloc(Node, init_count);
27022709
......@@ -2714,6 +2721,7 @@ fn transInitListExprArray(
27142721 break :blk init_node;
27152722 } else null;
27162723
2724 assert(expr.hasArrayFiller());
27172725 const filler_val_expr = expr.getArrayFiller();
27182726 const filler_node = try Tag.array_filler.create(c.arena, .{
27192727 .type = child_type,
......@@ -4176,6 +4184,17 @@ fn addTopLevelDecl(c: *Context, name: []const u8, decl_node: Node) !void {
41764184 try c.global_scope.nodes.append(decl_node);
41774185}
41784186
4187fn transQualTypeInitializedStringLiteral(c: *Context, elem_ty: Node, string_lit: *const clang.StringLiteral) TypeError!Node {
4188 const string_lit_size = string_lit.getLength();
4189 const array_size = @intCast(usize, string_lit_size);
4190
4191 // incomplete array initialized with empty string, will be translated as [1]T{0}
4192 // see https://github.com/ziglang/zig/issues/8256
4193 if (array_size == 0) return Tag.array_type.create(c.arena, .{ .len = 1, .elem_type = elem_ty });
4194
4195 return Tag.null_sentinel_array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty });
4196}
4197
41794198/// Translate a qualtype for a variable with an initializer. This only matters
41804199/// for incomplete arrays, since the initializer determines the size of the array.
41814200fn transQualTypeInitialized(
......@@ -4193,18 +4212,18 @@ fn transQualTypeInitialized(
41934212 switch (decl_init.getStmtClass()) {
41944213 .StringLiteralClass => {
41954214 const string_lit = @ptrCast(*const clang.StringLiteral, decl_init);
4196 const string_lit_size = string_lit.getLength();
4197 const array_size = @intCast(usize, string_lit_size);
4198
4199 // incomplete array initialized with empty string, will be translated as [1]T{0}
4200 // see https://github.com/ziglang/zig/issues/8256
4201 if (array_size == 0) return Tag.array_type.create(c.arena, .{ .len = 1, .elem_type = elem_ty });
4202
4203 return Tag.null_sentinel_array_type.create(c.arena, .{ .len = array_size, .elem_type = elem_ty });
4215 return transQualTypeInitializedStringLiteral(c, elem_ty, string_lit);
42044216 },
42054217 .InitListExprClass => {
42064218 const init_expr = @ptrCast(*const clang.InitListExpr, decl_init);
42074219 const size = init_expr.getNumInits();
4220
4221 if (init_expr.isStringLiteralInit()) {
4222 assert(size == 1);
4223 const string_lit = init_expr.getInit(0).castToStringLiteral().?;
4224 return transQualTypeInitializedStringLiteral(c, elem_ty, string_lit);
4225 }
4226
42084227 return Tag.array_type.create(c.arena, .{ .len = size, .elem_type = elem_ty });
42094228 },
42104229 else => {},
src/zig_clang.cpp+16
......@@ -2382,6 +2382,12 @@ bool ZigClangExpr_EvaluateAsConstantExpr(const ZigClangExpr *self, ZigClangExprE
23822382 return true;
23832383}
23842384
2385const ZigClangStringLiteral *ZigClangExpr_castToStringLiteral(const struct ZigClangExpr *self) {
2386 auto casted_self = reinterpret_cast<const clang::Expr *>(self);
2387 auto cast = clang::dyn_cast<const clang::StringLiteral>(casted_self);
2388 return reinterpret_cast<const ZigClangStringLiteral *>(cast);
2389}
2390
23852391const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *self, unsigned i) {
23862392 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
23872393 const clang::Expr *result = casted->getInit(i);
......@@ -2394,6 +2400,16 @@ const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListEx
23942400 return reinterpret_cast<const ZigClangExpr *>(result);
23952401}
23962402
2403bool ZigClangInitListExpr_hasArrayFiller(const ZigClangInitListExpr *self) {
2404 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
2405 return casted->hasArrayFiller();
2406}
2407
2408bool ZigClangInitListExpr_isStringLiteralInit(const ZigClangInitListExpr *self) {
2409 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
2410 return casted->isStringLiteralInit();
2411}
2412
23972413const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self) {
23982414 auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
23992415 const clang::FieldDecl *result = casted->getInitializedFieldInUnion();
src/zig_clang.h+3
......@@ -1220,9 +1220,12 @@ ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsFloat(const struct ZigClangExpr *self,
12201220 ZigClangAPFloat **result, const struct ZigClangASTContext *ctx);
12211221ZIG_EXTERN_C bool ZigClangExpr_EvaluateAsConstantExpr(const struct ZigClangExpr *,
12221222 struct ZigClangExprEvalResult *, ZigClangExpr_ConstantExprKind, const struct ZigClangASTContext *);
1223ZIG_EXTERN_C const struct ZigClangStringLiteral *ZigClangExpr_castToStringLiteral(const struct ZigClangExpr *self);
12231224
12241225ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *, unsigned);
12251226ZIG_EXTERN_C const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListExpr *);
1227ZIG_EXTERN_C bool ZigClangInitListExpr_hasArrayFiller(const ZigClangInitListExpr *);
1228ZIG_EXTERN_C bool ZigClangInitListExpr_isStringLiteralInit(const ZigClangInitListExpr *);
12261229ZIG_EXTERN_C unsigned ZigClangInitListExpr_getNumInits(const ZigClangInitListExpr *);
12271230ZIG_EXTERN_C const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self);
12281231
test/translate_c.zig+6
......@@ -3956,4 +3956,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
39563956 \\ .name = "foo",
39573957 \\});
39583958 });
3959
3960 cases.add("string array initializer",
3961 \\static const char foo[] = {"bar"};
3962 , &[_][]const u8{
3963 \\pub const foo: [3:0]u8 = "bar";
3964 });
39593965}