mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Simplify narrowing semantics.
This commit is contained in:
@@ -67,7 +67,7 @@ fn uint128! int_from_variant(variant arg, bool *is_neg) @private
|
||||
fn FloatType! float_from_variant(variant arg) @private
|
||||
{
|
||||
$if (env::F128_SUPPORT):
|
||||
if (arg.type == float128.typeid) return *((float128*)arg.ptr);
|
||||
if (arg.type == float128.typeid) return (FloatType)*((float128*)arg.ptr);
|
||||
$endif;
|
||||
$if (env::F16_SUPPORT):
|
||||
if (arg.type == float16.typeid) return *((float16*)arg.ptr);
|
||||
|
||||
@@ -550,7 +550,7 @@ static void setup_int_define(const char *id, uint64_t i, Type *type)
|
||||
id = symtab_add(id, (uint32_t) strlen(id), fnv1a(id, (uint32_t) strlen(id)), &token_type);
|
||||
Type *flat = type_flatten(type);
|
||||
assert(type_is_integer(flat));
|
||||
Expr *expr = expr_new_const_int(INVALID_SPAN, flat, i, true);
|
||||
Expr *expr = expr_new_const_int(INVALID_SPAN, flat, i);
|
||||
expr->type = type;
|
||||
if (expr_const_will_overflow(&expr->const_expr, flat->type_kind))
|
||||
{
|
||||
|
||||
@@ -185,7 +185,6 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
ConstKind const_kind : 8;
|
||||
bool narrowable : 1;
|
||||
bool is_character : 1;
|
||||
bool is_hex : 1;
|
||||
union
|
||||
@@ -2136,7 +2135,7 @@ bool decl_is_local(Decl *decl);
|
||||
|
||||
#define EXPR_NEW_TOKEN(kind_) expr_new(kind_, c->span)
|
||||
Expr *expr_new(ExprKind kind, SourceSpan start);
|
||||
Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v, bool narrowable);
|
||||
Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v);
|
||||
Expr *expr_new_const_bool(SourceSpan span, Type *type, bool value);
|
||||
Expr *expr_new_const_typeid(SourceSpan span, Type *type);
|
||||
bool expr_is_simple(Expr *expr);
|
||||
@@ -2174,8 +2173,8 @@ INLINE bool expr_is_const_member(Expr *expr);
|
||||
|
||||
INLINE void expr_rewrite_const_null(Expr *expr, Type *type);
|
||||
INLINE void expr_rewrite_const_bool(Expr *expr, Type *type, bool b);
|
||||
INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d, bool is_narrowable);
|
||||
INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v, bool narrowable);
|
||||
INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d);
|
||||
INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v);
|
||||
INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type);
|
||||
INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitializer *initializer);
|
||||
INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements);
|
||||
@@ -3156,7 +3155,7 @@ INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type)
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
}
|
||||
|
||||
INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v, bool narrowable)
|
||||
INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v)
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->type = type;
|
||||
@@ -3169,10 +3168,9 @@ INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v, bool narr
|
||||
(&expr->const_expr)->ixx.i.low = v;
|
||||
(&expr->const_expr)->ixx.type = kind;
|
||||
(&expr->const_expr)->const_kind = CONST_INTEGER;
|
||||
expr->const_expr.narrowable = narrowable;
|
||||
}
|
||||
|
||||
INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d, bool is_narrowable)
|
||||
INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d)
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->type = type;
|
||||
@@ -3194,7 +3192,6 @@ INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d, bool is_nar
|
||||
expr->const_expr = (ExprConst) {
|
||||
.fxx = (Float){ real, kind },
|
||||
.const_kind = CONST_FLOAT,
|
||||
.narrowable = is_narrowable,
|
||||
};
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
}
|
||||
|
||||
@@ -547,7 +547,6 @@ static inline ConstInitializer *initializer_for_index(ConstInitializer *initiali
|
||||
void expr_rewrite_to_const_zero(Expr *expr, Type *type)
|
||||
{
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
expr->const_expr.narrowable = true;
|
||||
switch (type->canonical->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
@@ -555,10 +554,10 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
UNREACHABLE
|
||||
case ALL_INTS:
|
||||
expr_rewrite_const_int(expr, type, 0, true);
|
||||
expr_rewrite_const_int(expr, type, 0);
|
||||
return;
|
||||
case ALL_FLOATS:
|
||||
expr_rewrite_const_float(expr, type, 0, true);
|
||||
expr_rewrite_const_float(expr, type, 0);
|
||||
break;
|
||||
case TYPE_BOOL:
|
||||
expr_rewrite_const_bool(expr, type, false);
|
||||
@@ -815,7 +814,7 @@ Expr *expr_new(ExprKind kind, SourceSpan start)
|
||||
return expr;
|
||||
}
|
||||
|
||||
Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v, bool narrowable)
|
||||
Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v)
|
||||
{
|
||||
Expr *expr = expr_calloc();
|
||||
expr->expr_kind = EXPR_CONST;
|
||||
@@ -830,7 +829,6 @@ Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v, bool narrowabl
|
||||
expr->const_expr.ixx.i.low = v;
|
||||
expr->const_expr.ixx.type = kind;
|
||||
expr->const_expr.const_kind = CONST_INTEGER;
|
||||
expr->const_expr.narrowable = narrowable;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ bool parse_range(ParseContext *c, Range *range)
|
||||
{
|
||||
// ..123 and :123
|
||||
range->start_from_end = false;
|
||||
range->start = exprid(expr_new_const_int(c->span, type_uint, 0, true));
|
||||
range->start = exprid(expr_new_const_int(c->span, type_uint, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1247,7 +1247,6 @@ Expr *parse_integer(ParseContext *c, Expr *left)
|
||||
expr_int->const_expr.const_kind = CONST_INTEGER;
|
||||
expr_int->const_expr.is_hex = hex_characters > 0;
|
||||
Type *type_base = NULL;
|
||||
expr_int->const_expr.narrowable = !type_bits;
|
||||
if (type_bits)
|
||||
{
|
||||
if (type_bits < 0 || !is_power_of_two((uint64_t)type_bits) || type_bits > 128)
|
||||
@@ -1449,7 +1448,6 @@ static Expr *parse_char_lit(ParseContext *c, Expr *left)
|
||||
Expr *expr_int = EXPR_NEW_TOKEN(EXPR_CONST);
|
||||
expr_int->const_expr.is_character = true;
|
||||
expr_int->const_expr.ixx.i = c->data.char_value;
|
||||
expr_int->const_expr.narrowable = true;
|
||||
expr_int->const_expr.const_kind = CONST_INTEGER;
|
||||
switch (c->data.width)
|
||||
{
|
||||
@@ -1515,7 +1513,6 @@ static Expr *parse_double(ParseContext *c, Expr *left)
|
||||
UNREACHABLE
|
||||
}
|
||||
number->const_expr.const_kind = CONST_FLOAT;
|
||||
number->const_expr.narrowable = true;
|
||||
advance(c);
|
||||
return number;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,7 @@ static bool cast_expr_inner(SemaContext *context, Expr *expr, Type *to_type, boo
|
||||
bool may_not_be_optional);
|
||||
static bool bitstruct_cast(Expr *expr, Type *from_type, Type *to, Type *to_type);
|
||||
static void sema_error_const_int_out_of_range(Expr *expr, Expr *problem, Type *to_type);
|
||||
static Expr *recursive_may_narrow_float(Expr *expr, Type *type);
|
||||
static Expr *recursive_may_narrow_int(Expr *expr, Type *type);
|
||||
static Expr *recursive_may_narrow(Expr *expr, Type *type);
|
||||
static void recursively_rewrite_untyped_list(Expr *expr, Expr **list);
|
||||
static inline bool cast_may_implicit_ptr(Type *from_pointee, Type *to_pointee);
|
||||
static inline bool cast_may_array(Type *from, Type *to, bool is_explicit);
|
||||
@@ -152,7 +151,7 @@ static bool pointer_to_integer(Expr *expr, Type *type)
|
||||
if (insert_runtime_cast_unless_const(expr, CAST_PTRINT, type)) return true;
|
||||
|
||||
// Revisit this to support pointers > 64 bits.
|
||||
expr_rewrite_const_int(expr, type, expr->const_expr.ptr, false);
|
||||
expr_rewrite_const_int(expr, type, expr->const_expr.ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -191,7 +190,6 @@ static bool pointer_to_pointer(Expr* expr, Type *type)
|
||||
|
||||
// Insert the cast, this removes the ability to narrow it.
|
||||
expr->type = type;
|
||||
expr->const_expr.narrowable = false;
|
||||
expr->const_expr.is_hex = false;
|
||||
return true;
|
||||
}
|
||||
@@ -205,7 +203,7 @@ static bool bool_to_int(Expr *expr, Type *canonical, Type *type)
|
||||
{
|
||||
if (insert_runtime_cast_unless_const(expr, CAST_BOOLINT, type)) return true;
|
||||
|
||||
expr_rewrite_const_int(expr, type, expr->const_expr.b ? 1 : 0, false);
|
||||
expr_rewrite_const_int(expr, type, expr->const_expr.b ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -219,7 +217,7 @@ static bool bool_to_float(Expr *expr, Type *canonical, Type *type)
|
||||
if (insert_runtime_cast_unless_const(expr, CAST_BOOLFP, type)) return true;
|
||||
|
||||
assert(expr->const_expr.const_kind == CONST_BOOL);
|
||||
expr_rewrite_const_float(expr, type, expr->const_expr.b ? 1.0 : 0.0, false);
|
||||
expr_rewrite_const_float(expr, type, expr->const_expr.b ? 1.0 : 0.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -275,7 +273,7 @@ static bool float_to_float(Expr* expr, Type *canonical, Type *type)
|
||||
if (insert_runtime_cast_unless_const(expr, CAST_FPFP, type)) return true;
|
||||
|
||||
// Otherwise rewrite the const, which may cause rounding.
|
||||
expr_rewrite_const_float(expr, type, expr->const_expr.fxx.f, false);
|
||||
expr_rewrite_const_float(expr, type, expr->const_expr.fxx.f);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -293,7 +291,6 @@ static bool float_to_integer(Expr *expr, Type *canonical, Type *type)
|
||||
expr->const_expr.ixx = int_from_real(d, canonical->type_kind);
|
||||
expr->const_expr.const_kind = CONST_INTEGER;
|
||||
expr->type = type;
|
||||
expr->const_expr.narrowable = false;
|
||||
expr->const_expr.is_hex = false;
|
||||
return true;
|
||||
}
|
||||
@@ -361,7 +358,6 @@ static bool integer_to_integer(Expr *expr, Type *canonical, Type *type)
|
||||
expr->const_expr.ixx = int_conv(expr->const_expr.ixx, canonical->type_kind);
|
||||
expr->const_expr.const_kind = CONST_INTEGER;
|
||||
expr->type = type;
|
||||
expr->const_expr.narrowable = false;
|
||||
expr->const_expr.is_hex = false;
|
||||
return true;
|
||||
}
|
||||
@@ -398,7 +394,7 @@ static bool integer_to_float(Expr *expr, Type *canonical, Type *type)
|
||||
if (insert_runtime_cast_unless_const(expr, CAST_INTFP, type)) return true;
|
||||
|
||||
Real f = int_to_real(expr->const_expr.ixx);
|
||||
expr_rewrite_const_float(expr, type, f, false);
|
||||
expr_rewrite_const_float(expr, type, f);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -441,7 +437,7 @@ static void enum_to_int_lowering(Expr* expr)
|
||||
if (expr->expr_kind == EXPR_CONST)
|
||||
{
|
||||
assert(expr->const_expr.const_kind == CONST_ENUM);
|
||||
expr_rewrite_const_int(expr, underlying_type, expr->const_expr.enum_err_val->enum_constant.ordinal, false);
|
||||
expr_rewrite_const_int(expr, underlying_type, expr->const_expr.enum_err_val->enum_constant.ordinal);
|
||||
|
||||
}
|
||||
expr->type = type_add_optional(underlying_type, IS_OPTIONAL(expr));
|
||||
@@ -860,17 +856,20 @@ bool cast_may_bool_convert(Type *type)
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE Expr *recursive_may_narrow_floatid(ExprId expr, Type *type)
|
||||
{
|
||||
return recursive_may_narrow_float(exprptr(expr), type);
|
||||
}
|
||||
|
||||
Expr *recursive_may_narrow_float(Expr *expr, Type *type)
|
||||
/**
|
||||
* Check whether an expression may narrow.
|
||||
* 1. If it has an intrinsic type, then compare it against the type. If the bitwidth is smaller or same => ok
|
||||
* 2. If it is a constant, then if it fits in the type it is ok.
|
||||
* 3. If it has sub expressions, recursively check those if they affect the type.
|
||||
* 4. Widening casts are ignored, all other casts are opaque.
|
||||
*/
|
||||
Expr *recursive_may_narrow(Expr *expr, Type *type)
|
||||
{
|
||||
RETRY:
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_BINARY:
|
||||
case EXPR_BITASSIGN:
|
||||
case EXPR_BINARY:
|
||||
switch (expr->binary_expr.operator)
|
||||
{
|
||||
case BINARYOP_ERROR:
|
||||
@@ -880,15 +879,33 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
|
||||
case BINARYOP_ADD:
|
||||
case BINARYOP_DIV:
|
||||
case BINARYOP_MOD:
|
||||
case BINARYOP_ELSE:
|
||||
{
|
||||
Expr *res = recursive_may_narrow_float(exprptr(expr->binary_expr.left), type);
|
||||
if (res) return res;
|
||||
return recursive_may_narrow_float(exprptr(expr->binary_expr.right), type);
|
||||
}
|
||||
case BINARYOP_BIT_OR:
|
||||
case BINARYOP_BIT_XOR:
|
||||
case BINARYOP_BIT_AND:
|
||||
case BINARYOP_ELSE:
|
||||
{
|
||||
// *, -, +, /, %, |, ^, &, ?? -> check both sides.
|
||||
Expr *res = recursive_may_narrow(exprptr(expr->binary_expr.left), type);
|
||||
if (res) return res;
|
||||
expr = exprptr(expr->binary_expr.right);
|
||||
goto RETRY;
|
||||
}
|
||||
case BINARYOP_SHR:
|
||||
case BINARYOP_SHL:
|
||||
case BINARYOP_ASSIGN:
|
||||
case BINARYOP_ADD_ASSIGN:
|
||||
case BINARYOP_BIT_AND_ASSIGN:
|
||||
case BINARYOP_BIT_OR_ASSIGN:
|
||||
case BINARYOP_BIT_XOR_ASSIGN:
|
||||
case BINARYOP_DIV_ASSIGN:
|
||||
case BINARYOP_MOD_ASSIGN:
|
||||
case BINARYOP_MULT_ASSIGN:
|
||||
case BINARYOP_SHR_ASSIGN:
|
||||
case BINARYOP_SHL_ASSIGN:
|
||||
case BINARYOP_SUB_ASSIGN:
|
||||
// For shifts and assignment, ignore the right hand side.
|
||||
expr = exprptr(expr->binary_expr.left);
|
||||
goto RETRY;
|
||||
case BINARYOP_AND:
|
||||
case BINARYOP_OR:
|
||||
case BINARYOP_GT:
|
||||
@@ -897,296 +914,114 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type)
|
||||
case BINARYOP_LE:
|
||||
case BINARYOP_NE:
|
||||
case BINARYOP_EQ:
|
||||
case BINARYOP_SHR:
|
||||
case BINARYOP_SHL:
|
||||
case BINARYOP_BIT_AND_ASSIGN:
|
||||
case BINARYOP_BIT_OR_ASSIGN:
|
||||
case BINARYOP_BIT_XOR_ASSIGN:
|
||||
case BINARYOP_SHR_ASSIGN:
|
||||
case BINARYOP_SHL_ASSIGN:
|
||||
// This type is bool, so check should never happen.
|
||||
UNREACHABLE
|
||||
case BINARYOP_ASSIGN:
|
||||
case BINARYOP_ADD_ASSIGN:
|
||||
case BINARYOP_DIV_ASSIGN:
|
||||
case BINARYOP_MOD_ASSIGN:
|
||||
case BINARYOP_MULT_ASSIGN:
|
||||
case BINARYOP_SUB_ASSIGN:
|
||||
return recursive_may_narrow_float(exprptr(expr->binary_expr.left), type);
|
||||
}
|
||||
UNREACHABLE
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
case EXPR_CALL:
|
||||
case EXPR_POISONED:
|
||||
case EXPR_BITACCESS:
|
||||
case EXPR_ACCESS:
|
||||
case EXPR_CATCH_UNWRAP:
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
case EXPR_COND:
|
||||
case EXPR_DECL:
|
||||
case EXPR_CT_IDENT:
|
||||
case EXPR_DESIGNATOR:
|
||||
case EXPR_EXPR_BLOCK:
|
||||
case EXPR_MACRO_BLOCK:
|
||||
case EXPR_IDENTIFIER:
|
||||
case EXPR_SLICE_ASSIGN:
|
||||
case EXPR_SLICE_COPY:
|
||||
case EXPR_SLICE:
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_RETVAL:
|
||||
case EXPR_TYPEID_INFO:
|
||||
if (type_size(expr->type) > type_size(type)) return expr;
|
||||
return NULL;
|
||||
case EXPR_BUILTIN_ACCESS:
|
||||
switch (expr->builtin_access_expr.kind)
|
||||
{
|
||||
case ACCESS_LEN:
|
||||
// Special: we may resize this, but not smaller than cint.
|
||||
if (type_size(type) < type_size(type_cint)) return expr;
|
||||
return NULL;
|
||||
case ACCESS_PTR:
|
||||
case ACCESS_TYPEOFANY:
|
||||
case ACCESS_ENUMNAME:
|
||||
case ACCESS_FAULTNAME:
|
||||
// For the rest, just check size.
|
||||
goto CHECK_SIZE;
|
||||
}
|
||||
UNREACHABLE;
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
return recursive_may_narrow_float(VECLAST(expr->expression_list), type);
|
||||
case EXPR_GROUP:
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
return recursive_may_narrow_float(expr->inner_expr, type);
|
||||
case EXPR_RETHROW:
|
||||
return recursive_may_narrow_float(expr->rethrow_expr.inner, type);
|
||||
// Only the last expression counts for narrowing.
|
||||
// It's unclear if this can happen.
|
||||
expr = VECLAST(expr->expression_list);
|
||||
goto RETRY;
|
||||
case EXPR_TERNARY:
|
||||
{
|
||||
Expr *res = recursive_may_narrow_floatid(expr->ternary_expr.then_expr ? expr->ternary_expr.then_expr
|
||||
: expr->ternary_expr.cond, type);
|
||||
// In the case a ?: b -> check a and b
|
||||
// In the case a ? b : c -> check b and c
|
||||
Expr *res = recursive_may_narrow(exprptr(expr->ternary_expr.then_expr
|
||||
? expr->ternary_expr.then_expr
|
||||
: expr->ternary_expr.cond), type);
|
||||
if (res) return res;
|
||||
return recursive_may_narrow_floatid(expr->ternary_expr.else_expr, type);
|
||||
expr = exprptr(expr->ternary_expr.else_expr);
|
||||
goto RETRY;
|
||||
}
|
||||
case EXPR_CAST:
|
||||
return recursive_may_narrow_floatid(expr->cast_expr.expr, type);
|
||||
case EXPR_CONST:
|
||||
if (!expr->const_expr.narrowable)
|
||||
switch (expr->cast_expr.kind)
|
||||
{
|
||||
return type_size(expr->type) > type_size(type) ? expr : NULL;
|
||||
case CAST_INTINT:
|
||||
case CAST_FPFP:
|
||||
// If this is a narrowing cast that makes it smaller that then target type
|
||||
// we're done.
|
||||
if (type_size(type) >= type_size(expr->type))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
// Otherwise just look through it.
|
||||
expr = exprptr(expr->cast_expr.expr);
|
||||
goto RETRY;
|
||||
default:
|
||||
// For all other casts we regard them as opaque.
|
||||
goto CHECK_SIZE;
|
||||
}
|
||||
case EXPR_CONST:
|
||||
// For constants, just check that they will fit.
|
||||
if (type_is_integer(type))
|
||||
{
|
||||
assert(expr->const_expr.const_kind == CONST_INTEGER || expr->const_expr.const_kind == CONST_ENUM);
|
||||
if (expr_const_will_overflow(&expr->const_expr, type_flatten(type)->type_kind))
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
assert(type_is_float(type));
|
||||
assert(expr->const_expr.const_kind == CONST_FLOAT);
|
||||
if (!expr_const_float_fits_type(&expr->const_expr, type_flatten(type)->type_kind))
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
return NULL;
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_FLATPATH:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
case EXPR_TYPEID:
|
||||
case EXPR_TYPEINFO:
|
||||
case EXPR_CT_CALL:
|
||||
case EXPR_NOP:
|
||||
case EXPR_CATCH:
|
||||
case EXPR_BUILTIN:
|
||||
case EXPR_TRY_UNWRAP:
|
||||
case EXPR_TRY_UNWRAP_CHAIN:
|
||||
case EXPR_SUBSCRIPT_ADDR:
|
||||
case EXPR_VARIANTSWITCH:
|
||||
case EXPR_COMPILER_CONST:
|
||||
case EXPR_STRINGIFY:
|
||||
case EXPR_CT_EVAL:
|
||||
case EXPR_VARIANT:
|
||||
case EXPR_POINTER_OFFSET:
|
||||
case EXPR_CT_ARG:
|
||||
case EXPR_ASM:
|
||||
case EXPR_VASPLAT:
|
||||
case EXPR_OPERATOR_CHARS:
|
||||
case EXPR_CT_CHECKS:
|
||||
case EXPR_SUBSCRIPT_ASSIGN:
|
||||
case EXPR_SWIZZLE:
|
||||
case EXPR_LAMBDA:
|
||||
UNREACHABLE
|
||||
case EXPR_BUILTIN_ACCESS:
|
||||
case EXPR_TEST_HOOK:
|
||||
return false;
|
||||
case EXPR_POST_UNARY:
|
||||
return recursive_may_narrow_float(expr->unary_expr.expr, type);
|
||||
case EXPR_TRY:
|
||||
return recursive_may_narrow_float(expr->inner_expr, type);
|
||||
case EXPR_UNARY:
|
||||
{
|
||||
switch (expr->unary_expr.operator)
|
||||
{
|
||||
case UNARYOP_DEREF:
|
||||
return false;
|
||||
case UNARYOP_ERROR:
|
||||
case UNARYOP_ADDR:
|
||||
case UNARYOP_NOT:
|
||||
case UNARYOP_TADDR:
|
||||
UNREACHABLE
|
||||
case UNARYOP_NEG:
|
||||
case UNARYOP_BITNEG:
|
||||
case UNARYOP_INC:
|
||||
case UNARYOP_DEC:
|
||||
return recursive_may_narrow_float(expr->unary_expr.expr, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
INLINE Expr *recursive_may_narrow_intid(ExprId expr, Type *type)
|
||||
{
|
||||
assert(expr);
|
||||
return recursive_may_narrow_int(exprptr(expr), type);
|
||||
}
|
||||
|
||||
Expr *recursive_may_narrow_int(Expr *expr, Type *type)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_BITASSIGN:
|
||||
case EXPR_BINARY:
|
||||
switch (expr->binary_expr.operator)
|
||||
{
|
||||
case BINARYOP_ERROR:
|
||||
UNREACHABLE
|
||||
case BINARYOP_MULT:
|
||||
case BINARYOP_SUB:
|
||||
case BINARYOP_ADD:
|
||||
case BINARYOP_DIV:
|
||||
case BINARYOP_MOD:
|
||||
case BINARYOP_BIT_OR:
|
||||
case BINARYOP_BIT_XOR:
|
||||
case BINARYOP_BIT_AND:
|
||||
case BINARYOP_ELSE:
|
||||
{
|
||||
Expr *res = recursive_may_narrow_int(exprptr(expr->binary_expr.left), type);
|
||||
if (res) return res;
|
||||
return recursive_may_narrow_int(exprptr(expr->binary_expr.right), type);
|
||||
}
|
||||
case BINARYOP_AND:
|
||||
case BINARYOP_OR:
|
||||
case BINARYOP_GT:
|
||||
case BINARYOP_GE:
|
||||
case BINARYOP_LT:
|
||||
case BINARYOP_LE:
|
||||
case BINARYOP_NE:
|
||||
case BINARYOP_EQ:
|
||||
return NULL;
|
||||
case BINARYOP_SHR:
|
||||
case BINARYOP_SHL:
|
||||
case BINARYOP_ASSIGN:
|
||||
case BINARYOP_ADD_ASSIGN:
|
||||
case BINARYOP_BIT_AND_ASSIGN:
|
||||
case BINARYOP_BIT_OR_ASSIGN:
|
||||
case BINARYOP_BIT_XOR_ASSIGN:
|
||||
case BINARYOP_DIV_ASSIGN:
|
||||
case BINARYOP_MOD_ASSIGN:
|
||||
case BINARYOP_MULT_ASSIGN:
|
||||
case BINARYOP_SHR_ASSIGN:
|
||||
case BINARYOP_SHL_ASSIGN:
|
||||
case BINARYOP_SUB_ASSIGN:
|
||||
return recursive_may_narrow_int(exprptr(expr->binary_expr.left), type);
|
||||
}
|
||||
UNREACHABLE
|
||||
case EXPR_MACRO_BODY_EXPANSION:
|
||||
case EXPR_CALL:
|
||||
case EXPR_POISONED:
|
||||
case EXPR_BITACCESS:
|
||||
case EXPR_ACCESS:
|
||||
case EXPR_CATCH_UNWRAP:
|
||||
case EXPR_COMPOUND_LITERAL:
|
||||
case EXPR_COND:
|
||||
case EXPR_DECL:
|
||||
case EXPR_CT_IDENT:
|
||||
case EXPR_DESIGNATOR:
|
||||
case EXPR_EXPR_BLOCK:
|
||||
case EXPR_MACRO_BLOCK:
|
||||
case EXPR_IDENTIFIER:
|
||||
case EXPR_SLICE_ASSIGN:
|
||||
case EXPR_SLICE_COPY:
|
||||
case EXPR_SLICE:
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_RETVAL:
|
||||
case EXPR_SUBSCRIPT_ASSIGN:
|
||||
case EXPR_TYPEID_INFO:
|
||||
if (type_size(expr->type) > type_size(type)) return expr;
|
||||
return NULL;
|
||||
case EXPR_BUILTIN_ACCESS:
|
||||
switch (expr->builtin_access_expr.kind)
|
||||
{
|
||||
case ACCESS_LEN:
|
||||
if (type_size(type) < type_size(type_cint)) return expr;
|
||||
return NULL;
|
||||
case ACCESS_TYPEOFANY:
|
||||
case ACCESS_PTR:
|
||||
case ACCESS_ENUMNAME:
|
||||
case ACCESS_FAULTNAME:
|
||||
return NULL;
|
||||
}
|
||||
UNREACHABLE;
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
return recursive_may_narrow_int(VECLAST(expr->expression_list), type);
|
||||
case EXPR_RETHROW:
|
||||
return recursive_may_narrow_int(expr->rethrow_expr.inner, type);
|
||||
case EXPR_TERNARY:
|
||||
{
|
||||
Expr *res = recursive_may_narrow_intid(expr->ternary_expr.then_expr ? expr->ternary_expr.then_expr
|
||||
: expr->ternary_expr.cond, type);
|
||||
if (res) return res;
|
||||
return recursive_may_narrow_intid(expr->ternary_expr.else_expr, type);
|
||||
}
|
||||
case EXPR_CAST:
|
||||
return recursive_may_narrow_intid(expr->cast_expr.expr, type);
|
||||
case EXPR_CONST:
|
||||
assert(expr->const_expr.const_kind == CONST_INTEGER || expr->const_expr.const_kind == CONST_ENUM);
|
||||
if (expr_const_will_overflow(&expr->const_expr, type_flatten(type)->type_kind))
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
return NULL;
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_FLATPATH:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_DESIGNATED_INITIALIZER_LIST:
|
||||
case EXPR_TYPEID:
|
||||
case EXPR_TYPEINFO:
|
||||
case EXPR_CT_CALL:
|
||||
case EXPR_NOP:
|
||||
case EXPR_BUILTIN:
|
||||
case EXPR_TRY_UNWRAP:
|
||||
case EXPR_TRY_UNWRAP_CHAIN:
|
||||
case EXPR_SUBSCRIPT_ADDR:
|
||||
case EXPR_VARIANTSWITCH:
|
||||
case EXPR_COMPILER_CONST:
|
||||
case EXPR_STRINGIFY:
|
||||
case EXPR_CT_EVAL:
|
||||
case EXPR_VARIANT:
|
||||
case EXPR_POINTER_OFFSET:
|
||||
case EXPR_CT_ARG:
|
||||
case EXPR_ASM:
|
||||
case EXPR_VASPLAT:
|
||||
case EXPR_OPERATOR_CHARS:
|
||||
case EXPR_CT_CHECKS:
|
||||
case EXPR_SWIZZLE:
|
||||
case EXPR_LAMBDA:
|
||||
UNREACHABLE
|
||||
case EXPR_TEST_HOOK:
|
||||
return false;
|
||||
case EXPR_POST_UNARY:
|
||||
return recursive_may_narrow_int(expr->unary_expr.expr, type);
|
||||
case EXPR_TRY:
|
||||
case EXPR_CATCH:
|
||||
expr = expr->unary_expr.expr;
|
||||
goto RETRY;
|
||||
case EXPR_GROUP:
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
return recursive_may_narrow_int(expr->inner_expr, type);
|
||||
expr = expr->inner_expr;
|
||||
goto RETRY;
|
||||
case EXPR_RETHROW:
|
||||
expr = expr->rethrow_expr.inner;
|
||||
goto RETRY;
|
||||
case EXPR_UNARY:
|
||||
{
|
||||
switch (expr->unary_expr.operator)
|
||||
{
|
||||
case UNARYOP_ERROR:
|
||||
case UNARYOP_DEREF:
|
||||
case UNARYOP_ADDR:
|
||||
case UNARYOP_NOT:
|
||||
case UNARYOP_TADDR:
|
||||
UNREACHABLE
|
||||
case UNARYOP_DEREF:
|
||||
// Check sizes.
|
||||
goto CHECK_SIZE;
|
||||
case UNARYOP_NEG:
|
||||
case UNARYOP_BITNEG:
|
||||
case UNARYOP_INC:
|
||||
case UNARYOP_DEC:
|
||||
return recursive_may_narrow_int(expr->unary_expr.expr, type);
|
||||
expr = expr->unary_expr.expr;
|
||||
goto RETRY;
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Check type sizes
|
||||
goto CHECK_SIZE;
|
||||
}
|
||||
UNREACHABLE
|
||||
CHECK_SIZE:
|
||||
if (type_size(expr->type) > type_size(type)) return expr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sema_error_const_int_out_of_range(Expr *expr, Expr *problem, Type *to_type)
|
||||
@@ -1267,9 +1102,7 @@ bool cast_implicit_silent(SemaContext *context, Expr *expr, Type *to_type)
|
||||
|
||||
bool cast_explicit(SemaContext *context, Expr *expr, Type *to_type)
|
||||
{
|
||||
if (!cast_expr_inner(context, expr, to_type, true, false, false)) return false;
|
||||
if (expr_is_const(expr)) expr->const_expr.narrowable = false;
|
||||
return true;
|
||||
return cast_expr_inner(context, expr, to_type, true, false, false);
|
||||
}
|
||||
|
||||
static inline bool cast_with_optional(Expr *expr, Type *to_type, bool add_optional)
|
||||
@@ -1491,10 +1324,12 @@ RETRY:
|
||||
return false;
|
||||
}
|
||||
if (to_size == from_size) goto CAST;
|
||||
Expr *problem = recursive_may_narrow_int(expr, to);
|
||||
assert(to == type_flatten(to));
|
||||
Expr *problem = recursive_may_narrow(expr, to);
|
||||
if (problem)
|
||||
{
|
||||
if (no_report) return false;
|
||||
expr = problem;
|
||||
goto REQUIRE_CAST;
|
||||
}
|
||||
goto CAST;
|
||||
@@ -1573,10 +1408,11 @@ RETRY:
|
||||
return false;
|
||||
}
|
||||
if (to_size == from_size) goto CAST;
|
||||
Expr *problem = recursive_may_narrow_float(expr, to);
|
||||
Expr *problem = recursive_may_narrow(expr, to);
|
||||
if (problem)
|
||||
{
|
||||
if (silent) return false;
|
||||
expr = problem;
|
||||
goto REQUIRE_CAST;
|
||||
}
|
||||
goto CAST;
|
||||
@@ -2133,7 +1969,6 @@ bool cast(Expr *expr, Type *to_type)
|
||||
expr->type = type_add_optional(to_type, from_is_optional);
|
||||
if (expr->expr_kind == EXPR_CONST)
|
||||
{
|
||||
expr->const_expr.narrowable = false;
|
||||
expr->const_expr.is_hex = false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -2783,7 +2783,6 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
|
||||
}
|
||||
if (init_expr->expr_kind == EXPR_CONST)
|
||||
{
|
||||
init_expr->const_expr.narrowable = false;
|
||||
init_expr->const_expr.is_hex = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2889,7 +2889,7 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e
|
||||
|
||||
if (name == kw_offsetof)
|
||||
{
|
||||
expr_rewrite_const_int(expr, type_usz, parent->const_expr.member.offset, true);
|
||||
expr_rewrite_const_int(expr, type_usz, parent->const_expr.member.offset);
|
||||
return true;
|
||||
}
|
||||
TypeProperty type_property = type_property_by_name(name);
|
||||
@@ -2904,8 +2904,8 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e
|
||||
return true;
|
||||
case TYPE_PROPERTY_ALIGNOF:
|
||||
expr_rewrite_const_int(expr, type_usz,
|
||||
type_min_alignment(parent->const_expr.member.offset, parent->const_expr.member.align),
|
||||
true);
|
||||
type_min_alignment(parent->const_expr.member.offset,
|
||||
parent->const_expr.member.align));
|
||||
return true;
|
||||
case TYPE_PROPERTY_MEMBERSOF:
|
||||
sema_create_const_membersof(context, expr, decl->type->canonical, parent->const_expr.member.align, parent->const_expr.member.offset);
|
||||
@@ -2977,7 +2977,7 @@ static inline bool sema_create_const_kind(Expr *expr, Type *type)
|
||||
Type *type_for_kind = type_kind ? type_kind->type : type_char;
|
||||
unsigned val = type_get_introspection_kind(type->type_kind);
|
||||
assert(type_for_kind->type_kind == TYPE_ENUM);
|
||||
expr_rewrite_const_int(expr, type_flatten(type_for_kind), val, false);
|
||||
expr_rewrite_const_int(expr, type_flatten(type_for_kind), val);
|
||||
return cast(expr, type_for_kind);
|
||||
}
|
||||
|
||||
@@ -3002,7 +3002,7 @@ static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
expr_rewrite_const_int(expr, type_usz, len, true);
|
||||
expr_rewrite_const_int(expr, type_usz, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3373,7 +3373,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
return sema_analyse_expr(context, expr);
|
||||
case TYPE_PROPERTY_ELEMENTS:
|
||||
if (!type_kind_is_enumlike(flat->type_kind)) return false;
|
||||
expr_rewrite_const_int(expr, type_isz, vec_size(flat->decl->enums.values), true);
|
||||
expr_rewrite_const_int(expr, type_isz, vec_size(flat->decl->enums.values));
|
||||
return true;
|
||||
case TYPE_PROPERTY_VALUES:
|
||||
if (!type_kind_is_enumlike(flat->type_kind)) return false;
|
||||
@@ -3398,7 +3398,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
expr_rewrite_const_typeid(expr, type_infoptr(flat->function.signature->rtype)->type);
|
||||
return true;
|
||||
case TYPE_PROPERTY_SIZEOF:
|
||||
expr_rewrite_const_int(expr, type_usz, type_size(type), true);
|
||||
expr_rewrite_const_int(expr, type_usz, type_size(type));
|
||||
return true;
|
||||
case TYPE_PROPERTY_NAMEOF:
|
||||
sema_expr_rewrite_to_type_nameof(expr, type, TOKEN_CT_NAMEOF);
|
||||
@@ -3410,7 +3410,7 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
{
|
||||
AlignSize align;
|
||||
if (!sema_set_abi_alignment(context, type, &align)) return false;
|
||||
expr_rewrite_const_int(expr, type_usz, align, true);
|
||||
expr_rewrite_const_int(expr, type_usz, align);
|
||||
return true;
|
||||
}
|
||||
case TYPE_PROPERTY_EXTNAMEOF:
|
||||
@@ -3442,7 +3442,7 @@ static inline bool sema_expr_analyse_swizzle(SemaContext *context, Expr *expr, E
|
||||
{
|
||||
expr->expr_kind = EXPR_SUBSCRIPT_ADDR;
|
||||
expr->subscript_expr = (ExprSubscript) {
|
||||
.range.start = exprid(expr_new_const_int(expr->span, type_usz, index, true)),
|
||||
.range.start = exprid(expr_new_const_int(expr->span, type_usz, index)),
|
||||
.expr = exprid(parent)
|
||||
};
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
@@ -3557,12 +3557,12 @@ CHECK_DEEPER:
|
||||
}
|
||||
if (flat_type->type_kind == TYPE_ARRAY || flat_type->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
expr_rewrite_const_int(expr, type_isz, flat_type->array.len, true);
|
||||
expr_rewrite_const_int(expr, type_isz, flat_type->array.len);
|
||||
return true;
|
||||
}
|
||||
if (flat_type->type_kind == TYPE_UNTYPED_LIST)
|
||||
{
|
||||
expr_rewrite_const_int(expr, type_isz, vec_size(current_parent->const_expr.untyped_list), true);
|
||||
expr_rewrite_const_int(expr, type_isz, vec_size(current_parent->const_expr.untyped_list));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4440,7 +4440,7 @@ static bool sema_expr_analyse_sub(SemaContext *context, Expr *expr, Expr *left,
|
||||
if (expr_both_const(left, right) && sema_constant_fold_ops(left))
|
||||
{
|
||||
expr_rewrite_const_int(expr, type_isz, (left->const_expr.ptr - right->const_expr.ptr) /
|
||||
type_size(left_type->pointer), false);
|
||||
type_size(left_type->pointer));
|
||||
return true;
|
||||
}
|
||||
// 3b. Set the type
|
||||
@@ -6043,15 +6043,15 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr *
|
||||
case BUILTIN_DEF_LINE:
|
||||
if (context->original_inline_line)
|
||||
{
|
||||
expr_rewrite_const_int(expr, type_isz, context->original_inline_line, true);
|
||||
expr_rewrite_const_int(expr, type_isz, context->original_inline_line);
|
||||
}
|
||||
else
|
||||
{
|
||||
expr_rewrite_const_int(expr, type_isz, expr->span.row, true);
|
||||
expr_rewrite_const_int(expr, type_isz, expr->span.row);
|
||||
}
|
||||
return true;
|
||||
case BUILTIN_DEF_LINE_RAW:
|
||||
expr_rewrite_const_int(expr, type_isz, expr->span.row, true);
|
||||
expr_rewrite_const_int(expr, type_isz, expr->span.row);
|
||||
return true;
|
||||
case BUILTIN_DEF_FUNCTION:
|
||||
switch (context->call_env.kind)
|
||||
@@ -6357,7 +6357,7 @@ static inline bool sema_expr_analyse_ct_alignof(SemaContext *context, Expr *expr
|
||||
type = result_type;
|
||||
}
|
||||
|
||||
expr_rewrite_const_int(expr, type_isz, align, true);
|
||||
expr_rewrite_const_int(expr, type_isz, align);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6811,7 +6811,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Expr *expr)
|
||||
switch (type)
|
||||
{
|
||||
case TOKEN_CT_VACOUNT:
|
||||
expr_rewrite_const_int(expr, type_usz, vec_size(context->macro_varargs), true);
|
||||
expr_rewrite_const_int(expr, type_usz, vec_size(context->macro_varargs));
|
||||
return true;
|
||||
case TOKEN_CT_VAARG:
|
||||
{
|
||||
@@ -6965,7 +6965,7 @@ static inline bool sema_expr_analyse_ct_offsetof(SemaContext *context, Expr *exp
|
||||
type = result_type;
|
||||
}
|
||||
|
||||
expr_rewrite_const_int(expr, type_isz, offset, true);
|
||||
expr_rewrite_const_int(expr, type_isz, offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
vec_add(expr_list->expression_list, decl_expr);
|
||||
Expr *sub = expr_new_expr(EXPR_SUBSCRIPT, element);
|
||||
sub->subscript_expr.expr = exprid(expr_variable(decl));
|
||||
sub->subscript_expr.range.start = exprid(expr_new_const_int(element->span, type_usz, 0, true));
|
||||
sub->subscript_expr.range.start = exprid(expr_new_const_int(element->span, type_usz, 0));
|
||||
vec_add(expr_list->expression_list, sub);
|
||||
if (!sema_analyse_expr_rhs(context, inner_type, expr_list, true)) return false;
|
||||
elements[i] = expr_list;
|
||||
@@ -289,7 +289,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
|
||||
{
|
||||
sub = expr_new_expr(EXPR_SUBSCRIPT, element);
|
||||
sub->subscript_expr.expr = exprid(expr_variable(decl));
|
||||
sub->subscript_expr.range.start = exprid(expr_new_const_int(element->span, type_usz, 1, true));
|
||||
sub->subscript_expr.range.start = exprid(expr_new_const_int(element->span, type_usz, 1));
|
||||
vec_insert_at(elements, i + j, sub);
|
||||
if (!sema_analyse_expr_rhs(context, inner_type, sub, true)) return false;
|
||||
}
|
||||
|
||||
@@ -1432,7 +1432,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
if (!len_call)
|
||||
{
|
||||
// Create const len if missing.
|
||||
len_call = expr_new_const_int(enumerator->span, type_isz, array_len, true);
|
||||
len_call = expr_new_const_int(enumerator->span, type_isz, array_len);
|
||||
}
|
||||
if (!cast_implicit(context, len_call, index_type)) return false;
|
||||
// __idx$ = (IndexType)(@__enum$.len()) (or const)
|
||||
@@ -1446,7 +1446,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
if (!cast_implicit(context, len_call, index_type)) return false;
|
||||
vec_add(expressions, expr_generate_decl(len_decl, len_call));
|
||||
}
|
||||
Expr *idx_init = expr_new_const_int(idx_decl->span, index_type, 0, true);
|
||||
Expr *idx_init = expr_new_const_int(idx_decl->span, index_type, 0);
|
||||
vec_add(expressions, expr_generate_decl(idx_decl, idx_init));
|
||||
}
|
||||
|
||||
@@ -1462,7 +1462,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
cond = expr_new(EXPR_BINARY, idx_decl->span);
|
||||
cond->binary_expr.operator = BINARYOP_GT;
|
||||
cond->binary_expr.left = exprid(expr_variable(idx_decl));
|
||||
Expr *rhs = expr_new_const_int(enumerator->span, index_type, 0, true);
|
||||
Expr *rhs = expr_new_const_int(enumerator->span, index_type, 0);
|
||||
cond->binary_expr.right = exprid(rhs);
|
||||
|
||||
// Create --__idx$
|
||||
@@ -1485,7 +1485,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen
|
||||
}
|
||||
else
|
||||
{
|
||||
Expr *rhs = expr_new_const_int(enumerator->span, type_isz, array_len, true);
|
||||
Expr *rhs = expr_new_const_int(enumerator->span, type_isz, array_len);
|
||||
cond->binary_expr.right = exprid(rhs);
|
||||
}
|
||||
|
||||
@@ -2396,7 +2396,7 @@ static inline bool sema_analyse_ct_foreach_stmt(SemaContext *context, Ast *state
|
||||
}
|
||||
if (index)
|
||||
{
|
||||
index->var.init_expr = expr_new_const_int(index->span, type_int, i, true);
|
||||
index->var.init_expr = expr_new_const_int(index->span, type_int, i);
|
||||
index->type = type_int;
|
||||
}
|
||||
if (!sema_analyse_compound_stmt(context, compound_stmt)) goto FAILED;
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.93"
|
||||
#define COMPILER_VERSION "0.4.94"
|
||||
@@ -0,0 +1,9 @@
|
||||
fn void main()
|
||||
{
|
||||
long x;
|
||||
|
||||
int i = (char)x; // Ok
|
||||
char c;
|
||||
short s1 = (long)c; // Ok
|
||||
short s2 = (long)i; // #error: 'int' cannot implicitly be converted
|
||||
}
|
||||
Reference in New Issue
Block a user