Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion analyser/module_analyser_expr.c2
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,36 @@ fn QualType Analyser.analyseExplicitCast(Analyser* ma, Expr** e_ptr) {
TypeRef* ref = c.getTypeRef();
QualType destType = ma.analyseTypeRef(ref);

Expr* inner = c.getInner();
if (inner.isInitList()) {
InitListExpr* initList = cast<InitListExpr*>(inner);
if (destType.isInvalid())
return QualType_Invalid;
if (destType.isArray() || destType.isStruct()) {
if (!ma.analyseInitListExpr(initList, destType))
return QualType_Invalid;
} else {
u32 num_values = initList.getNumValues();
Expr** values = initList.getValues();
if (num_values != 1 || values[0].isInitList()) {
ma.error(inner.getLoc(), "invalid initializer");
return QualType_Invalid;
}
if (!ma.analyseInitExpr(&values[0], destType, values[0].getLoc(), false, false))
return QualType_Invalid;
}
e.setLValue();
c.setDestType(destType);
return destType;
}
QualType srcType = ma.analyseExpr(c.getInner2(), true, RHS);

if (srcType.isInvalid() || destType.isInvalid()) return QualType_Invalid;

Expr* inner = c.getInner();
inner = c.getInner();
e.copyConstantFlags(inner);
// TODO: this is probably incorrect: valType should be LValue for reinterpret
// casts and RValue for conversion casts
e.copyValType(inner);
c.setDestType(destType);

Expand Down
1 change: 1 addition & 0 deletions ast/explicit_cast_expr.c2
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public fn ExplicitCastExpr* ExplicitCastExpr.create(ast_context.Context* c,
{
u32 size = sizeof(ExplicitCastExpr) + ref.getExtraSize();
ExplicitCastExpr* e = c.alloc(size);
// TODO ValType.LValue for compound
e.base.init(ExprKind.ExplicitCast, loc, 0, 0, 0, ValType.NValue);
e.base.base.explicitCastExprBits.c_style = c_style;
e.base.base.explicitCastExprBits.src_len = src_len;
Expand Down
2 changes: 1 addition & 1 deletion ast/expr.c2
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ static_assert(elemsof(ExprKind), elemsof(exprKind_names));

/*
An LValue may be on the left/right side of an assignment
An RValue may only be on the left side
An RValue may only be on the right side
An NValue is an abstract object (cannot be used on either side)

Lvalue:
Expand Down
4 changes: 2 additions & 2 deletions generator/c/c_generator_expr.c2
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ fn void Generator.emitExpr2(Generator* gen, string_buffer.Buf* out, Expr* e, C_P
case ExplicitCast:
ExplicitCastExpr* c = (ExplicitCastExpr*)e;
if (prec > Prefix) out.lparen();
gen.emitCast(out, c.getDestType(), false);
gen.emitCast(out, c.getDestType(), true);
if (c.getCStyle()) {
gen.emitExpr2(out, c.getInner(), Prefix);
} else {
Expand All @@ -163,7 +163,7 @@ fn void Generator.emitExpr2(Generator* gen, string_buffer.Buf* out, Expr* e, C_P
out.add(" ... ");
gen.emitExpr(out, b.getRHS());
if (prec > Assignment) out.rparen();
return;
break;
case NamedArgument:
NamedArgument* n = (NamedArgument*)e;
gen.emitExpr(out, n.getInner());
Expand Down
4 changes: 4 additions & 0 deletions generator/ir/ir_generator_expr.c2
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ fn void Generator.emitExpr(Generator* gen, ir.Ref* result, const Expr* e) {
break;
case ExplicitCast:
ExplicitCastExpr* ec = (ExplicitCastExpr*)e;
if (ec.getInner().isInitList()) {
assert(0); // TODO
break;
}
gen.emitExpr(result, ec.getInner());
break;
case ImplicitCast:
Expand Down
11 changes: 6 additions & 5 deletions parser/c2_parser_expr.c2
Original file line number Diff line number Diff line change
Expand Up @@ -532,16 +532,17 @@ fn Expr* Parser.parseParenExpr(Parser* p) {
TypeRefHolder ref.init();
p.parseTypeSpecifier(&ref);
p.expectAndConsume(Kind.RParen);
Expr* expr;
if (p.tok.kind == Kind.LBrace) {
// compound literal
p.error("Compound literals are not supported");
expr = p.parseInitList();
} else {
// C cast expression
if (ref.isArray()) p.error("array types are not allowed here");
Expr* expr = p.parseCastExpr(false, false);
u32 src_len = p.prev_loc - loc;
return p.builder.actOnExplicitCast(loc, src_len, &ref, expr, true);
if (ref.isArray()) p.error("cast to array type is invalid");
expr = p.parseCastExpr(false, false);
}
u32 src_len = p.prev_loc - loc;
return p.builder.actOnExplicitCast(loc, src_len, &ref, expr, true);
}

Expr* res = p.parseExpr();
Expand Down
2 changes: 1 addition & 1 deletion test/expr/explicit_cast/explicit_c_cast_array.c2
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
module test;

fn void test1a(i32 a) {
char[2] b1 = (char[2])(a); // @error{array types are not allowed here}
char[2] b1 = (char[2])(a); // @error{cast to array type is invalid}
}

2 changes: 1 addition & 1 deletion test/expr/explicit_cast/explicit_cast_array.c2
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
module test;

fn void test1(i32 a) {
char[2] b = (char[2])a; // @error{array types are not allowed here}
char[2] b = (char[2])a; // @error{cast to array type is invalid}
}

56 changes: 56 additions & 0 deletions test/literals/compound_literals.c2
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// @warnings{no-unused}
module test;

import stdio local;

type Foo struct {
i32 x;
i32 y;
}

fn void test_foo(Foo foo) {}
fn void Foo.bar(Foo* foo) {}
fn Foo Foo.create(i32 x, i32 y) { return (Foo){ x, y }; }

fn i32 sum(i32 *p, u32 count) {
i32 total = 0;
for (i32 i = 0; i < count; i++) total += p[i];
return total;
}

public fn i32 main() {
Foo[] foos = {
{ },
{ 0, 1 },
(Foo){ 1, 2 },
(Foo){ .x = 2, .y = 3 },
[4] = { },
[5] = { 3, 4 },
[6] = (Foo){ 4, 5 },
[7] = (Foo){ .x = 5, .y = 6 },
}

test_foo({});
test_foo({ 1, 2 });
test_foo({ .x = 1, .y = 2 });
test_foo((Foo){});
test_foo((Foo){ 1, 2 });
test_foo((Foo){ .x = 1, .y = 2 });

foos[0].bar();
(Foo){1, 2}.bar();

printf("%d\n", sum((i32[]){ 1 }, 1));
printf("%d\n", sum((i32[]){ 1, 2 }, 2));
printf("%d\n", sum((i32[]){ 1, 2, 3 }, 3));
printf("%d\n", sum((i32[1]){ 1 }, 1));
printf("%d\n", sum((i32[2]){ 1, 2 }, 2));
printf("%d\n", sum((i32[10]){ 1, 2, 3 }, 10));

// Enable these tests once arrays are implied for pointer arguments
//printf("%d\n", sum({ 1 }, 1));
//printf("%d\n", sum({ 1, 2 }, 2));
//printf("%d\n", sum({ 1, 2, 3 }, 3));

return 0;
}