mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Usage of @noreturn macro is type-checked as if it returns #1913.
This commit is contained in:
@@ -36,7 +36,8 @@
|
||||
- Missing error when placing a single statement for-body on a new row #1892.
|
||||
- Fix bug where in dead code, only the first statement would be turned into a nop.
|
||||
- Remove unused $inline argument to mem::copy.
|
||||
- defer is broken when placed before a $foreach #1912.
|
||||
- Defer is broken when placed before a $foreach #1912.
|
||||
- Usage of @noreturn macro is type-checked as if it returns #1913.
|
||||
|
||||
### Stdlib changes
|
||||
- Added '%h' and '%H' for printing out binary data in hexadecimal using the formatter.
|
||||
|
||||
@@ -5124,7 +5124,7 @@ void llvm_add_abi_call_attributes(GenContext *c, LLVMValueRef call_value, int co
|
||||
}
|
||||
|
||||
|
||||
void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype *prototype, LLVMTypeRef func_type, LLVMValueRef func, LLVMValueRef *args, unsigned arg_count, int inline_flag, LLVMValueRef error_var, bool sret_return, BEValue *synthetic_return_param)
|
||||
void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype *prototype, LLVMTypeRef func_type, LLVMValueRef func, LLVMValueRef *args, unsigned arg_count, int inline_flag, LLVMValueRef error_var, bool sret_return, BEValue *synthetic_return_param, bool no_return)
|
||||
{
|
||||
ABIArgInfo *ret_info = prototype->ret_abi_info;
|
||||
Type *call_return_type = prototype->abi_ret_type;
|
||||
@@ -5134,6 +5134,10 @@ void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype
|
||||
{
|
||||
LLVMSetInstructionCallConv(call_value, llvm_call_convention_from_call(prototype->call_abi));
|
||||
}
|
||||
if (no_return)
|
||||
{
|
||||
llvm_attribute_add_call(c, call_value, attribute_id.noreturn, -1, 0);
|
||||
}
|
||||
switch (inline_flag)
|
||||
{
|
||||
case -1:
|
||||
@@ -5145,7 +5149,6 @@ void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(!prototype->ret_by_ref || prototype->ret_by_ref_abi_info->kind != ABI_ARG_INDIRECT);
|
||||
|
||||
llvm_add_abi_call_attributes(c, call_value, vec_size(prototype->param_types), prototype->abi_args);
|
||||
@@ -5442,6 +5445,7 @@ INLINE void llvm_emit_call_invocation(GenContext *c, BEValue *result_value,
|
||||
Expr **args,
|
||||
BEValue *values,
|
||||
int inline_flag,
|
||||
bool no_return,
|
||||
LLVMValueRef func,
|
||||
LLVMTypeRef func_type,
|
||||
Expr **varargs)
|
||||
@@ -5583,7 +5587,7 @@ INLINE void llvm_emit_call_invocation(GenContext *c, BEValue *result_value,
|
||||
// 10. Create the actual call (remember to emit a loc, because we might have shifted loc emitting the params)
|
||||
EMIT_SPAN(c, span);
|
||||
|
||||
llvm_emit_raw_call(c, result_value, prototype, func_type, func, arg_values, arg_count, inline_flag, error_var, sret_return, &synthetic_return_param);
|
||||
llvm_emit_raw_call(c, result_value, prototype, func_type, func, arg_values, arg_count, inline_flag, error_var, sret_return, &synthetic_return_param, no_return);
|
||||
|
||||
// 17i. The simple case here is where there is a normal return.
|
||||
// In this case be_value already holds the result
|
||||
@@ -5711,6 +5715,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
func_type = llvm_get_type(c, function_decl->type);
|
||||
}
|
||||
int inline_flag = 0;
|
||||
bool no_return = expr->call_expr.no_return;
|
||||
if (expr->call_expr.attr_force_noinline)
|
||||
{
|
||||
inline_flag = -1;
|
||||
@@ -5793,7 +5798,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
LLVMBasicBlockRef after = llvm_basic_block_new(c, "after_call");
|
||||
FunctionPrototype *default_prototype = type_get_resolved_prototype(default_method->type);
|
||||
BEValue default_res;
|
||||
llvm_emit_call_invocation(c, &default_res, target, expr->span, default_prototype, args, values, inline_flag,
|
||||
llvm_emit_call_invocation(c, &default_res, target, expr->span, default_prototype, args, values, inline_flag, no_return,
|
||||
llvm_get_ref(c, default_method),
|
||||
llvm_get_type(c, default_method->type),
|
||||
varargs);
|
||||
@@ -5805,7 +5810,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
func_type = llvm_get_type(c, dyn_fn->type);
|
||||
BEValue normal_res;
|
||||
values[0] = result;
|
||||
llvm_emit_call_invocation(c, &normal_res, target, expr->span, prototype, args, values, inline_flag, func, func_type,
|
||||
llvm_emit_call_invocation(c, &normal_res, target, expr->span, prototype, args, values, inline_flag, no_return, func, func_type,
|
||||
varargs);
|
||||
LLVMValueRef normal_val = llvm_load_value(c, &normal_res);
|
||||
LLVMBasicBlockRef normal_block = c->current_block;
|
||||
@@ -5830,7 +5835,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
|
||||
}
|
||||
|
||||
llvm_emit_call_invocation(c, result_value, target, expr->span, prototype, args, values, inline_flag, func, func_type,
|
||||
llvm_emit_call_invocation(c, result_value, target, expr->span, prototype, args, values, inline_flag, no_return, func, func_type,
|
||||
varargs);
|
||||
}
|
||||
|
||||
|
||||
@@ -506,7 +506,7 @@ void llvm_emit_coerce_store(GenContext *c, LLVMValueRef addr, AlignSize alignmen
|
||||
LLVMValueRef llvm_emit_coerce(GenContext *c, LLVMTypeRef coerced, BEValue *value, Type *original_type);
|
||||
|
||||
static inline LLVMCallConv llvm_call_convention_from_call(CallABI abi);
|
||||
void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype *prototype, LLVMTypeRef func_type, LLVMValueRef func, LLVMValueRef *args, unsigned arg_count, int inline_flag, LLVMValueRef error_var, bool sret_return, BEValue *synthetic_return_param);
|
||||
void llvm_emit_raw_call(GenContext *c, BEValue *result_value, FunctionPrototype *prototype, LLVMTypeRef func_type, LLVMValueRef func, LLVMValueRef *args, unsigned arg_count, int inline_flag, LLVMValueRef error_var, bool sret_return, BEValue *synthetic_return_param, bool no_return);
|
||||
void llvm_emit_parameter(GenContext *c, LLVMValueRef *args, unsigned *arg_count_ref, ABIArgInfo *info, BEValue *be_value, Type *type);
|
||||
|
||||
// -- Dynamic interface --
|
||||
|
||||
@@ -1582,7 +1582,7 @@ void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc, const c
|
||||
BEValue res;
|
||||
if (c->debug.builder) llvm_emit_debug_location(c, loc);
|
||||
llvm_emit_raw_call(c, &res, prototype, llvm_func_type(c, prototype), llvm_get_ref(c, panicf), actual_args,
|
||||
count, 0, NULL, false, NULL);
|
||||
count, 0, NULL, false, NULL, true);
|
||||
llvm_emit_unreachable(c);
|
||||
return;
|
||||
}
|
||||
@@ -1594,7 +1594,7 @@ void llvm_emit_panic(GenContext *c, const char *message, SourceSpan loc, const c
|
||||
BEValue res;
|
||||
if (c->debug.builder) llvm_emit_debug_location(c, loc);
|
||||
llvm_emit_raw_call(c, &res, prototype, llvm_func_type(c, prototype), val.value, actual_args,
|
||||
count, 0, NULL, false, NULL);
|
||||
count, 0, NULL, false, NULL, true);
|
||||
llvm_emit_unreachable(c);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
static inline bool sema_analyse_func_macro(SemaContext *context, Decl *decl, AttributeDomain domain, bool *erase_decl);
|
||||
static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *erase_decl);
|
||||
static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *erase_decl);
|
||||
static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export, bool is_deprecated);
|
||||
static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export, bool is_deprecated, SourceSpan span);
|
||||
static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl);
|
||||
static inline bool sema_check_param_uniqueness_and_type(SemaContext *context, Decl **decls, Decl *current,
|
||||
unsigned current_index, unsigned count);
|
||||
@@ -1082,7 +1082,7 @@ ERROR:
|
||||
return decl_poison(decl);
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export, bool is_deprecated)
|
||||
static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, TypeInfo *method_parent, bool is_export, bool is_deprecated, SourceSpan span)
|
||||
{
|
||||
Variadic variadic_type = sig->variadic;
|
||||
Decl **params = sig->params;
|
||||
@@ -1100,6 +1100,10 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig,
|
||||
is_macro ? RESOLVE_TYPE_ALLOW_INFER
|
||||
: RESOLVE_TYPE_DEFAULT)) return false;
|
||||
rtype = rtype_info->type;
|
||||
if (sig->attrs.noreturn && !type_is_void(rtype))
|
||||
{
|
||||
RETURN_SEMA_ERROR(rtype_info, "@noreturn cannot be used on %s not returning 'void'.", is_macro ? "macros" : "functions");
|
||||
}
|
||||
if (sig->attrs.nodiscard)
|
||||
{
|
||||
if (type_is_void(rtype))
|
||||
@@ -1337,7 +1341,7 @@ bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, Type
|
||||
|
||||
bool deprecated = func_decl->resolved_attributes && func_decl->attrs_resolved && func_decl->attrs_resolved->deprecated;
|
||||
|
||||
if (!sema_analyse_signature(context, signature, parent, func_decl->is_export, deprecated)) return false;
|
||||
if (!sema_analyse_signature(context, signature, parent, func_decl->is_export, deprecated, func_decl->span)) return false;
|
||||
|
||||
Variadic variadic_type = signature->variadic;
|
||||
|
||||
@@ -2875,6 +2879,10 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_
|
||||
decl->func_decl.signature.attrs.always_const = true;
|
||||
break;
|
||||
case ATTRIBUTE_NODISCARD:
|
||||
if (decl->func_decl.signature.attrs.nodiscard)
|
||||
{
|
||||
RETURN_SEMA_ERROR(attr, "@nodiscard cannot be combined with @noreturn.");
|
||||
}
|
||||
decl->func_decl.signature.attrs.nodiscard = true;
|
||||
break;
|
||||
case ATTRIBUTE_MAYDISCARD:
|
||||
@@ -2885,6 +2893,10 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_
|
||||
decl->func_decl.attr_noinline = false;
|
||||
break;
|
||||
case ATTRIBUTE_NORETURN:
|
||||
if (decl->func_decl.signature.attrs.nodiscard)
|
||||
{
|
||||
RETURN_SEMA_ERROR(attr, "@noreturn cannot be combined with @nodiscard.");
|
||||
}
|
||||
decl->func_decl.signature.attrs.noreturn = true;
|
||||
break;
|
||||
case ATTRIBUTE_NOSANITIZE:
|
||||
@@ -3846,7 +3858,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *er
|
||||
|
||||
if (!sema_analyse_signature(context, &decl->func_decl.signature,
|
||||
type_infoptrzero(decl->func_decl.type_parent),
|
||||
false, deprecated)) return false;
|
||||
false, deprecated, decl->span)) return false;
|
||||
|
||||
if (!decl->func_decl.signature.is_at_macro && decl->func_decl.body_param && !decl->func_decl.signature.is_safemacro)
|
||||
{
|
||||
|
||||
@@ -91,7 +91,6 @@ static bool sema_expr_analyse_enum_add_sub(SemaContext *context, Expr *expr, Exp
|
||||
static bool sema_expr_analyse_shift(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_shift_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_and_or(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_add_sub_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped);
|
||||
static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Expr *expr, Expr *left, Expr *right);
|
||||
@@ -298,8 +297,6 @@ Expr *sema_enter_inline_member(Expr *parent, CanonicalType *type)
|
||||
Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr, unsigned *index_ref)
|
||||
{
|
||||
unsigned args = vec_size(context->macro_varargs);
|
||||
uint64_t index;
|
||||
Decl *param = NULL;
|
||||
if (!sema_analyse_expr(context, index_expr)) return poisoned_expr;
|
||||
if (!type_is_integer(index_expr->type))
|
||||
{
|
||||
@@ -954,13 +951,11 @@ static inline bool sema_expr_analyse_ternary(SemaContext *context, Type *infer_t
|
||||
Expr *right = exprptr(expr->ternary_expr.else_expr);
|
||||
if (!sema_analyse_maybe_dead_expr(context, right, path == COND_TRUE, infer_type)) return expr_poison(expr);
|
||||
|
||||
bool is_optional = false;
|
||||
Type *left_canonical = left->type->canonical;
|
||||
Type *right_canonical = right->type->canonical;
|
||||
if (left_canonical != right_canonical)
|
||||
{
|
||||
Type *max;
|
||||
max = type_find_max_type(type_no_optional(left_canonical), type_no_optional(right_canonical));
|
||||
Type *max = type_find_max_type(type_no_optional(left_canonical), type_no_optional(right_canonical));
|
||||
if (!max)
|
||||
{
|
||||
SEMA_ERROR(expr, "Cannot find a common parent type of '%s' and '%s'",
|
||||
@@ -1039,9 +1034,6 @@ static inline bool sema_identifier_find_possible_inferred(SemaContext *context,
|
||||
|
||||
static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr)
|
||||
{
|
||||
Decl *ambiguous_decl = NULL;
|
||||
Decl *private_symbol = NULL;
|
||||
|
||||
ASSERT_SPAN(expr, expr && expr->unresolved_ident_expr.ident);
|
||||
DEBUG_LOG("Resolving identifier '%s'", expr->unresolved_ident_expr.ident);
|
||||
|
||||
@@ -1484,7 +1476,6 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee,
|
||||
if (arg->resolve_status != RESOLVE_DONE)
|
||||
{
|
||||
SemaContext default_context;
|
||||
Type *rtype = NULL;
|
||||
SemaContext *new_context = context_transform_for_eval(context, &default_context, param->unit);
|
||||
bool success;
|
||||
SCOPE_START
|
||||
@@ -1632,7 +1623,6 @@ INLINE bool sema_call_evaluate_arguments(SemaContext *context, CalledDecl *calle
|
||||
|
||||
// 2. Loop through the parameters.
|
||||
bool has_named = false;
|
||||
bool found_splat = false;
|
||||
ArrayIndex last_index = -1;
|
||||
Expr *last_named_arg = INVALID_PTR;
|
||||
Expr *last = NULL;
|
||||
@@ -1956,7 +1946,7 @@ static inline bool sema_call_analyse_func_invocation(SemaContext *context, Decl
|
||||
|
||||
expr->call_expr.has_optional_arg = optional;
|
||||
|
||||
if (rtype != type_void)
|
||||
if (!type_is_void(rtype))
|
||||
{
|
||||
bool is_optional_return = type_is_optional(rtype);
|
||||
expr->call_expr.is_optional_return = is_optional_return;
|
||||
@@ -2413,6 +2403,10 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
}
|
||||
|
||||
call_expr->type = type_add_optional(rtype, optional_return || has_optional_arg);
|
||||
if (is_no_return && type_is_void(rtype))
|
||||
{
|
||||
call_expr->type = type_wildcard;
|
||||
}
|
||||
|
||||
ASSERT_SPAN(call_expr, call_expr->type);
|
||||
bool must_use = false;
|
||||
@@ -7827,10 +7821,12 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr)
|
||||
expr_replace(expr, lhs);
|
||||
return true;
|
||||
}
|
||||
SEMA_ERROR(lhs, "No optional to use '\?\?' with, please remove the '\?\?'.");
|
||||
RETURN_SEMA_ERROR(lhs, "No optional to use '\?\?' with, please remove the '\?\?'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool active_scope_jump = context->active_scope.jump_end;
|
||||
|
||||
// First we analyse the "else" and try to implictly cast.
|
||||
if (!sema_analyse_expr(context, rhs)) return false;
|
||||
|
||||
@@ -7840,6 +7836,9 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ignore the jump here.
|
||||
context->active_scope.jump_end = active_scope_jump;
|
||||
|
||||
// Here we might need to insert casts.
|
||||
Type *else_type = rhs->type;
|
||||
|
||||
|
||||
@@ -3171,6 +3171,7 @@ bool sema_analyse_statement(SemaContext *context, Ast *statement)
|
||||
{
|
||||
if (statement->ast_kind == AST_POISONED) return false;
|
||||
bool dead_code = context->active_scope.jump_end;
|
||||
unsigned returns = vec_size(context->returns);
|
||||
if (!sema_analyse_statement_inner(context, statement)) return ast_poison(statement);
|
||||
if (dead_code)
|
||||
{
|
||||
@@ -3187,6 +3188,7 @@ bool sema_analyse_statement(SemaContext *context, Ast *statement)
|
||||
}
|
||||
// Remove it
|
||||
}
|
||||
vec_resize(context->returns, returns);
|
||||
statement->ast_kind = AST_NOP_STMT;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -19,7 +19,6 @@ fn void main() {
|
||||
define void @test.foo() #0 !dbg !8 {
|
||||
entry:
|
||||
%values = alloca [1 x i32], align 4
|
||||
call void @llvm.dbg.declare(metadata ptr %values, metadata !12, metadata !DIExpression()), !dbg !17
|
||||
store i32 0, ptr %values, align 4, !dbg !17
|
||||
store i32 0, ptr %values, align 4, !dbg !18
|
||||
ret void, !dbg !18
|
||||
|
||||
@@ -145,21 +145,17 @@ entry:
|
||||
store i32 %1, ptr %a, align 4, !dbg !26
|
||||
store i64 0, ptr %a.f, align 8, !dbg !26
|
||||
br label %loop.cond, !dbg !27
|
||||
|
||||
loop.cond: ; preds = %loop.body, %entry
|
||||
%load.err = load i64, ptr %a.f, align 8, !dbg !28
|
||||
%result = icmp eq i64 %load.err, 0, !dbg !28
|
||||
br i1 %result, label %loop.body, label %loop.exit, !dbg !28
|
||||
|
||||
loop.body: ; preds = %loop.cond
|
||||
store i32 2, ptr %a, align 4, !dbg !30
|
||||
store i64 0, ptr %a.f, align 8, !dbg !30
|
||||
br label %loop.cond, !dbg !30
|
||||
|
||||
loop.exit: ; preds = %loop.cond
|
||||
ret void, !dbg !30
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind uwtable
|
||||
define i32 @test.main(ptr %0, i64 %1) #0 !dbg !32 {
|
||||
entry:
|
||||
@@ -268,39 +264,30 @@ noerr_block: ; preds = %after_check
|
||||
%not_err6 = icmp eq i64 %16, 0, !dbg !103
|
||||
%17 = call i1 @llvm.expect.i1(i1 %not_err6, i1 true), !dbg !103
|
||||
br i1 %17, label %after_check8, label %assign_optional7, !dbg !103
|
||||
|
||||
assign_optional7: ; preds = %noerr_block
|
||||
store i64 %16, ptr %error_var5, align 8, !dbg !103
|
||||
br label %guard_block9, !dbg !103
|
||||
|
||||
after_check8: ; preds = %noerr_block
|
||||
br label %noerr_block10, !dbg !103
|
||||
|
||||
guard_block9: ; preds = %assign_optional7
|
||||
br label %voiderr, !dbg !103
|
||||
|
||||
noerr_block10: ; preds = %after_check8
|
||||
%18 = load ptr, ptr %out, align 8, !dbg !104
|
||||
%19 = call i64 @std.io.File.flush(ptr %18), !dbg !104
|
||||
%not_err12 = icmp eq i64 %19, 0, !dbg !104
|
||||
%20 = call i1 @llvm.expect.i1(i1 %not_err12, i1 true), !dbg !104
|
||||
br i1 %20, label %after_check14, label %assign_optional13, !dbg !104
|
||||
|
||||
assign_optional13: ; preds = %noerr_block10
|
||||
store i64 %19, ptr %error_var11, align 8, !dbg !104
|
||||
br label %guard_block15, !dbg !104
|
||||
|
||||
after_check14: ; preds = %noerr_block10
|
||||
br label %noerr_block16, !dbg !104
|
||||
|
||||
guard_block15: ; preds = %assign_optional13
|
||||
br label %voiderr, !dbg !104
|
||||
|
||||
noerr_block16: ; preds = %after_check14
|
||||
%21 = load i64, ptr %len, align 8, !dbg !105
|
||||
%add = add i64 %21, 1, !dbg !105
|
||||
br label %voiderr, !dbg !96
|
||||
|
||||
voiderr: ; preds = %noerr_block16, %guard_block15, %guard_block9, %guard_block
|
||||
ret ptr null, !dbg !106
|
||||
}
|
||||
@@ -395,11 +382,9 @@ entry:
|
||||
%10 = load i64, ptr %size, align 8, !dbg !160
|
||||
%i2nb = icmp eq i64 %10, 0, !dbg !160
|
||||
br i1 %i2nb, label %if.then, label %if.exit, !dbg !160
|
||||
|
||||
if.then: ; preds = %entry
|
||||
store ptr null, ptr %blockret11, align 8, !dbg !163
|
||||
br label %expr_block.exit, !dbg !163
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
%ptradd = getelementptr inbounds i8, ptr %allocator10, i64 8, !dbg !164
|
||||
%11 = load i64, ptr %ptradd, align 8, !dbg !164
|
||||
@@ -407,7 +392,6 @@ if.exit: ; preds = %entry
|
||||
%type = load ptr, ptr %.cachedtype, align 8
|
||||
%13 = icmp eq ptr %12, %type
|
||||
br i1 %13, label %cache_hit, label %cache_miss
|
||||
|
||||
cache_miss: ; preds = %if.exit
|
||||
%ptradd12 = getelementptr inbounds i8, ptr %12, i64 16
|
||||
%14 = load ptr, ptr %ptradd12, align 8
|
||||
@@ -415,21 +399,17 @@ cache_miss: ; preds = %if.exit
|
||||
store ptr %15, ptr %.inlinecache, align 8
|
||||
store ptr %12, ptr %.cachedtype, align 8
|
||||
br label %16
|
||||
|
||||
cache_hit: ; preds = %if.exit
|
||||
%cache_hit_fn = load ptr, ptr %.inlinecache, align 8
|
||||
br label %16
|
||||
|
||||
16: ; preds = %cache_hit, %cache_miss
|
||||
%fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %15, %cache_miss ]
|
||||
%17 = icmp eq ptr %fn_phi, null
|
||||
br i1 %17, label %missing_function, label %match
|
||||
|
||||
missing_function: ; preds = %16
|
||||
%18 = load ptr, ptr @std.core.builtin.panic, align 8, !dbg !166
|
||||
call void %18(ptr @.panic_msg, i64 44, ptr @.file, i64 16, ptr @.func, i64 6, i32 68), !dbg !166
|
||||
call void %18(ptr @.panic_msg, i64 44, ptr @.file, i64 16, ptr @.func, i64 6, i32 68) #5, !dbg !166
|
||||
unreachable, !dbg !166
|
||||
|
||||
match: ; preds = %16
|
||||
%19 = load ptr, ptr %allocator10, align 8
|
||||
%20 = load i64, ptr %size, align 8
|
||||
@@ -437,16 +417,13 @@ match: ; preds = %16
|
||||
%not_err = icmp eq i64 %21, 0, !dbg !166
|
||||
%22 = call i1 @llvm.expect.i1(i1 %not_err, i1 true), !dbg !166
|
||||
br i1 %22, label %after_check, label %assign_optional, !dbg !166
|
||||
|
||||
assign_optional: ; preds = %match
|
||||
store i64 %21, ptr %error_var, align 8, !dbg !166
|
||||
br label %panic_block, !dbg !166
|
||||
|
||||
after_check: ; preds = %match
|
||||
%23 = load ptr, ptr %retparam, align 8, !dbg !166
|
||||
store ptr %23, ptr %blockret11, align 8, !dbg !166
|
||||
br label %expr_block.exit, !dbg !166
|
||||
|
||||
expr_block.exit: ; preds = %after_check, %if.then
|
||||
%24 = load ptr, ptr %blockret11, align 8, !dbg !166
|
||||
store ptr %24, ptr %taddr, align 8
|
||||
@@ -457,7 +434,6 @@ expr_block.exit: ; preds = %after_check, %if.th
|
||||
%27 = insertvalue %"char[][]" undef, ptr %25, 0, !dbg !167
|
||||
%28 = insertvalue %"char[][]" %27, i64 %size13, 1, !dbg !167
|
||||
br label %noerr_block, !dbg !167
|
||||
|
||||
panic_block: ; preds = %assign_optional
|
||||
%29 = insertvalue %any undef, ptr %error_var, 0, !dbg !167
|
||||
%30 = insertvalue %any %29, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1, !dbg !167
|
||||
@@ -467,19 +443,16 @@ panic_block: ; preds = %assign_optional
|
||||
store %"any[]" %"$$temp", ptr %indirectarg, align 8
|
||||
call void @std.core.builtin.panicf(ptr @.panic_msg.1
|
||||
unreachable, !dbg !154
|
||||
|
||||
noerr_block: ; preds = %expr_block.exit
|
||||
store %"char[][]" %28, ptr %list5, align 8, !dbg !154
|
||||
!170
|
||||
store i32 0, ptr %i, align 4, !dbg !171
|
||||
br label %loop.cond, !dbg !171
|
||||
|
||||
loop.cond: ; preds = %loop.exit, %noerr_block
|
||||
%32 = load i32, ptr %i, align 4, !dbg !172
|
||||
%33 = load i32, ptr %argc2, align 4, !dbg !173
|
||||
%lt = icmp slt i32 %32, %33, !dbg !172
|
||||
br i1 %lt, label %loop.body, label %loop.exit26, !dbg !172
|
||||
|
||||
loop.body: ; preds = %loop.cond
|
||||
!176
|
||||
%34 = load ptr, ptr %argv3, align 8, !dbg !177
|
||||
@@ -500,7 +473,6 @@ loop.body: ; preds = %loop.cond
|
||||
!187
|
||||
store i64 0, ptr %len18, align 8, !dbg !189
|
||||
br label %loop.cond19, !dbg !190
|
||||
|
||||
loop.cond19: ; preds = %loop.body21, %loop.body
|
||||
%41 = load ptr, ptr %ptr, align 8, !dbg !191
|
||||
%42 = load i64, ptr %len18, align 8, !dbg !193
|
||||
@@ -508,13 +480,11 @@ loop.cond19: ; preds = %loop.body21, %loop.
|
||||
%43 = load i8, ptr %ptradd20, align 1, !dbg !193
|
||||
%i2b = icmp ne i8 %43, 0, !dbg !193
|
||||
br i1 %i2b, label %loop.body21, label %loop.exit, !dbg !193
|
||||
|
||||
loop.body21: ; preds = %loop.cond19
|
||||
%44 = load i64, ptr %len18, align 8, !dbg !194
|
||||
%add22 = add i64 %44, 1, !dbg !194
|
||||
store i64 %add22, ptr %len18, align 8, !dbg !194
|
||||
br label %loop.cond19, !dbg !194
|
||||
|
||||
loop.exit: ; preds = %loop.cond19
|
||||
%45 = load i64, ptr %len18, align 8, !dbg !195
|
||||
%add23 = add i64 0, %45, !dbg !195
|
||||
@@ -526,7 +496,6 @@ loop.exit: ; preds = %loop.cond19
|
||||
%add25 = add i32 %48, 1, !dbg !196
|
||||
store i32 %add25, ptr %i, align 4, !dbg !196
|
||||
br label %loop.cond, !dbg !196
|
||||
|
||||
loop.exit26: ; preds = %loop.cond
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %list, ptr align 8 %list5, i32 16, i1 false), !dbg !197
|
||||
%lo = load ptr, ptr %list, align 8, !dbg !198
|
||||
@@ -537,7 +506,6 @@ loop.exit26: ; preds = %loop.cond
|
||||
%50 = load ptr, ptr %list, align 8, !dbg !200
|
||||
call void @std.core.mem.free(ptr %50)
|
||||
br label %expr_block.exit28, !dbg !202
|
||||
|
||||
expr_block.exit28: ; preds = %loop.exit26
|
||||
%51 = load i32, ptr %blockret, align 4, !dbg !202
|
||||
ret i32 %51, !dbg !202
|
||||
@@ -561,25 +529,20 @@ declare void @arena_scratch_end(ptr, i64) #0
|
||||
define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr {
|
||||
entry:
|
||||
br label %check
|
||||
|
||||
check: ; preds = %no_match, %entry
|
||||
%2 = phi ptr [ %0, %entry ], [ %9, %no_match ]
|
||||
%3 = icmp eq ptr %2, null
|
||||
br i1 %3, label %missing_function, label %compare
|
||||
|
||||
missing_function: ; preds = %check
|
||||
ret ptr null
|
||||
|
||||
compare: ; preds = %check
|
||||
%4 = getelementptr inbounds
|
||||
%5 = load ptr, ptr %4, align 8
|
||||
%6 = icmp eq ptr %5, %1
|
||||
br i1 %6, label %match, label %no_match
|
||||
|
||||
match: ; preds = %compare
|
||||
%7 = load ptr, ptr %2, align 8
|
||||
ret ptr %7
|
||||
|
||||
no_match: ; preds = %compare
|
||||
%8 = getelementptr inbounds
|
||||
%9 = load ptr, ptr %8, align 8
|
||||
@@ -587,7 +550,6 @@ no_match: ; preds = %compare
|
||||
}
|
||||
|
||||
!llvm.dbg.cu = !{!6}
|
||||
|
||||
!0 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!1 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!2 = !{i32 2, !"wchar_size", i32 4}
|
||||
|
||||
39
test/test_suite/errors/else_unreachable.c3t
Normal file
39
test/test_suite/errors/else_unreachable.c3t
Normal file
@@ -0,0 +1,39 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
import std;
|
||||
// Issue #1913
|
||||
fn void main()
|
||||
{
|
||||
char[] bytes = file::load_temp("config.json") ?? abort("Unable to open config.json file");
|
||||
int hello;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define void @test.main() #0 {
|
||||
entry:
|
||||
%bytes = alloca %"char[]", align 8
|
||||
%retparam = alloca %"char[]", align 8
|
||||
%blockret = alloca %"char[]", align 8
|
||||
%indirectarg = alloca %"any[]", align 8
|
||||
%hello = alloca i32, align 4
|
||||
%0 = call i64 @std.io.file.load_temp(ptr %retparam, ptr @.str, i64 11)
|
||||
%not_err = icmp eq i64 %0, 0
|
||||
%1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
||||
br i1 %1, label %after_check, label %else_block
|
||||
|
||||
after_check: ; preds = %entry
|
||||
%2 = load %"char[]", ptr %retparam, align 8
|
||||
br label %phi_block
|
||||
|
||||
else_block: ; preds = %entry
|
||||
store %"any[]" zeroinitializer, ptr %indirectarg, align 8
|
||||
call void @std.core.builtin.panicf(ptr @.str.1, i64 31, ptr @.str.2, i64 19, ptr @.str.3, i64 4, i32 6, ptr byval(%"any[]") align 8 %indirectarg)
|
||||
call void @llvm.trap()
|
||||
unreachable
|
||||
|
||||
phi_block: ; preds = %after_check
|
||||
store %"char[]" %2, ptr %bytes, align 8
|
||||
store i32 0, ptr %hello, align 4
|
||||
ret void
|
||||
}
|
||||
8
test/test_suite/errors/else_unreachable_in_block.c3
Normal file
8
test/test_suite/errors/else_unreachable_in_block.c3
Normal file
@@ -0,0 +1,8 @@
|
||||
module test;
|
||||
import std;
|
||||
fn void main()
|
||||
{
|
||||
char[] bytes = file::load_temp("config.json") ?? {| abort("Unable to open config.json file"); // #error: Cannot find a common type for 'char[]' and 'void'
|
||||
return {}; |}; // #warning: This code will never execute.
|
||||
char[] bytes2;
|
||||
}
|
||||
Reference in New Issue
Block a user