mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
translate-c: support brace-enclosed string initializers (c++20 9.4.2.1)
This commit is contained in:
parent
bc8e1e1de4
commit
42ee364e7b
@ -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;
|
||||
|
||||
|
||||
@ -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 => {},
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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";
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user