mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix of macro defer with bodies.
This commit is contained in:
committed by
Christoffer Lerno
parent
131bf5ed34
commit
34bd5fa6da
@@ -1590,7 +1590,6 @@ extern const char *kw_out;
|
||||
extern const char *kw_inout;
|
||||
extern const char *kw_deprecated;
|
||||
extern const char *kw_distinct;
|
||||
extern const char *kw_ensure;
|
||||
extern const char *kw_inline;
|
||||
extern const char *kw_inf;
|
||||
extern const char *kw_elementat;
|
||||
@@ -1602,10 +1601,8 @@ extern const char *kw_noinline;
|
||||
extern const char *kw_main;
|
||||
extern const char *kw_ordinal;
|
||||
extern const char *kw_pure;
|
||||
extern const char *kw_param;
|
||||
extern const char *kw_ptr;
|
||||
extern const char *kw_values;
|
||||
extern const char *kw_errors;
|
||||
extern const char *kw_return;
|
||||
extern const char *kw_type;
|
||||
extern const char *kw_FILE;
|
||||
|
||||
@@ -1861,11 +1861,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
if (!sema_add_local(¯o_context, param)) goto EXIT_FAIL;
|
||||
}
|
||||
|
||||
AstId current = body->compound_stmt.first_stmt;
|
||||
while (current)
|
||||
{
|
||||
if (!sema_analyse_statement(¯o_context, ast_next(¤t))) goto EXIT_FAIL;
|
||||
}
|
||||
if (!sema_analyse_statement(¯o_context, body)) goto EXIT_FAIL;
|
||||
|
||||
bool is_no_return = decl->macro_decl.attr_noreturn;
|
||||
|
||||
@@ -2072,17 +2068,33 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call)
|
||||
Expr *expr = args[i];
|
||||
if (!sema_analyse_expr(macro_context, expr)) return false;
|
||||
}
|
||||
|
||||
AstId macro_defer = macro_context->active_scope.defer_last;
|
||||
Ast *first_defer = NULL;
|
||||
SemaContext *context = macro_context->yield_context;
|
||||
Decl **params = macro_context->yield_params;
|
||||
|
||||
|
||||
Expr *func_expr = exprptr(call_expr->function);
|
||||
assert(func_expr->expr_kind == EXPR_MACRO_BODY_EXPANSION);
|
||||
expr_replace(call, func_expr);
|
||||
call->body_expansion_expr.values = args;
|
||||
call->body_expansion_expr.declarations = macro_context->yield_params;
|
||||
|
||||
AstId last_defer = context->active_scope.defer_last;
|
||||
bool success;
|
||||
SCOPE_START
|
||||
|
||||
if (macro_defer)
|
||||
{
|
||||
Ast *macro_defer_ast = astptr(macro_defer);
|
||||
first_defer = macro_defer_ast;
|
||||
while (first_defer->defer_stmt.prev_defer)
|
||||
{
|
||||
first_defer = astptr(first_defer->defer_stmt.prev_defer);
|
||||
}
|
||||
first_defer->defer_stmt.prev_defer = context->active_scope.defer_last;
|
||||
context->active_scope.defer_last = macro_defer;
|
||||
}
|
||||
VECEACH(params, i)
|
||||
{
|
||||
Decl *param = params[i];
|
||||
@@ -2091,6 +2103,11 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call)
|
||||
call->body_expansion_expr.ast = ast_macro_copy(macro_context->yield_body);
|
||||
success = sema_analyse_statement(context, call->body_expansion_expr.ast);
|
||||
|
||||
if (first_defer)
|
||||
{
|
||||
first_defer->defer_stmt.prev_defer = 0;
|
||||
context->active_scope.defer_last = last_defer;
|
||||
}
|
||||
SCOPE_END;
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -45,9 +45,7 @@ const char *kw_inout;
|
||||
const char *kw_align;
|
||||
const char *kw_deprecated;
|
||||
const char *kw_distinct;
|
||||
const char *kw_ensure;
|
||||
const char *kw_elements;
|
||||
const char *kw_errors;
|
||||
const char *kw_return;
|
||||
const char *kw_type;
|
||||
const char *kw_inf;
|
||||
@@ -62,7 +60,6 @@ const char *kw_min;
|
||||
const char *kw_nan;
|
||||
const char *kw_noinline;
|
||||
const char *kw_ordinal;
|
||||
const char *kw_param;
|
||||
const char *kw_ptr;
|
||||
const char *kw_pure;
|
||||
const char *kw_std;
|
||||
@@ -132,8 +129,6 @@ void symtab_init(uint32_t capacity)
|
||||
kw_deprecated = KW_DEF("deprecated");
|
||||
kw_distinct = KW_DEF("distinct");
|
||||
kw_elements = KW_DEF("elements");
|
||||
kw_ensure = KW_DEF("ensure");
|
||||
kw_errors = KW_DEF("errors");
|
||||
kw_type = KW_DEF("type");
|
||||
kw_inf = KW_DEF("inf");
|
||||
kw_inline = KW_DEF("inline");
|
||||
@@ -147,7 +142,6 @@ void symtab_init(uint32_t capacity)
|
||||
kw_nan = KW_DEF("nan");
|
||||
kw_noinline = KW_DEF("noinline");
|
||||
kw_ordinal = KW_DEF("ordinal");
|
||||
kw_param = KW_DEF("param");
|
||||
kw_ptr = KW_DEF("ptr");
|
||||
kw_pure = KW_DEF("pure");
|
||||
KW_DEF("require");
|
||||
|
||||
126
test/test_suite/macros/macro_body_defer.c3t
Normal file
126
test/test_suite/macros/macro_body_defer.c3t
Normal file
@@ -0,0 +1,126 @@
|
||||
// #target: x64-darwin
|
||||
module foo;
|
||||
extern fn void printf(char*,...);
|
||||
|
||||
fn int! foo() { return 1; }
|
||||
|
||||
macro foo_test(int i; @body())
|
||||
{
|
||||
defer printf("%d\n", i);
|
||||
@body();
|
||||
defer printf("2:%d\n", i);
|
||||
}
|
||||
|
||||
macro foo_defer()
|
||||
{
|
||||
defer printf("A\n");
|
||||
printf("B\n");
|
||||
defer printf("C\n");
|
||||
}
|
||||
fn void! main()
|
||||
{
|
||||
@foo_defer();
|
||||
@foo_test(34) {
|
||||
defer printf("inside_defer\n");
|
||||
};
|
||||
while (1)
|
||||
{
|
||||
defer printf("outside\n");
|
||||
@foo_test(3)
|
||||
{
|
||||
defer printf("Inside will it jump?\n");
|
||||
printf("3-test\n");
|
||||
break;
|
||||
};
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
defer printf("outside2\n");
|
||||
printf("--\n");
|
||||
@foo_test(3)
|
||||
{
|
||||
defer printf("Inside will it jump?\n");
|
||||
printf("--3\n");
|
||||
return;
|
||||
};
|
||||
}
|
||||
printf("Should not reach\n");
|
||||
}
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
define i64 @foo.foo(i32* %0) #0 {
|
||||
entry:
|
||||
%reterr = alloca i64, align 8
|
||||
store i32 1, i32* %0, align 4
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
define i64 @foo.main() #0 {
|
||||
entry:
|
||||
%i = alloca i32, align 4
|
||||
%i1 = alloca i32, align 4
|
||||
%i3 = alloca i32, align 4
|
||||
%reterr = alloca i64, align 8
|
||||
%reterr5 = alloca i64, align 8
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i32 0, i32 0))
|
||||
store i32 34, i32* %i, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.3, i32 0, i32 0))
|
||||
%0 = load i32, i32* %i, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.4, i32 0, i32 0), i32 %0)
|
||||
%1 = load i32, i32* %i, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.5, i32 0, i32 0), i32 %1)
|
||||
br label %loop.body
|
||||
|
||||
loop.body: ; preds = %entry
|
||||
store i32 3, i32* %i1, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.6, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.7, i32 0, i32 0))
|
||||
%2 = load i32, i32* %i1, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.8, i32 0, i32 0), i32 %2)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.9, i32 0, i32 0))
|
||||
br label %loop.exit
|
||||
|
||||
loop.exit: ; preds = %loop.body
|
||||
br label %loop.body2
|
||||
|
||||
loop.body2: ; preds = %loop.exit
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.13, i32 0, i32 0))
|
||||
store i32 3, i32* %i3, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.14, i32 0, i32 0))
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.15, i32 0, i32 0))
|
||||
%3 = load i32, i32* %i3, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.16, i32 0, i32 0), i32 %3)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.17, i32 0, i32 0))
|
||||
ret i64 0
|
||||
|
||||
loop.exit4: ; No predecessors!
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.21, i32 0, i32 0))
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @main(i32 %0, i8** %1) #0 {
|
||||
entry:
|
||||
%2 = call i64 @foo.main()
|
||||
%not_err = icmp eq i64 %2, 0
|
||||
br i1 %not_err, label %after.errcheck, label %error_block
|
||||
|
||||
after.errcheck: ; preds = %entry
|
||||
br label %noerr_block
|
||||
|
||||
noerr_block: ; preds = %after.errcheck
|
||||
br label %phi_trycatch_block
|
||||
|
||||
error_block: ; preds = %entry
|
||||
br label %phi_trycatch_block
|
||||
|
||||
phi_trycatch_block: ; preds = %error_block, %noerr_block
|
||||
%val = phi i8 [ 1, %noerr_block ], [ 0, %error_block ]
|
||||
%3 = trunc i8 %val to i1
|
||||
%not = xor i1 %3, true
|
||||
%boolsi = zext i1 %not to i32
|
||||
ret i32 %boolsi
|
||||
}
|
||||
Reference in New Issue
Block a user