Miscompilation of do-while when the while starts with a branch #2394. Also: change do-while to make the lowering follow the execution.

This commit is contained in:
Christoffer Lerno
2025-08-18 21:28:19 +02:00
parent eeab73df4e
commit 7d6a864d56
2 changed files with 18 additions and 9 deletions

View File

@@ -1588,7 +1588,7 @@ void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_na
{
if (LLVMIsAConstantInt(value->value))
{
ASSERT(!LLVMConstIntGetZExtValue(value->value) && "Unexpected bounds check failed.");
ASSERT_AT(loc, !LLVMConstIntGetZExtValue(value->value) && "Unexpected bounds check failed.");
return;
}
LLVMBasicBlockRef panic_block = llvm_basic_block_new(c, "panic");

View File

@@ -143,8 +143,8 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
static void sema_binary_unify_voidptr(Expr *left, Expr *right, Type **left_type_ref, Type **right_type_ref);
// -- function helper functions
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type,
bool optional, bool *no_match_ref);
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Expr *var,
Type *func_ptr_type, bool optional,bool *no_match_ref);
static inline bool sema_expr_analyse_func_call(SemaContext *context, Expr *expr, Decl *decl,
Expr *struct_var, bool optional, bool *no_match_ref);
@@ -2386,7 +2386,7 @@ SKIP_CONTRACTS:
return true;
}
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Type *func_ptr_type, bool optional, bool *no_match_ref)
static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr, Expr *var, Type *func_ptr_type, bool optional,bool *no_match_ref)
{
func_ptr_type = type_flat_distinct_inline(func_ptr_type);
if (func_ptr_type->type_kind != TYPE_FUNC_PTR)
@@ -2399,6 +2399,10 @@ static inline bool sema_expr_analyse_var_call(SemaContext *context, Expr *expr,
RETURN_SEMA_ERROR(expr, "Only macros, functions and function pointers may be invoked, this is of type '%s'.",
type_to_error_string(func_ptr_type));
}
if (sema_cast_const(var) && expr_is_const_pointer(var) && var->const_expr.ptr == 0)
{
RETURN_SEMA_ERROR(var, "You cannot call a null function pointer.");
}
Type *pointee = func_ptr_type->pointer;
expr->call_expr.is_pointer_call = true;
return sema_call_analyse_func_invocation(context, pointee->function.decl, pointee, expr, NULL, optional,
@@ -3129,9 +3133,9 @@ bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl
expr->call_expr.is_type_method = struct_var != NULL;
if (decl == NULL)
{
return sema_expr_analyse_var_call(context, expr,
type_flatten(exprptr(expr->call_expr.function)->type), optional,
no_match_ref);
Expr *var = exprptr(expr->call_expr.function);
return sema_expr_analyse_var_call(context, expr, var, type_flatten(var->type),
optional, no_match_ref);
}
if (!sema_analyse_decl(context, decl)) return false;
switch (decl->decl_kind)
@@ -3141,9 +3145,14 @@ bool sema_expr_analyse_general_call(SemaContext *context, Expr *expr, Decl *decl
expr->call_expr.is_func_ref = true;
return sema_expr_analyse_macro_call(context, expr, struct_var, decl, optional, no_match_ref);
case DECL_VAR:
{
ASSERT_SPAN(expr, struct_var == NULL);
return sema_expr_analyse_var_call(context, expr, decl->type->canonical, optional || IS_OPTIONAL(decl),
no_match_ref);
Expr *var = exprptr(expr->call_expr.function);
ASSERT_SPAN(expr, var);
return sema_expr_analyse_var_call(context, expr, var, decl->type->canonical,
optional || IS_OPTIONAL(decl), no_match_ref);
}
case DECL_FUNC:
expr->call_expr.func_ref = declid(decl);
expr->call_expr.is_func_ref = true;