Fix of macro defer with bodies.

This commit is contained in:
Christoffer Lerno
2022-03-28 10:08:07 +02:00
committed by Christoffer Lerno
parent 131bf5ed34
commit 34bd5fa6da
4 changed files with 149 additions and 15 deletions

View File

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

View File

@@ -1861,11 +1861,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
if (!sema_add_local(&macro_context, param)) goto EXIT_FAIL;
}
AstId current = body->compound_stmt.first_stmt;
while (current)
{
if (!sema_analyse_statement(&macro_context, ast_next(&current))) goto EXIT_FAIL;
}
if (!sema_analyse_statement(&macro_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;
}

View File

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

View 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
}