Simplify narrowing semantics.

This commit is contained in:
Christoffer Lerno
2023-03-02 22:04:15 +01:00
parent 3449d2ea88
commit a2911292d8
12 changed files with 165 additions and 330 deletions

View File

@@ -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);

View File

@@ -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))
{

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.93"
#define COMPILER_VERSION "0.4.94"

View File

@@ -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
}