Regression String! a; char* b = a.ptr; would incorrectly be allowed.

This commit is contained in:
Christoffer Lerno
2025-02-14 16:11:31 +01:00
parent 7ca70b20be
commit 0dd1a93d0d
6 changed files with 44 additions and 28 deletions

View File

@@ -69,6 +69,7 @@
- Missing end padding when including a packed struct #1966.
- Issue when scalar expanding a boolean from a conditional to a bool vector #1954.
- Fix issue when parsing bitstructs, preventing them from implementing interfaces.
- Regression `String! a; char* b = a.ptr;` would incorrectly be allowed.
### Stdlib changes
- Added '%h' and '%H' for printing out binary data in hexadecimal using the formatter.

View File

@@ -3784,7 +3784,7 @@ INLINE void expr_rewrite_ptr_access(Expr *expr, Expr *inner, Type *type)
ASSERT(inner->resolve_status == RESOLVE_DONE);
expr->expr_kind = EXPR_PTR_ACCESS;
expr->inner_expr = inner;
expr->type = type;
expr->type = type_add_optional(type, IS_OPTIONAL(inner));
expr->resolve_status = RESOLVE_DONE;
}
@@ -3794,7 +3794,7 @@ INLINE void expr_rewrite_enum_from_ord(Expr *expr, Type *type)
ASSERT(inner->resolve_status == RESOLVE_DONE);
expr->expr_kind = EXPR_ENUM_FROM_ORD;
expr->inner_expr = inner;
expr->type = type;
expr->type = type_add_optional(type, IS_OPTIONAL(expr));
expr->resolve_status = RESOLVE_DONE;
}
@@ -3819,7 +3819,7 @@ INLINE void expr_rewrite_int_to_bool(Expr *expr, bool negate)
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_INT_TO_BOOL;
expr->int_to_bool_expr = (ExprIntToBool) { .inner = inner, .negate = negate };
expr->type = type_bool;
expr->type = type_add_optional(type_bool, IS_OPTIONAL(expr));
}
INLINE void expr_rewrite_ext_trunc(Expr *expr, Type *type, bool is_signed)
@@ -3827,7 +3827,7 @@ INLINE void expr_rewrite_ext_trunc(Expr *expr, Type *type, bool is_signed)
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_EXT_TRUNC;
expr->ext_trunc_expr = (ExprExtTrunc) { .inner = inner, .is_signed = is_signed };
expr->type = type;
expr->type = type_add_optional(type, IS_OPTIONAL(inner));
}
INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v)
@@ -3869,7 +3869,7 @@ INLINE void expr_rewrite_to_int_to_float(Expr *expr, Type *type)
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_INT_TO_FLOAT;
expr->inner_expr = inner;
expr->type = type;
expr->type = type_add_optional(type, IS_OPTIONAL(inner));
}
INLINE void expr_rewrite_to_int_to_ptr(Expr *expr, Type *type)
@@ -3877,7 +3877,7 @@ INLINE void expr_rewrite_to_int_to_ptr(Expr *expr, Type *type)
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_INT_TO_PTR;
expr->inner_expr = inner;
expr->type = type;
expr->type = type_add_optional(type, IS_OPTIONAL(inner));
}
INLINE void expr_rewrite_to_ptr_to_int(Expr *expr, Type *type)
@@ -3885,7 +3885,7 @@ INLINE void expr_rewrite_to_ptr_to_int(Expr *expr, Type *type)
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_PTR_TO_INT;
expr->inner_expr = inner;
expr->type = type;
expr->type = type_add_optional(type, IS_OPTIONAL(inner));
}
INLINE void expr_rewrite_to_float_to_int(Expr *expr, Type *type)
@@ -3893,7 +3893,7 @@ INLINE void expr_rewrite_to_float_to_int(Expr *expr, Type *type)
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_FLOAT_TO_INT;
expr->inner_expr = inner;
expr->type = type;
expr->type = type_add_optional(type, IS_OPTIONAL(inner));
}
INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d)
@@ -4108,9 +4108,11 @@ INLINE bool check_module_name(Path *path)
#ifdef NDEBUG
#define ASSERT_SPANF(node__, check__, format__, ...) do { } while(0)
#define ASSERT_SPAN(node__, check__) do { } while(0)
#define ASSERT_AT(span__, check__) do { } while(0)
#else
#define ASSERT_SPANF(node__, check__, format__, ...) do { if (!(check__)) { assert_print_line((node__)->span); eprintf(format__, __VA_ARGS__); ASSERT(check__); } } while(0)
#define ASSERT_SPAN(node__, check__) do { if (!(check__)) { assert_print_line((node__)->span); ASSERT(check__); } } while(0)
#define ASSERT_AT(span__, check__) do { if (!(check__)) { assert_print_line(span__); ASSERT(check__); } } while(0)
#endif
void assert_print_line(SourceSpan span);

View File

@@ -115,7 +115,7 @@ void llvm_value_rvalue(GenContext *c, BEValue *value)
void llvm_emit_jump_to_optional_exit(GenContext *c, LLVMValueRef opt_value)
{
ASSERT(c->catch.block && "unexpected emit");
ASSERT_AT(c->last_emitted_loc, c->catch.block && "unexpected emit");
bool is_constant_opt = llvm_is_const(opt_value);
// Maybe we don't need to emit anything?

View File

@@ -255,23 +255,24 @@ static inline void context_switch_stat_pop(SemaContext *swapped, ContextSwitchSt
Expr *sema_enter_inline_member(Expr *parent, CanonicalType *type)
{
Expr *expr;
switch (type->type_kind)
{
case TYPE_STRUCT:
{
Decl *decl = type->decl;
if (!decl->is_substruct) return NULL;
Expr *embedded_struct = expr_access_inline_member(parent, decl);
return embedded_struct;
expr = expr_access_inline_member(parent, decl);
break;
}
case TYPE_DISTINCT:
{
Decl *decl = type->decl;
if (!decl->is_substruct) return NULL;
Expr *inner_expr = expr_copy(parent);
expr = expr_copy(parent);
type = type->decl->distinct->type;
inner_expr->type = type;
return inner_expr;
expr->type = type;
break;
}
case TYPE_ENUM:
{
@@ -282,28 +283,31 @@ Expr *sema_enter_inline_member(Expr *parent, CanonicalType *type)
{
if (decl->enums.inline_value)
{
Expr *expr = expr_new_expr(EXPR_CONST, parent);
expr = expr_new_expr(EXPR_CONST, parent);
expr_rewrite_const_int(expr, decl->enums.type_info->type, parent->const_expr.enum_err_val->enum_constant.ordinal);
return expr;
}
return copy_expr_single(parent->const_expr.enum_err_val->enum_constant.args[decl->enums.inline_index]);
expr = copy_expr_single(parent->const_expr.enum_err_val->enum_constant.args[decl->enums.inline_index]);
break;
}
if (decl->enums.inline_value)
{
Expr *expr = copy_expr_single(parent);
expr->type = decl->enums.type_info->type;
return expr;
expr = copy_expr_single(parent);
expr->type = type_add_optional(decl->enums.type_info->type, IS_OPTIONAL(parent));
break;
}
Expr *property = expr_new(EXPR_ACCESS_RESOLVED, parent->span);
property->resolve_status = RESOLVE_DONE;
property->access_resolved_expr.parent = parent;
property->access_resolved_expr.ref = decl->enums.parameters[decl->enums.inline_value];
property->type = property->access_resolved_expr.ref->type;
return property;
expr = expr_new(EXPR_ACCESS_RESOLVED, parent->span);
expr->resolve_status = RESOLVE_DONE;
expr->access_resolved_expr.parent = parent;
expr->access_resolved_expr.ref = decl->enums.parameters[decl->enums.inline_value];
expr->type = expr->access_resolved_expr.ref->type;
break;
}
default:
return NULL;
}
if (IS_OPTIONAL(parent)) expr->type = type_add_optional(expr->type, true);
return expr;
}
Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr, unsigned *index_ref)
@@ -406,7 +410,7 @@ Expr *expr_access_inline_member(Expr *parent, Decl *parent_decl)
embedded_struct->resolve_status = RESOLVE_DONE;
embedded_struct->access_resolved_expr.parent = parent;
embedded_struct->access_resolved_expr.ref = parent_decl->strukt.members[0];
embedded_struct->type = embedded_struct->access_resolved_expr.ref->type;
embedded_struct->type = type_add_optional(embedded_struct->access_resolved_expr.ref->type, IS_OPTIONAL(parent));
return embedded_struct;
}

View File

@@ -480,8 +480,8 @@ static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, E
{
RETURN_SEMA_ERROR(element, "An untyped list can only have "
"constant elements, you can try "
"to type the list by prefixing the type, "
"e.g. 'int[2] { a, b }'.");
"to type the list by prefixing the type and possibly enclosing it in parentheses, "
"e.g. '((int[2]){ a, b })'.");
}
}
initializer->expr_kind = EXPR_CONST;

View File

@@ -0,0 +1,9 @@
module test;
import std;
fn void main()
{
String s = "Hello";
Char16* title = String.to_new_utf16(s).ptr; // #error: It is not possible to cast from
int! a;
float b = (float)a; // #error: It is not possible to cast from
}