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

This commit is contained in:
kcbanner 2023-04-22 02:11:16 -04:00 committed by Veikka Tuominen
parent bc8e1e1de4
commit 42ee364e7b
5 changed files with 61 additions and 8 deletions

View file

@ -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;

View file

@ -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 => {},

View file

@ -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<const clang::Expr *>(self);
auto cast = clang::dyn_cast<const clang::StringLiteral>(casted_self);
return reinterpret_cast<const ZigClangStringLiteral *>(cast);
}
const ZigClangExpr *ZigClangInitListExpr_getInit(const ZigClangInitListExpr *self, unsigned i) {
auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
const clang::Expr *result = casted->getInit(i);
@ -2394,6 +2400,16 @@ const ZigClangExpr *ZigClangInitListExpr_getArrayFiller(const ZigClangInitListEx
return reinterpret_cast<const ZigClangExpr *>(result);
}
bool ZigClangInitListExpr_hasArrayFiller(const ZigClangInitListExpr *self) {
auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
return casted->hasArrayFiller();
}
bool ZigClangInitListExpr_isStringLiteralInit(const ZigClangInitListExpr *self) {
auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
return casted->isStringLiteralInit();
}
const ZigClangFieldDecl *ZigClangInitListExpr_getInitializedFieldInUnion(const ZigClangInitListExpr *self) {
auto casted = reinterpret_cast<const clang::InitListExpr *>(self);
const clang::FieldDecl *result = casted->getInitializedFieldInUnion();

View file

@ -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);

View file

@ -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";
});
}