mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
Support (void)foo for any type.
This commit is contained in:
@@ -79,48 +79,49 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CAST_ANYPTR,
|
||||
CAST_APTSA,
|
||||
CAST_ARRVEC,
|
||||
CAST_BOOLBOOL,
|
||||
CAST_BOOLFP,
|
||||
CAST_BOOLINT,
|
||||
CAST_BOOLVECINT,
|
||||
CAST_BSARRY,
|
||||
CAST_BSINT,
|
||||
CAST_ERROR,
|
||||
CAST_ENUMLOW,
|
||||
CAST_ERBOOL,
|
||||
CAST_EREU,
|
||||
CAST_ERINT,
|
||||
CAST_ERROR,
|
||||
CAST_EUBOOL,
|
||||
CAST_EUER,
|
||||
CAST_EUINT,
|
||||
CAST_EREU,
|
||||
CAST_ERINT,
|
||||
CAST_XIERR,
|
||||
CAST_PTRPTR,
|
||||
CAST_PTRXI,
|
||||
CAST_ARRVEC,
|
||||
CAST_STRPTR,
|
||||
CAST_PTRBOOL,
|
||||
CAST_BOOLINT,
|
||||
CAST_BOOLFP,
|
||||
CAST_BOOLVECINT,
|
||||
CAST_BOOLBOOL,
|
||||
CAST_FPBOOL,
|
||||
CAST_INTBOOL,
|
||||
CAST_INTENUM,
|
||||
CAST_NUMVEC,
|
||||
CAST_FPFP,
|
||||
CAST_FPSI,
|
||||
CAST_FPUI,
|
||||
CAST_SISI,
|
||||
CAST_SIUI,
|
||||
CAST_SIFP,
|
||||
CAST_XIPTR,
|
||||
CAST_UISI,
|
||||
CAST_UIUI,
|
||||
CAST_UIFP,
|
||||
CAST_ENUMLOW,
|
||||
CAST_APTSA,
|
||||
CAST_INTBOOL,
|
||||
CAST_INTENUM,
|
||||
CAST_NUMVEC,
|
||||
CAST_PTRANY,
|
||||
CAST_PTRBOOL,
|
||||
CAST_PTRPTR,
|
||||
CAST_PTRXI,
|
||||
CAST_SABOOL,
|
||||
CAST_SAPTR,
|
||||
CAST_SASA,
|
||||
CAST_SABOOL,
|
||||
CAST_SIFP,
|
||||
CAST_SISI,
|
||||
CAST_SIUI,
|
||||
CAST_STRPTR,
|
||||
CAST_STST,
|
||||
CAST_PTRANY,
|
||||
CAST_ANYPTR,
|
||||
CAST_UIFP,
|
||||
CAST_UISI,
|
||||
CAST_UIUI,
|
||||
CAST_VECARR,
|
||||
CAST_VOID,
|
||||
CAST_XIERR,
|
||||
CAST_XIPTR,
|
||||
} CastKind;
|
||||
|
||||
|
||||
|
||||
@@ -382,6 +382,7 @@ static inline bool expr_cast_is_constant_eval(Expr *expr, ConstantEvalKind eval_
|
||||
case CAST_SAPTR:
|
||||
case CAST_SASA:
|
||||
case CAST_ENUMLOW:
|
||||
case CAST_VOID:
|
||||
return exprid_is_constant_eval(expr->cast_expr.expr, eval_kind);
|
||||
case CAST_PTRANY:
|
||||
if (eval_kind == CONSTANT_EVAL_LOCAL_INIT || eval_kind == CONSTANT_EVAL_CONSTANT_VALUE) return false;
|
||||
|
||||
@@ -1185,6 +1185,31 @@ void llvm_emit_bool_to_intvec_cast(GenContext *c, BEValue *value, Type *to_type,
|
||||
llvm_value_set(value, res, to_type);
|
||||
}
|
||||
|
||||
void llvm_emit_void_cast(GenContext *c, Expr *expr, BEValue *value)
|
||||
{
|
||||
// Simple path
|
||||
if (!IS_OPTIONAL(expr))
|
||||
{
|
||||
llvm_emit_expr_to_rvalue(c, expr);
|
||||
llvm_value_set(value, NULL, type_void);
|
||||
return;
|
||||
}
|
||||
|
||||
PUSH_OPT();
|
||||
LLVMBasicBlockRef after_void = llvm_basic_block_new(c, "end_block");
|
||||
c->opt_var = NULL;
|
||||
c->catch_block = after_void;
|
||||
llvm_emit_expr_to_rvalue(c, expr);
|
||||
llvm_emit_br(c, after_void);
|
||||
// Ensure we are on a branch that is non-empty.
|
||||
if (llvm_emit_check_block_branch(c))
|
||||
{
|
||||
c->current_block = NULL;
|
||||
c->current_block_is_target = false;
|
||||
}
|
||||
POP_OPT();
|
||||
llvm_emit_block(c, after_void);
|
||||
}
|
||||
|
||||
void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *value, Type *to_type, Type *from_type)
|
||||
{
|
||||
@@ -1221,6 +1246,8 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu
|
||||
llvm_value_bitcast(c, value, to_type);
|
||||
llvm_value_rvalue(c, value);
|
||||
return;
|
||||
case CAST_VOID:
|
||||
UNREACHABLE;
|
||||
case CAST_EUINT:
|
||||
case CAST_ERINT:
|
||||
to_type = type_lowering(to_type);
|
||||
@@ -1414,8 +1441,13 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu
|
||||
value->type = to_type;
|
||||
}
|
||||
|
||||
static inline void gencontext_emit_cast_expr(GenContext *context, BEValue *be_value, Expr *expr)
|
||||
static inline void llvm_emit_cast_expr(GenContext *context, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
if (expr->cast_expr.kind == CAST_VOID)
|
||||
{
|
||||
llvm_emit_void_cast(context, exprptr(expr->cast_expr.expr), be_value);
|
||||
return;
|
||||
}
|
||||
llvm_emit_exprid(context, be_value, expr->cast_expr.expr);
|
||||
llvm_emit_cast(context,
|
||||
expr->cast_expr.kind,
|
||||
@@ -6235,7 +6267,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
gencontext_emit_expression_list_expr(c, value, expr);
|
||||
return;
|
||||
case EXPR_CAST:
|
||||
gencontext_emit_cast_expr(c, value, expr);
|
||||
llvm_emit_cast_expr(c, value, expr);
|
||||
return;
|
||||
case EXPR_BITACCESS:
|
||||
llvm_emit_bitaccess(c, value, expr);
|
||||
|
||||
@@ -1465,6 +1465,13 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
|
||||
Type *from_type = expr->type;
|
||||
|
||||
assert(!type_is_optional(to_type) || may_not_be_optional);
|
||||
|
||||
// Allow (void)foo
|
||||
if (is_explicit && to_type == type_void)
|
||||
{
|
||||
return cast(expr, to_type);
|
||||
}
|
||||
|
||||
Type *to = is_explicit ? type_flatten_distinct_optional(to_type) : type_no_optional(to_type)->canonical;
|
||||
|
||||
// Step one, cast from optional.
|
||||
@@ -1978,7 +1985,7 @@ bool cast(Expr *expr, Type *to_type)
|
||||
{
|
||||
if (to_type == type_void)
|
||||
{
|
||||
expr->type = type_void;
|
||||
insert_cast(expr, CAST_VOID, type_void);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.60"
|
||||
#define COMPILER_VERSION "0.4.61"
|
||||
88
test/test_suite/expressions/casts/void_casting.c3
Normal file
88
test/test_suite/expressions/casts/void_casting.c3
Normal file
@@ -0,0 +1,88 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
|
||||
fn void! foo()
|
||||
{}
|
||||
|
||||
fault Abc { AAA }
|
||||
|
||||
macro int! bar()
|
||||
{
|
||||
return Abc.AAA!;
|
||||
}
|
||||
|
||||
fn int! baz()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
fn int main()
|
||||
{
|
||||
int x;
|
||||
int! y;
|
||||
(void)x;
|
||||
(void)y;
|
||||
(void)foo();
|
||||
(void)bar();
|
||||
(void)(bar() + 1);
|
||||
(void)baz();
|
||||
(void)(baz() + 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
%y = alloca i32, align 4
|
||||
%y.f = alloca i64, align 8
|
||||
%retparam = alloca i32, align 4
|
||||
%retparam9 = alloca i32, align 4
|
||||
store i32 0, ptr %x, align 4
|
||||
store i64 0, ptr %y.f, align 8
|
||||
store i32 0, ptr %y, align 4
|
||||
%0 = load i32, ptr %x, align 4
|
||||
%optval = load i64, ptr %y.f, align 8
|
||||
%not_err = icmp eq i64 %optval, 0
|
||||
br i1 %not_err, label %after_check, label %end_block
|
||||
|
||||
after_check: ; preds = %entry
|
||||
%1 = load i32, ptr %y, align 4
|
||||
br label %end_block
|
||||
|
||||
end_block: ; preds = %after_check, %entry
|
||||
%2 = call i64 @test_foo()
|
||||
%not_err1 = icmp eq i64 %2, 0
|
||||
br i1 %not_err1, label %after_check2, label %end_block3
|
||||
|
||||
after_check2: ; preds = %end_block
|
||||
br label %end_block3
|
||||
|
||||
end_block3: ; preds = %after_check2, %end_block
|
||||
br label %end_block4
|
||||
|
||||
end_block4: ; preds = %end_block3
|
||||
br label %end_block5
|
||||
|
||||
end_block5: ; preds = %end_block4
|
||||
%3 = call i64 @test_baz(ptr %retparam)
|
||||
%not_err6 = icmp eq i64 %3, 0
|
||||
br i1 %not_err6, label %after_check7, label %end_block8
|
||||
|
||||
after_check7: ; preds = %end_block5
|
||||
%4 = load i32, ptr %retparam, align 4
|
||||
br label %end_block8
|
||||
|
||||
end_block8: ; preds = %after_check7, %end_block5
|
||||
%5 = call i64 @test_baz(ptr %retparam9)
|
||||
%not_err10 = icmp eq i64 %5, 0
|
||||
br i1 %not_err10, label %after_check11, label %end_block12
|
||||
|
||||
after_check11: ; preds = %end_block8
|
||||
%6 = load i32, ptr %retparam9, align 4
|
||||
%add = add i32 %6, 1
|
||||
br label %end_block12
|
||||
|
||||
end_block12: ; preds = %after_check11, %end_block8
|
||||
ret i32 1
|
||||
}
|
||||
Reference in New Issue
Block a user