mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- 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:
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
26
test/test_suite/any/casting_voidptr_to_any.c3
Normal file
26
test/test_suite/any/casting_voidptr_to_any.c3
Normal 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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user