- Disallow casting a void* to any or an interface, unless it is null.

- Defer resolution of declarations when looked up in `def` aliased #1559.
This commit is contained in:
Christoffer Lerno
2024-10-16 12:50:47 +02:00
parent 4445b6c054
commit 705856d51a
7 changed files with 54 additions and 14 deletions

View File

@@ -505,10 +505,10 @@ struct TempState
TempAllocator* old;
TempAllocator* current;
usz mark;
}/*
/+++
}
<*
Push the current temp allocator. A push must always be balanced with a pop using the current state.
+++/ */
*>
fn TempState temp_push(TempAllocator* other = null)
{
TempAllocator* current = allocator::temp();

View File

@@ -14,6 +14,8 @@
- Interfaces now support .ptr and .type directly without casting to `any`.
- Switch to `<* *>` docs.
- Improve error messages on expressions like `var $type = int;` #1553.
- Disallow casting a `void*` to `any` or an interface, unless it is `null`.
- Defer resolution of declarations when looked up in `def` aliased #1559.
### Fixes
- `Unsupported int[*] $x = { 1, 2, 3, 4 }` #1489.

View File

@@ -724,6 +724,14 @@ static TypeCmpResult match_pointers(CastContext *cc, Type *to_ptr, Type *from_pt
return type_is_pointer_equivalent(cc->context, to_ptr, from_ptr, flatten);
}
static bool rule_voidptr_to_any(CastContext *cc, bool is_explicit, bool is_silent)
{
if (expr_is_const_pointer(cc->expr) && !cc->expr->const_expr.ptr) return true;
RETURN_CAST_ERROR(cc->expr,
"Casting a 'void*' to %s is not permitted (except when the 'void*' is a constant null).",
type_quoted_error_string(cc->to));
}
static bool rule_ptr_to_ptr(CastContext *cc, bool is_explicit, bool is_silent)
{
if (is_explicit) return true;
@@ -1129,7 +1137,6 @@ static bool rule_ptr_to_interface(CastContext *cc, bool is_explicit, bool is_sil
if (type_may_implement_interface(pointee))
{
Type *interface = cc->to;
Decl *pointee_decl = pointee->decl;
if (type_implements_interface(cc, pointee->decl, interface)) return true;
}
if (is_silent) return false;
@@ -2283,7 +2290,9 @@ static void cast_typeid_to_bool(SemaContext *context, Expr *expr, Type *to_type)
#define RULST &rule_ulist_to_struct /* Untyped list -> bitstruct or union */
#define RULAR &rule_ulist_to_vecarr /* Untyped list -> vector or array */
#define RULFE &rule_ulist_to_inferred /* Untyped list -> inferred vector or array */
#define RULSL &rule_ulist_to_slice /* Untyped list -> slice */
#define RULSL &rule_ulist_to_slice /* Untyped list -> slice */
#define RVPAN &rule_voidptr_to_any /* void* -> interface/any */
CastRule cast_rules[CONV_LAST + 1][CONV_LAST + 1] = {
// void, wildc, bool, int, float, ptr, slice, vec, bitst, distc, array, strct, union, any, infc, fault, enum, func, typid, afaul, voidp, arrpt, infer, ulist (to)
{_NA__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // VOID (from)
@@ -2306,7 +2315,7 @@ CastRule cast_rules[CONV_LAST + 1][CONV_LAST + 1] = {
{REXPL, _NO__, REXPL, RPTIN, _NO__, _NO__, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RPTPT, _NO__, _NO__, ROKOK, _NO__, _NO__, _NO__}, // FUNC
{REXPL, _NO__, REXPL, RPTIN, _NO__, REXPL, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NA__, _NO__, REXPL, REXPL, _NO__, _NO__}, // TYPEID
{REXPL, _NO__, REXPL, RPTIN, _NO__, REXPL, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, RAFFA, _NO__, _NO__, _NO__, _NA__, REXPL, REXPL, _NO__, _NO__}, // ANYFAULT
{REXPL, _NO__, REXPL, RPTIN, _NO__, ROKOK, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, ROKOK, ROKOK, _NO__, _NO__, ROKOK, _NO__, _NO__, _NA__, ROKOK, _NO__, _NO__}, // VOIDPTR
{REXPL, _NO__, REXPL, RPTIN, _NO__, ROKOK, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, RVPAN, RVPAN, _NO__, _NO__, ROKOK, _NO__, _NO__, _NA__, ROKOK, _NO__, _NO__}, // VOIDPTR
{REXPL, _NO__, REXPL, RPTIN, _NO__, RPTPT, RAPSL, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, ROKOK, ROKOK, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, RPTPT, RPTFE, _NO__}, // ARRPTR
{_NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // INFERRED
{_NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RULSL, RULAR, RULST, RXXDI, RULAR, RULST, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RULFE, _NO__}, // UNTYPED_LIST

View File

@@ -4299,7 +4299,16 @@ Decl *sema_analyse_parameterized_identifier(SemaContext *c, Path *decl_path, con
return poisoned_decl;
}
}
if (!sema_analyse_decl(c, symbol)) return poisoned_decl;
CompilationUnit *unit = symbol->unit;
if (unit->module->stage < ANALYSIS_POST_REGISTER)
{
vec_add(unit->global_decls, symbol);
}
else
{
if (!sema_analyse_decl(c, symbol)) return poisoned_decl;
}
unit_register_external_symbol(c, symbol);
return symbol;
}
@@ -4345,6 +4354,7 @@ static inline bool sema_analyse_define(SemaContext *context, Decl *decl, bool *e
RETURN_SEMA_ERROR(expr, "A global variable or function name was expected here.");
}
Decl *symbol = expr->identifier_expr.decl;
if (!sema_analyse_decl(context, symbol)) return false;
bool should_be_const = char_is_upper(decl->name[0]);
if (should_be_const)
{

View File

@@ -729,7 +729,6 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
{
Decl *decl = expr->identifier_expr.decl;
decl = decl_flatten(decl);
switch (decl->decl_kind)
{
case DECL_FNTYPE:

View File

@@ -0,0 +1,26 @@
module mylib::ifaces;
interface IOp {
fn void op();
}
module mylib(<Type>);
import std::io;
import mylib::ifaces;
struct Op (IOp){
Type data;
}
fn void Op.op(&self) @dynamic => io::printn("op");
module myapp;
import mylib;
fn void test(void* tptr){
// this work
IOp iop = (Op(<int>)*)tptr;
iop.op();
// this don't work
iop = tptr; // #error: Casting a 'void*' to 'IOp' is not permitted
iop.op();
}
fn void! main(String[] args) {
Op(<int>)* t = mem::new(Op(<int>), {.data = 1});
test(&t);
}

View File

@@ -5,14 +5,8 @@ fn void any_compare()
int x;
any a = &x;
any b = &x;
void* v = &x;
any c = v;
assert(a == b);
assert(a == a);
assert(a.ptr == c.ptr);
assert(a != c);
bool aisc = a == c;
assert(!aisc);
}
def AnyAlias = any;