mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Regression String! a; char* b = a.ptr; would incorrectly be allowed.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
9
test/test_suite/expressions/opt_in_conv.c3
Normal file
9
test/test_suite/expressions/opt_in_conv.c3
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user