Ordinal based enums.

This commit is contained in:
Christoffer Lerno
2022-05-07 17:28:50 +02:00
parent 15e1db78a7
commit 29a9769651
26 changed files with 465 additions and 440 deletions

View File

@@ -56,9 +56,9 @@ fn void! File.open(File* file, char[] filename, char[] mode)
enum Seek
{
SET = 0,
CURSOR = 1,
END = 2
SET,
CURSOR,
END
}
fault IoError
@@ -84,10 +84,10 @@ fn void! File.seek(File *file, long offset, Seek seekMode = Seek.SET)
{
switch (libc::errno())
{
case EBADF: return IoError.FILE_NOT_SEEKABLE!;
case EINVAL: return IoError.FILE_INVALID_POSITION!;
case EOVERFLOW: return IoError.FILE_OVERFLOW!;
case ESPIPE: return IoError.FILE_IS_PIPE!;
case errno::EBADF: return IoError.FILE_NOT_SEEKABLE!;
case errno::EINVAL: return IoError.FILE_INVALID_POSITION!;
case errno::EOVERFLOW: return IoError.FILE_OVERFLOW!;
case errno::ESPIPE: return IoError.FILE_IS_PIPE!;
default: return IoError.UNKNOWN_ERROR!;
}
}
@@ -110,17 +110,17 @@ fn void! File.close(File *file) @inline
{
switch (libc::errno())
{
case ECONNRESET:
case EBADF: return IoError.FILE_NOT_VALID!;
case EINTR: return IoError.INTERRUPTED!;
case EDQUOT:
case EFAULT:
case EAGAIN:
case EFBIG:
case ENETDOWN:
case ENETUNREACH:
case ENOSPC:
case EIO: return IoError.FILE_INCOMPLETE_WRITE!;
case errno::ECONNRESET:
case errno::EBADF: return IoError.FILE_NOT_VALID!;
case errno::EINTR: return IoError.INTERRUPTED!;
case errno::EDQUOT:
case errno::EFAULT:
case errno::EAGAIN:
case errno::EFBIG:
case errno::ENETDOWN:
case errno::ENETUNREACH:
case errno::ENOSPC:
case errno::EIO: return IoError.FILE_INCOMPLETE_WRITE!;
default: return IoError.UNKNOWN_ERROR!;
}
}

View File

@@ -27,142 +27,7 @@ struct LongDivResult
long rem;
}
enum Errno : ErrnoType
{
EPERM = 1, /* Operation not permitted */
ENOENT = 2, /* No such file or directory */
ESRCH = 3, /* No such process */
EINTR = 4, /* Interrupted system call */
EIO = 5, /* I/O error */
ENXIO = 6, /* No such device or address */
E2BIG = 7, /* Argument list too long */
ENOEXEC = 8, /* Exec format error */
EBADF = 9, /* Bad file number */
ECHILD = 10, /* No child processes */
EAGAIN = 11, /* Try again */
ENOMEM = 12, /* Out of memory */
EACCES = 13, /* Permission denied */
EFAULT = 14, /* Bad address */
ENOTBLK = 15, /* Block device required */
EBUSY = 16, /* Device or resource busy */
EEXIST = 17, /* File exists */
EXDEV = 18, /* Cross-device link */
ENODEV = 19, /* No such device */
ENOTDIR = 20, /* Not a directory */
EISDIR = 21, /* Is a directory */
EINVAL = 22, /* Invalid argument */
ENFILE = 23, /* File table overflow */
EMFILE = 24, /* Too many open files */
ENOTTY = 25, /* Not a typewriter */
ETXTBSY = 26, /* Text file busy */
EFBIG = 27, /* File too large */
ENOSPC = 28, /* No space left on device */
ESPIPE = 29, /* Illegal seek */
EROFS = 30, /* Read-only file system */
EMLINK = 31, /* Too many links */
EPIPE = 32, /* Broken pipe */
EDOM = 33, /* Math argument out of domain of func */
ERANGE = 34, /* Math result not representable */
EDEADLK = 35, /* Resource deadlock would occur */
ENAMETOOLONG = 36, /* File name too long */
ENOLCK = 37, /* No record locks available */
ENOSYS = 38, /* Function not implemented */
ENOTEMPTY = 39, /* Directory not empty */
ELOOP = 40, /* Too many symbolic links encountered */
ENOMSG = 42, /* No message of desired type */
EIDRM = 43, /* Identifier removed */
ECHRNG = 44, /* Channel number out of range */
EL2NSYNC = 45, /* Level 2 not synchronized */
EL3HLT = 46, /* Level 3 halted */
EL3RST = 47, /* Level 3 reset */
ELNRNG = 48, /* Link number out of range */
EUNATCH = 49, /* Protocol driver not attached */
ENOCSI = 50, /* No CSI structure available */
EL2HLT = 51, /* Level 2 halted */
EBADE = 52, /* Invalid exchange */
EBADR = 53, /* Invalid request descriptor */
EXFULL = 54, /* Exchange full */
ENOANO = 55, /* No anode */
EBADRQC = 56, /* Invalid request code */
EBADSLT = 57, /* Invalid slot */
EBFONT = 59, /* Bad font file format */
ENOSTR = 60, /* Device not a stream */
ENODATA = 61, /* No data available */
ETIME = 62, /* Timer expired */
ENOSR = 63, /* Out of streams resources */
ENONET = 64, /* Machine is not on the network */
ENOPKG = 65, /* Package not installed */
EREMOTE = 66, /* Object is remote */
ENOLINK = 67, /* Link has been severed */
EADV = 68, /* Advertise error */
ESRMNT = 69, /* Srmount error */
ECOMM = 70, /* Communication error on send */
EPROTO = 71, /* Protocol error */
EMULTIHOP = 72, /* Multihop attempted */
EDOTDOT = 73, /* RFS specific error */
EBADMSG = 74, /* Not a data message */
EOVERFLOW = 75, /* Value too large for defined data type */
ENOTUNIQ = 76, /* Name not unique on network */
EBADFD = 77, /* File descriptor in bad state */
EREMCHG = 78, /* Remote address changed */
ELIBACC = 79, /* Can not access a needed shared library */
ELIBBAD = 80, /* Accessing a corrupted shared library */
ELIBSCN = 81, /* .lib section in a.out corrupted */
ELIBMAX = 82, /* Attempting to link in too many shared libraries */
ELIBEXEC = 83, /* Cannot exec a shared library directly */
EILSEQ = 84, /* Illegal byte sequence */
ERESTART = 85, /* Interrupted system call should be restarted */
ESTRPIPE = 86, /* Streams pipe error */
EUSERS = 87, /* Too many users */
ENOTSOCK = 88, /* Socket operation on non-socket */
EDESTADDRREQ = 89, /* Destination address required */
EMSGSIZE = 90, /* Message too long */
EPROTOTYPE = 91, /* Protocol wrong type for socket */
ENOPROTOOPT = 92, /* Protocol not available */
EPROTONOSUPPORT = 93, /* Protocol not supported */
ESOCKTNOSUPPORT = 94, /* Socket type not supported */
EOPNOTSUPP = 95, /* Operation not supported on transport endpoint */
EPFNOSUPPORT = 96, /* Protocol family not supported */
EAFNOSUPPORT = 97, /* Address family not supported by protocol */
EADDRINUSE = 98, /* Address already in use */
EADDRNOTAVAIL = 99, /* Cannot assign requested address */
ENETDOWN = 100, /* Network is down */
ENETUNREACH = 101, /* Network is unreachable */
ENETRESET = 102, /* Network dropped connection because of reset */
ECONNABORTED = 103, /* Software caused connection abort */
ECONNRESET = 104, /* Connection reset by peer */
ENOBUFS = 105, /* No buffer space available */
EISCONN = 106, /* Transport endpoint is already connected */
ENOTCONN = 107, /* Transport endpoint is not connected */
ESHUTDOWN = 108, /* Cannot send after transport endpoint shutdown */
ETOOMANYREFS = 109, /* Too many references: cannot splice */
ETIMEDOUT = 110, /* Connection timed out */
ECONNREFUSED = 111, /* Connection refused */
EHOSTDOWN = 112, /* Host is down */
EHOSTUNREACH = 113, /* No route to host */
EALREADY = 114, /* Operation already in progress */
EINPROGRESS = 115, /* Operation now in progress */
ESTALE = 116, /* Stale NFS file handle */
EUCLEAN = 117, /* Structure needs cleaning */
ENOTNAM = 118, /* Not a XENIX named type file */
ENAVAIL = 119, /* No XENIX semaphores available */
EISNAM = 120, /* Is a named type file */
EREMOTEIO = 121, /* Remote I/O error */
EDQUOT = 122, /* Quota exceeded */
ENOMEDIUM = 123, /* No medium found */
EMEDIUMTYPE = 124, /* Wrong medium type */
ECANCELED = 125, /* Operation Canceled */
ENOKEY = 126, /* Required key not available */
EKEYEXPIRED = 127, /* Key has expired */
EKEYREVOKED = 128, /* Key has been revoked */
EKEYREJECTED = 129, /* Key was rejected by service */
EOWNERDEAD = 130, /* Owner died */
ENOTRECOVERABLE = 131, /* State not recoverable */
}
fn Errno errno()
{
@@ -173,7 +38,7 @@ fn Errno errno()
$elif (env::OS_TYPE == OsType.LINUX):
return (Errno)linux::errno();
$else:
return Errno.ENOTRECOVERABLE;
return errno::ENOTRECOVERABLE;
$endif;
}
@@ -271,7 +136,7 @@ const int EOF = -1;
const int FOPEN_MAX = 20;
const int FILENAME_MAX = 1024;
define ErrnoType = CInt;
define Errno = distinct CInt;
define SeekIndex = CLong;
extern fn int fclose(CFile stream);
@@ -352,4 +217,140 @@ extern fn Time time(Time *timer);
// signal
define SignalFunction = fn void(int);
extern fn SignalFunction signal(int sig, SignalFunction function);
// Incomplete
// Incomplete
module libc::errno;
const Errno EPERM = 1; /* Operation not permitted */
const Errno ENOENT = 2; /* No such file or directory */
const Errno ESRCH = 3; /* No such process */
const Errno EINTR = 4; /* Interrupted system call */
const Errno EIO = 5; /* I/O error */
const Errno ENXIO = 6; /* No such device or address */
const Errno E2BIG = 7; /* Argument list too long */
const Errno ENOEXEC = 8; /* Exec format error */
const Errno EBADF = 9; /* Bad file number */
const Errno ECHILD = 10; /* No child processes */
const Errno EAGAIN = 11; /* Try again */
const Errno ENOMEM = 12; /* Out of memory */
const Errno EACCES = 13; /* Permission denied */
const Errno EFAULT = 14; /* Bad address */
const Errno ENOTBLK = 15; /* Block device required */
const Errno EBUSY = 16; /* Device or resource busy */
const Errno EEXIST = 17; /* File exists */
const Errno EXDEV = 18; /* Cross-device link */
const Errno ENODEV = 19; /* No such device */
const Errno ENOTDIR = 20; /* Not a directory */
const Errno EISDIR = 21; /* Is a directory */
const Errno EINVAL = 22; /* Invalid argument */
const Errno ENFILE = 23; /* File table overflow */
const Errno EMFILE = 24; /* Too many open files */
const Errno ENOTTY = 25; /* Not a typewriter */
const Errno ETXTBSY = 26; /* Text file busy */
const Errno EFBIG = 27; /* File too large */
const Errno ENOSPC = 28; /* No space left on device */
const Errno ESPIPE = 29; /* Illegal seek */
const Errno EROFS = 30; /* Read-only file system */
const Errno EMLINK = 31; /* Too many links */
const Errno EPIPE = 32; /* Broken pipe */
const Errno EDOM = 33; /* Math argument out of domain of func */
const Errno ERANGE = 34; /* Math result not representable */
const Errno EDEADLK = 35; /* Resource deadlock would occur */
const Errno ENAMETOOLONG = 36; /* File name too long */
const Errno ENOLCK = 37; /* No record locks available */
const Errno ENOSYS = 38; /* Function not implemented */
const Errno ENOTEMPTY = 39; /* Directory not empty */
const Errno ELOOP = 40; /* Too many symbolic links encountered */
const Errno ENOMSG = 42; /* No message of desired type */
const Errno EIDRM = 43; /* Identifier removed */
const Errno ECHRNG = 44; /* Channel number out of range */
const Errno EL2NSYNC = 45; /* Level 2 not synchronized */
const Errno EL3HLT = 46; /* Level 3 halted */
const Errno EL3RST = 47; /* Level 3 reset */
const Errno ELNRNG = 48; /* Link number out of range */
const Errno EUNATCH = 49; /* Protocol driver not attached */
const Errno ENOCSI = 50; /* No CSI structure available */
const Errno EL2HLT = 51; /* Level 2 halted */
const Errno EBADE = 52; /* Invalid exchange */
const Errno EBADR = 53; /* Invalid request descriptor */
const Errno EXFULL = 54; /* Exchange full */
const Errno ENOANO = 55; /* No anode */
const Errno EBADRQC = 56; /* Invalid request code */
const Errno EBADSLT = 57; /* Invalid slot */
const Errno EBFONT = 59; /* Bad font file format */
const Errno ENOSTR = 60; /* Device not a stream */
const Errno ENODATA = 61; /* No data available */
const Errno ETIME = 62; /* Timer expired */
const Errno ENOSR = 63; /* Out of streams resources */
const Errno ENONET = 64; /* Machine is not on the network */
const Errno ENOPKG = 65; /* Package not installed */
const Errno EREMOTE = 66; /* Object is remote */
const Errno ENOLINK = 67; /* Link has been severed */
const Errno EADV = 68; /* Advertise error */
const Errno ESRMNT = 69; /* Srmount error */
const Errno ECOMM = 70; /* Communication error on send */
const Errno EPROTO = 71; /* Protocol error */
const Errno EMULTIHOP = 72; /* Multihop attempted */
const Errno EDOTDOT = 73; /* RFS specific error */
const Errno EBADMSG = 74; /* Not a data message */
const Errno EOVERFLOW = 75; /* Value too large for defined data type */
const Errno ENOTUNIQ = 76; /* Name not unique on network */
const Errno EBADFD = 77; /* File descriptor in bad state */
const Errno EREMCHG = 78; /* Remote address changed */
const Errno ELIBACC = 79; /* Can not access a needed shared library */
const Errno ELIBBAD = 80; /* Accessing a corrupted shared library */
const Errno ELIBSCN = 81; /* .lib section in a.out corrupted */
const Errno ELIBMAX = 82; /* Attempting to link in too many shared libraries */
const Errno ELIBEXEC = 83; /* Cannot exec a shared library directly */
const Errno EILSEQ = 84; /* Illegal byte sequence */
const Errno ERESTART = 85; /* Interrupted system call should be restarted */
const Errno ESTRPIPE = 86; /* Streams pipe error */
const Errno EUSERS = 87; /* Too many users */
const Errno ENOTSOCK = 88; /* Socket operation on non-socket */
const Errno EDESTADDRREQ = 89; /* Destination address required */
const Errno EMSGSIZE = 90; /* Message too long */
const Errno EPROTOTYPE = 91; /* Protocol wrong type for socket */
const Errno ENOPROTOOPT = 92; /* Protocol not available */
const Errno EPROTONOSUPPORT = 93; /* Protocol not supported */
const Errno ESOCKTNOSUPPORT = 94; /* Socket type not supported */
const Errno EOPNOTSUPP = 95; /* Operation not supported on transport endpoint */
const Errno EPFNOSUPPORT = 96; /* Protocol family not supported */
const Errno EAFNOSUPPORT = 97; /* Address family not supported by protocol */
const Errno EADDRINUSE = 98; /* Address already in use */
const Errno EADDRNOTAVAIL = 99; /* Cannot assign requested address */
const Errno ENETDOWN = 100; /* Network is down */
const Errno ENETUNREACH = 101; /* Network is unreachable */
const Errno ENETRESET = 102; /* Network dropped connection because of reset */
const Errno ECONNABORTED = 103; /* Software caused connection abort */
const Errno ECONNRESET = 104; /* Connection reset by peer */
const Errno ENOBUFS = 105; /* No buffer space available */
const Errno EISCONN = 106; /* Transport endpoint is already connected */
const Errno ENOTCONN = 107; /* Transport endpoint is not connected */
const Errno ESHUTDOWN = 108; /* Cannot send after transport endpoint shutdown */
const Errno ETOOMANYREFS = 109; /* Too many references: cannot splice */
const Errno ETIMEDOUT = 110; /* Connection timed out */
const Errno ECONNREFUSED = 111; /* Connection refused */
const Errno EHOSTDOWN = 112; /* Host is down */
const Errno EHOSTUNREACH = 113; /* No route to host */
const Errno EALREADY = 114; /* Operation already in progress */
const Errno EINPROGRESS = 115; /* Operation now in progress */
const Errno ESTALE = 116; /* Stale NFS file handle */
const Errno EUCLEAN = 117; /* Structure needs cleaning */
const Errno ENOTNAM = 118; /* Not a XENIX named type file */
const Errno ENAVAIL = 119; /* No XENIX semaphores available */
const Errno EISNAM = 120; /* Is a named type file */
const Errno EREMOTEIO = 121; /* Remote I/O error */
const Errno EDQUOT = 122; /* Quota exceeded */
const Errno ENOMEDIUM = 123; /* No medium found */
const Errno EMEDIUMTYPE = 124; /* Wrong medium type */
const Errno ECANCELED = 125; /* Operation Canceled */
const Errno ENOKEY = 126; /* Required key not available */
const Errno EKEYEXPIRED = 127; /* Key has expired */
const Errno EKEYREVOKED = 128; /* Key has been revoked */
const Errno EKEYREJECTED = 129; /* Key was rejected by service */
const Errno EOWNERDEAD = 130; /* Owner died */
const Errno ENOTRECOVERABLE = 131; /* State not recoverable */

View File

@@ -417,9 +417,8 @@ typedef struct
typedef struct
{
Expr *expr;
Expr **args;
uint64_t ordinal;
uint32_t ordinal;
DeclId parent;
} EnumConstantDecl;

View File

@@ -628,12 +628,9 @@ Decl *copy_decl(CopyStruct *c, Decl *decl)
// Note that the ast id should be patched by the parent.
return copy;
case DECL_ENUM_CONSTANT:
MACRO_COPY_EXPR(copy->enum_constant.expr);
MACRO_COPY_EXPR_LIST(copy->enum_constant.args);
break;
case DECL_FAULTVALUE:
MACRO_COPY_EXPR(copy->enum_constant.expr);
MACRO_COPY_EXPR_LIST(copy->enum_constant.args);
break;
case DECL_TYPEDEF:
if (copy->typedef_decl.is_func)

View File

@@ -309,11 +309,11 @@ static LLVMMetadataRef llvm_debug_enum_type(GenContext *c, Type *type, LLVMMetad
VECEACH(enums, i)
{
Decl *enum_constant = enums[i];
uint64_t val = int_to_u64(enum_constant->enum_constant.expr->const_expr.ixx);
int64_t val = enum_constant->enum_constant.ordinal;
LLVMMetadataRef debug_info = LLVMDIBuilderCreateEnumerator(
c->debug.builder,
enum_constant->name, strlen(enum_constant->name),
(int64_t)val,
val,
is_unsigned);
vec_add(elements, debug_info);
}

View File

@@ -4004,10 +4004,8 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
return;
}
case CONST_ENUM:
{
llvm_emit_const_expr(c, be_value, expr->const_expr.enum_val->enum_constant.expr);
llvm_value_set(be_value, llvm_const_int(c, type, expr->const_expr.enum_val->enum_constant.ordinal), type);
return;
}
default:
UNREACHABLE
}

View File

@@ -82,10 +82,7 @@ bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp
case CONST_BOOL:
return compare_bool(left->b, right->b, op);
case CONST_INTEGER:
if (right->const_kind == CONST_ENUM)
{
return int_comp(left->ixx, right->enum_val->enum_constant.expr->const_expr.ixx, op);
}
assert(right->const_kind != CONST_ENUM);
return int_comp(left->ixx, right->ixx, op);
case CONST_FLOAT:
return compare_fps(left->fxx.f, right->fxx.f, op);
@@ -107,15 +104,15 @@ bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp
case CONST_TYPEID:
return left->typeid == right->typeid;
case CONST_ERR:
case CONST_ENUM:
{
Decl *left_decl = left->err_val;
// The error case
uint64_t right_ordinal;
assert(right->const_kind == CONST_ERR);
assert(right->const_kind == left->const_kind);
Decl *right_decl = right->err_val;
// Non matching cannot be compared.
if (right_decl->type != left_decl->type) return false;
right_ordinal = right->err_val->enum_constant.ordinal;
int64_t right_ordinal = right->err_val->enum_constant.ordinal;
switch (op)
{
case BINARYOP_GT:
@@ -134,20 +131,6 @@ bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp
UNREACHABLE
}
}
case CONST_ENUM:
{
Decl *left_decl = left->enum_val;
// The enum case
Expr *left_const = left_decl->enum_constant.expr;
assert(left_const->expr_kind == EXPR_CONST);
const ExprConst *right_const = right;
if (right->const_kind == CONST_ENUM)
{
assert(right->enum_val->enum_constant.expr->expr_kind == EXPR_CONST);
right_const = &right->enum_val->enum_constant.expr->const_expr;
}
return expr_const_compare(&left_const->const_expr, right_const, op);
}
case CONST_BYTES:
if (left->bytes.len != right->bytes.len)
{

View File

@@ -1881,9 +1881,7 @@ static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl***
*
* enum_def
* : CAPS_IDENT
* | CAPS_IDENT '=' const_expr
* | CAPS_IDENT '(' expr_list ')'
* | CAPS_IDENT '(' expr_list ')' '=' const_expr
* ;
*
*/
@@ -1930,10 +1928,6 @@ static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibilit
enum_const->enum_constant.args = result;
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_decl);
}
if (try_consume(c, TOKEN_EQ))
{
ASSIGN_EXPR_OR_RET(enum_const->enum_constant.expr, parse_expr(c), poisoned_decl);
}
vec_add(decl->enums.values, enum_const);
// Allow trailing ','
if (!try_consume(c, TOKEN_COMMA))

View File

@@ -232,8 +232,26 @@ static bool int_literal_to_int(Expr *expr, Type *canonical, Type *type)
bool lit_integer_to_enum(Expr *expr, Type *canonical, Type *type)
{
assert(canonical->type_kind == TYPE_ENUM);
canonical = type_flatten(canonical->decl->enums.type_info->type);
return int_literal_to_int(expr, canonical, type);
unsigned max_enums = vec_size(canonical->decl->enums.values);
Int to_convert = expr->const_expr.ixx;
if (int_is_neg(to_convert))
{
SEMA_ERROR(expr, "A negative number cannot be converted to an enum.");
return false;
}
Int max = { .i.low = max_enums, .type = TYPE_I32 };
if (int_comp(to_convert, max, BINARYOP_GE))
{
SEMA_ERROR(expr, "This value exceeds the number of enums in %s.", canonical->decl->name);
return false;
}
Decl *decl = canonical->decl->enums.values[to_convert.i.low];
expr->const_expr = (ExprConst) {
.enum_val = decl,
.const_kind = CONST_ENUM
};
expr->type = type;
return true;
}
@@ -315,40 +333,41 @@ static bool int_to_int(Expr *left, Type *from_canonical, Type *canonical, Type *
}
}
static Type *enum_lowering(Expr* expr, Type *from)
static Type *enum_to_int_cast(Expr* expr, Type *from)
{
assert(from->type_kind == TYPE_ENUM);
Type *original = from->decl->enums.type_info->type;
expr->type = original;
if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_ENUM)
{
expr_replace(expr, expr->const_expr.enum_val->enum_constant.expr);
assert(!IS_FAILABLE(expr));
return expr->type;
expr_const_set_int(&expr->const_expr, expr->const_expr.enum_val->enum_constant.ordinal, type_flatten(original)->type_kind);
return original;
}
Type *result = from->decl->enums.type_info->type;
insert_cast(expr, CAST_ENUMLOW, type_get_opt_fail(result, IS_FAILABLE(expr)));
return result;
insert_cast(expr, CAST_ENUMLOW, type_get_opt_fail(original, IS_FAILABLE(expr)));
return original;
}
static bool enum_to_integer(Expr* expr, Type *from, Type *canonical, Type *type)
{
Type *result = enum_lowering(expr, from);
Type *result = enum_to_int_cast(expr, from);
return int_to_int(expr, result->canonical, canonical, type);
}
static bool enum_to_float(Expr* expr, Type *from, Type *canonical, Type *type)
{
Type *result = enum_lowering(expr, from);
Type *result = enum_to_int_cast(expr, from);
return int_to_float(expr, type_is_unsigned(result->canonical) ? CAST_UIFP : CAST_SIFP, canonical, type);
}
bool enum_to_bool(Expr* expr, Type *from, Type *type)
{
enum_lowering(expr, from);
enum_to_int_cast(expr, from);
return integer_to_bool(expr, type);
}
bool enum_to_pointer(Expr* expr, Type *from, Type *type)
{
enum_lowering(expr, from);
enum_to_int_cast(expr, from);
return int_to_pointer(expr, type);
}
@@ -462,12 +481,12 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
case ALL_UNSIGNED_INTS:
// We don't have to match pointer size if it's a constant.
if (to_kind == TYPE_POINTER && is_const) return true;
if (to_kind == TYPE_POINTER && type_is_pointer_sized(from_type)) return true;
if (to_kind == TYPE_ENUM) return true;
FALLTHROUGH;
case TYPE_ENUM:
// Allow conversion int/enum -> float/bool/enum int/enum -> pointer is only allowed if the int/enum is pointer sized.
if (type_is_integer(to_type) || type_is_float(to_type) || to_type == type_bool || to_kind == TYPE_ENUM) return true;
// TODO think about this, maybe we should require a bitcast?
if (to_kind == TYPE_POINTER && type_is_pointer_sized(from_type)) return true;
// Allow conversion int/enum -> float/bool/int
if (type_is_integer(to_type) || type_is_float(to_type) || to_type == type_bool) return true;
return false;
case ALL_FLOATS:
// Allow conversion float -> float/int/bool/enum
@@ -1312,7 +1331,7 @@ bool cast(Expr *expr, Type *to_type)
assert(!type_is_failable(to_type));
Type *from_type = expr->type;
bool from_is_failable = false;
Type *to = type_flatten(to_type);
Type *to = type_flatten_distinct(to_type);
// Special case *! => error
if (to == type_anyerr || to->type_kind == TYPE_FAULTTYPE)
@@ -1347,8 +1366,8 @@ bool cast(Expr *expr, Type *to_type)
}
return true;
}
bool result = cast_inner(expr, from_type, to, to_type);
assert(result == true);
if (!cast_inner(expr, from_type, to, to_type)) return false;
Type *result_type = expr->type;
if (from_is_failable && !type_is_failable(result_type))

View File

@@ -795,56 +795,22 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl)
// Start evaluating the constant
enum_value->resolve_status = RESOLVE_RUNNING;
Expr *expr = enum_value->enum_constant.expr;
// Create a "fake" expression.
// This will be evaluated later to catch the case
if (!expr)
Int val = (Int){ value, canonical->type_kind };
if (!int_fits(val, canonical->type_kind))
{
expr = expr_new(EXPR_CONST, enum_value->span);
expr->type = type;
expr->resolve_status = RESOLVE_NOT_DONE;
expr->const_expr.ixx = (Int) { value, canonical->type_kind };
if (expr_const_will_overflow(&expr->const_expr, canonical->type_kind))
{
SEMA_ERROR(enum_value,
"The enum value would implicitly be %s which does not fit in %s.",
i128_to_string(value, 10, type_is_signed(canonical)),
type_quoted_error_string(type));
return false;
}
expr->const_expr.const_kind = CONST_INTEGER;
expr->const_expr.narrowable = true;
expr->type = canonical;
enum_value->enum_constant.expr = expr;
}
// We try to convert to the desired type.
if (!sema_analyse_expr_rhs(context, type, expr, false))
{
success = false;
enum_value->resolve_status = RESOLVE_DONE;
decl_poison(enum_value);
// Reset!
value = (Int128) { 0, 0 };
continue;
}
assert(type_is_integer(expr->type->canonical));
// Here we might have a non-constant value,
if (expr->expr_kind != EXPR_CONST)
{
SEMA_ERROR(expr, "Expected a constant expression for enum.");
decl_poison(enum_value);
success = false;
// Skip one value.
continue;
SEMA_ERROR(enum_value,
"The enum value would implicitly be %s which does not fit in %s.",
i128_to_string(value, 10, type_is_signed(canonical)),
type_quoted_error_string(type));
return false;
}
enum_value->enum_constant.ordinal = value.low;
// Update the value
value = i128_add64(expr->const_expr.ixx.i, 1);
DEBUG_LOG("* Value: %s", expr_const_to_error_string(&expr->const_expr));
value.low++;
enum_value->resolve_status = RESOLVE_DONE;
}
return success;

View File

@@ -622,7 +622,8 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
SEMA_ERROR(expr, "Did you forget a '!' after '%s'?", decl->name);
return expr_poison(expr);
case DECL_ENUM_CONSTANT:
expr_replace(expr, decl->enum_constant.expr);
TODO
//expr_replace(expr, decl->enum_constant.expr);
return true;
case DECL_VAR:
break;
@@ -2946,28 +2947,6 @@ static void add_members_to_context(SemaContext *context, Decl *decl)
}
}
static Expr *enum_minmax_value(Decl *decl, BinaryOp comparison)
{
assert(decl->decl_kind == DECL_ENUM);
bool is_signed = type_is_signed(decl->enums.type_info->type->canonical);
Expr *expr = NULL;
VECEACH(decl->enums.values, i)
{
Decl *enum_constant = decl->enums.values[i];
Expr *candidate = enum_constant->enum_constant.expr;
assert(candidate->expr_kind == EXPR_CONST);
if (!expr)
{
expr = candidate;
continue;
}
if (expr_const_compare(&candidate->const_expr, &expr->const_expr, comparison))
{
expr = candidate;
}
}
return expr;
}
/**
* 1. .A -> It is an enum constant.
@@ -3127,34 +3106,12 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
expr_rewrite_to_int_const(expr, type_isize, vec_size(decl->enums.values), true);
return true;
}
if (name == kw_max)
{
Expr *max = enum_minmax_value(decl, BINARYOP_GT);
if (!max)
{
expr_rewrite_to_int_const(expr, decl->enums.type_info->type->canonical, 0, false);
return true;
}
expr_replace(expr, max);
return true;
}
if (name == kw_values)
{
expr_replace_with_enum_array(expr, decl);
return sema_analyse_expr(context, expr);
return true;
}
if (name == kw_min)
{
Expr *min = enum_minmax_value(decl, BINARYOP_LT);
if (!min)
{
expr_rewrite_to_int_const(expr, decl->enums.type_info->type->canonical, 0, false);
return true;
}
expr_replace(expr, min);
return true;
}
break;
case DECL_FAULT:
unit_register_external_symbol(context->compilation_unit, decl);
@@ -3173,28 +3130,6 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
expr_rewrite_to_int_const(expr, type_isize, vec_size(decl->enums.values), true);
return true;
}
if (name == kw_max)
{
Expr *max = enum_minmax_value(decl, BINARYOP_GT);
if (!max)
{
expr_rewrite_to_int_const(expr, decl->enums.type_info->type->canonical, 0, false);
return true;
}
expr_replace(expr, max);
return true;
}
if (name == kw_min)
{
Expr *min = enum_minmax_value(decl, BINARYOP_LT);
if (!min)
{
expr_rewrite_to_int_const(expr, decl->enums.type_info->type->canonical, 0, false);
return true;
}
expr_replace(expr, min);
return true;
}
break;
case DECL_UNION:
case DECL_STRUCT:
@@ -3377,6 +3312,16 @@ CHECK_DEEPER:
}
}
if (!is_macro && kw == kw_ordinal)
{
if (type->type_kind == TYPE_ENUM)
{
if (!cast(parent, type->decl->enums.type_info->type)) return false;
expr_replace(expr, parent);
return true;
}
}
// 9. At this point we may only have distinct, struct, union, error, enum
if (!type_may_have_sub_elements(type))
{
@@ -4353,7 +4298,10 @@ static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr)
{
return sema_failed_cast(expr, type_no_fail(inner->type), target_type);
}
cast(inner, target_type);
if (!cast(inner, target_type))
{
return expr_poison(expr);
}
expr_replace(expr, inner);
return true;
}

View File

@@ -1683,12 +1683,15 @@ static inline ExprConst *flatten_enum_const(Expr *expr)
if (const_expr->const_kind == CONST_ENUM)
{
const_expr->const_kind = CONST_INTEGER;
Decl *enum_val = const_expr->enum_val;
Expr *enum_expr = enum_val->enum_constant.expr;
TODO
/*
Expr *enum_expr = exprptr(enum_val->enum_constant.ordinal2);
assert(enum_expr->expr_kind == EXPR_CONST);
ExprConst *enum_const = &enum_expr->const_expr;
assert(enum_const->const_kind == CONST_INTEGER);
*const_expr = *enum_const;
*const_expr = *enum_const;*/
}
return const_expr;
}
@@ -1707,25 +1710,39 @@ static inline bool sema_check_value_case(SemaContext *context, Type *switch_type
*if_chained = true;
return true;
}
ExprConst *const_expr = flatten_enum_const(expr);
ExprConst *to_const_expr = to_expr ? flatten_enum_const(to_expr) : const_expr;
ExprConst *const_expr = &expr->const_expr;
ExprConst *to_const_expr = to_expr ? &to_expr->const_expr : const_expr;
if (!*max_ranged && type_is_integer(expr->type) && to_const_expr != const_expr)
if (!*max_ranged && to_const_expr != const_expr)
{
if (int_comp(const_expr->ixx, to_const_expr->ixx, BINARYOP_GT))
if (const_expr->const_kind == CONST_ENUM)
{
sema_error_at(extend_span_with_token(expr->span, to_expr->span),
"The range is not valid because the first value (%s) is greater than the second (%s). "
"It would work if you swapped their order.",
int_to_str(const_expr->ixx, 10),
int_to_str(to_const_expr->ixx, 10));
return false;
assert(to_const_expr->const_kind == CONST_ENUM);
if (to_const_expr->enum_val->enum_constant.ordinal < const_expr->enum_val->enum_constant.ordinal)
{
sema_error_at(extend_span_with_token(expr->span, to_expr->span),
"A enum range must be have the enum with a lower ordinal followed by the one with a higher ordinal. "
"It would work if you swapped their order.");
return false;
}
}
Int128 range = int_sub(to_const_expr->ixx, const_expr->ixx).i;
Int128 max_range = { .low = active_target.switchrange_max_size };
if (i128_comp(range, max_range, type_i128) == CMP_GT)
else if (type_is_integer(expr->type))
{
*max_ranged = true;
if (int_comp(const_expr->ixx, to_const_expr->ixx, BINARYOP_GT))
{
sema_error_at(extend_span_with_token(expr->span, to_expr->span),
"The range is not valid because the first value (%s) is greater than the second (%s). "
"It would work if you swapped their order.",
int_to_str(const_expr->ixx, 10),
int_to_str(to_const_expr->ixx, 10));
return false;
}
Int128 range = int_sub(to_const_expr->ixx, const_expr->ixx).i;
Int128 max_range = { .low = active_target.switchrange_max_size };
if (i128_comp(range, max_range, type_i128) == CMP_GT)
{
*max_ranged = true;
}
}
}
for (unsigned i = 0; i < index; i++)
@@ -1765,6 +1782,7 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc
bool type_switch = switch_type == type_typeid;
for (unsigned i = 0; i < case_count; i++)
{
if (!success) break;
Ast *stmt = cases[i];
Ast *next = (i < case_count - 1) ? cases[i + 1] : NULL;
PUSH_NEXT(next, statement);

View File

@@ -1,20 +1,16 @@
enum MyEnum : short
{
HELO = 12,
WORLD = 14,
BYE = -5
HELO,
WORLD,
BYE
}
int myenum_max = MyEnum.max;
int myenum_min = MyEnum.min;
int myenum_elements = MyEnum.elements;
int myenum_alignof = $alignof(MyEnum);
int myenum_sizeof = MyEnum.sizeof;
// #expect: compile_time.ll
@compile_time.myenum_max = local_unnamed_addr global i32 14, align 4
@compile_time.myenum_min = local_unnamed_addr global i32 -5, align 4
@compile_time.myenum_elements = local_unnamed_addr global i32 3, align 4
@compile_time.myenum_alignof = local_unnamed_addr global i32 2, align 4
@compile_time.myenum_sizeof = local_unnamed_addr global i32 2, align 4

View File

@@ -3,9 +3,17 @@ module test;
enum MyEnum : char
{
FOO = 3,
BAR = 100
FOO,
BAR
}
fn void test2()
{
char ww = MyEnum.FOO.ordinal;
MyEnum x = MyEnum.BAR;
char zz = x.ordinal;
}
fn void test()
{
char b = MyEnum.FOO;
@@ -22,10 +30,23 @@ fn void test()
MyEnum! xf = MyEnum.BAR;
float! e = (float)(x);
e = (float)(xf);
}
/* #expect: test.ll
define void @test.test2() #0 {
entry:
%ww = alloca i8, align 1
%x = alloca i8, align 1
%zz = alloca i8, align 1
store i8 0, i8* %ww, align 1
store i8 1, i8* %x, align 1
%0 = load i8, i8* %x, align 1
store i8 %0, i8* %zz, align 1
ret void
}
define void @test.test() #0 {
entry:
%b = alloca i8, align 1
@@ -39,17 +60,17 @@ entry:
%xf.f = alloca i64, align 8
%e = alloca float, align 4
%e.f = alloca i64, align 8
store i8 3, i8* %b, align 1
store i32 100, i32* %z, align 4
store i8 100, i8* %x, align 1
store i8 0, i8* %b, align 1
store i32 1, i32* %z, align 4
store i8 1, i8* %x, align 1
%0 = load i8, i8* %x, align 1
store i8 %0, i8* %b2, align 1
%1 = load i8, i8* %x, align 1
%uisiext = zext i8 %1 to i32
store i32 %uisiext, i32* %z2, align 4
store float 3.000000e+00, float* %d, align 4
store i8 1, i8* %hello, align 1
store i8 100, i8* %xf, align 1
store float 0.000000e+00, float* %d, align 4
store i8 0, i8* %hello, align 1
store i8 1, i8* %xf, align 1
store i64 0, i64* %xf.f, align 8
%2 = load i8, i8* %x, align 1
%uifp = uitofp i8 %2 to float
@@ -75,4 +96,6 @@ after_assign: ; preds = %after_check, %error
voiderr: ; preds = %after_assign
ret void
}
}
attributes #0 = { nounwind }

View File

@@ -4,12 +4,10 @@ module test;
enum Foo
{
ABC = 3,
BCD = 123
ABC,
BCD
}
int z = Foo.min;
int w = Foo.max;
Foo zfok = Foo.values[0];
Foo[] zw = &&Foo.values;
@@ -22,10 +20,8 @@ fn void test(int x)
%"Foo[]" = type { i32*, i64 }
@test.z = local_unnamed_addr global i32 3, align 4
@test.w = local_unnamed_addr global i32 123, align 4
@test.zfok = local_unnamed_addr global i32 3, align 4
@.taddr = private global [2 x i32] [i32 3, i32 123], align 4
@test.zfok = local_unnamed_addr global i32 0, align 4
@.taddr = private global [2 x i32] [i32 0, i32 1], align 4
@test.zw = local_unnamed_addr global %"Foo[]" { i32* getelementptr inbounds ([2 x i32], [2 x i32]* @.taddr, i32 0, i32 0), i64 2 }, align 8
define void @test.test(i32 %0) #0 {
@@ -33,9 +29,9 @@ entry:
%zonk = alloca i32, align 4
%literal = alloca [2 x i32], align 4
%1 = getelementptr inbounds [2 x i32], [2 x i32]* %literal, i64 0, i64 0
store i32 3, i32* %1, align 4
store i32 0, i32* %1, align 4
%2 = getelementptr inbounds [2 x i32], [2 x i32]* %literal, i64 0, i64 1
store i32 123, i32* %2, align 4
store i32 1, i32* %2, align 4
%sisiext = sext i32 %0 to i64
%3 = getelementptr inbounds [2 x i32], [2 x i32]* %literal, i64 0, i64 %sisiext
%4 = load i32, i32* %3, align 4

View File

@@ -34,6 +34,6 @@ fn void test2(Enum e)
fn void test3(Enum e)
{
EnumB h = (EnumB)(e);
EnumB h = (EnumB)(e); // #error: 'Enum' to 'EnumB' is not allowed
Func i = (Func)(e); // #error: cast 'Enum' to 'Func'
}

View File

@@ -20,7 +20,7 @@ fn void example_for()
enum Height : uint
{
LOW = 0,
LOW,
MEDIUM,
HIGH,
}

View File

@@ -107,9 +107,9 @@ define IntList = LinkedList<int>;
enum MyEnum : int
{
HELO = 12,
WORLD = 14,
BYE = -5
HELO,
WORLD,
BYE
}
@@ -129,10 +129,8 @@ fn void main()
}
list.free();
printf("Min %d Max %d Elements: %d\n", MyEnum.min, MyEnum.max, (int)(MyEnum.elements));
printf("Elements: %d\n", (int)(MyEnum.elements));
int maxv = MyEnum.max;
int minv = MyEnum.min;
int elements = MyEnum.elements;
printf("Hello\n");
IntArray array;
@@ -211,8 +209,8 @@ fault MyErr
enum Hello : int
{
FOO = 3,
BAR = 4,
FOO,
BAR,
}
macro Hello wut()
@@ -431,8 +429,6 @@ define void @test.main() #0 {
entry:
%list = alloca %LinkedList, align 8
%i = alloca i32, align 4
%maxv = alloca i32, align 4
%minv = alloca i32, align 4
%elements = alloca i32, align 4
%array = alloca %List, align 8
%i1 = alloca i32, align 4
@@ -486,9 +482,7 @@ loop.body: ; preds = %loop.cond
loop.exit: ; preds = %loop.cond
call void @"std::array::linkedlist.int.LinkedList__free"(%LinkedList* %list)
%11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.3, i32 0, i32 0), i32 -5, i32 14, i32 3)
store i32 14, i32* %maxv, align 4
store i32 -5, i32* %minv, align 4
%11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.3, i32 0, i32 0), i32 3)
store i32 3, i32* %elements, align 4
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0))
%13 = bitcast %List* %array to i8*

View File

@@ -109,9 +109,9 @@ define IntList = LinkedList<int>;
enum MyEnum : int
{
HELO = 12,
WORLD = 14,
BYE = -5
HELO,
WORLD,
BYE
}
@@ -131,10 +131,8 @@ fn void main()
}
list.free();
printf("Min %d Max %d Elements: %d\n", MyEnum.min, MyEnum.max, (int)(MyEnum.elements));
printf("Elements: %d\n", (int)(MyEnum.elements));
int maxv = MyEnum.max;
int minv = MyEnum.min;
int elements = MyEnum.elements;
printf("Hello\n");
IntArray array;
@@ -213,8 +211,8 @@ fault MyErr
enum Hello : int
{
FOO = 3,
BAR = 4,
FOO,
BAR,
}
macro Hello wut()
@@ -268,7 +266,7 @@ $introspect.Foo = comdat any
@.str.1 = private unnamed_addr constant [16 x i8] c"Test static %d\0A\00", align 1
@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4
@.str.2 = private unnamed_addr constant [17 x i8] c"Element[%d]: %d\0A\00", align 1
@.str.3 = private unnamed_addr constant [28 x i8] c"Min %d Max %d Elements: %d\0A\00", align 1
@.str.3 = private unnamed_addr constant [14 x i8] c"Elements: %d\0A\00", align 1
@.str.4 = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
@.str.5 = private unnamed_addr constant [17 x i8] c"Element[%d]: %d\0A\00", align 1
@.__const.6 = private unnamed_addr constant %Blob.0 { i32 42 }, align 4
@@ -464,8 +462,6 @@ define void @test.main() #0 {
entry:
%list = alloca %LinkedList, align 8
%i = alloca i32, align 4
%maxv = alloca i32, align 4
%minv = alloca i32, align 4
%elements = alloca i32, align 4
%array = alloca %List, align 8
%i1 = alloca i32, align 4
@@ -525,9 +521,7 @@ loop.body: ; preds = %loop.cond
loop.exit: ; preds = %loop.cond
call void @"std::array::linkedlist.int.LinkedList__free"(%LinkedList* %list)
%11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.3, i32 0, i32 0), i32 -5, i32 14, i32 3)
store i32 14, i32* %maxv, align 4
store i32 -5, i32* %minv, align 4
%11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.3, i32 0, i32 0), i32 3)
store i32 3, i32* %elements, align 4
%12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0))
%13 = bitcast %List* %array to i8*

View File

@@ -18,7 +18,7 @@ fn void test_other_enum()
break;
case B:
break;
case Bar.B: // #error: 'Bar' to 'Foo'
case Bar.B: // #error: 'Bar' into 'Foo'
break;
}
}
@@ -28,7 +28,7 @@ fn void test_check_nums()
Foo f = A;
switch (f)
{
case (Foo)(2):
case (Foo)(1):
break;
case (Foo)(0):
break;
@@ -66,7 +66,7 @@ fn void test_duplicate_case2(Foo i)
{
case A:
break;
case (Foo)(2):
case (Foo)(1):
break;
case A: // #error: same case value appears
break;

View File

@@ -75,7 +75,7 @@ fn void test10()
enum Enum : int
{
A = 127,
A,
B,
}

View File

@@ -1,17 +0,0 @@
enum EnumTestErrorType3 : int
{
A = FOO // #error: 'FOO' could not be found, did you spell it
}
fn int foo()
{
return 10;
}
enum State
{
A = foo(), // #error: Expected a constant expression for enum
B = "hello", // #error: 'char[5]*' into 'int'
C = true, // #error: 'bool' to 'int'
}

View File

@@ -1,5 +1,136 @@
enum Foo : char
enum Foo : ichar
{
MY_VAL1 = 255,
MY_VAL2, // #error: The enum value would implicitly be 256 which does not fit in 'char'
MY_VAL0,
MY_VAL1,
MY_VAL2,
MY_VAL3,
MY_VAL4,
MY_VAL5,
MY_VAL6,
MY_VAL7,
MY_VAL8,
MY_VAL9,
MY_VAL10,
MY_VAL11,
MY_VAL12,
MY_VAL13,
MY_VAL14,
MY_VAL15,
MY_VAL16,
MY_VAL17,
MY_VAL18,
MY_VAL19,
MY_VAL20,
MY_VAL21,
MY_VAL22,
MY_VAL23,
MY_VAL24,
MY_VAL25,
MY_VAL26,
MY_VAL27,
MY_VAL28,
MY_VAL29,
MY_VAL30,
MY_VAL31,
MY_VAL32,
MY_VAL33,
MY_VAL34,
MY_VAL35,
MY_VAL36,
MY_VAL37,
MY_VAL38,
MY_VAL39,
MY_VAL40,
MY_VAL41,
MY_VAL42,
MY_VAL43,
MY_VAL44,
MY_VAL45,
MY_VAL46,
MY_VAL47,
MY_VAL48,
MY_VAL49,
MY_VAL50,
MY_VAL51,
MY_VAL52,
MY_VAL53,
MY_VAL54,
MY_VAL55,
MY_VAL56,
MY_VAL57,
MY_VAL58,
MY_VAL59,
MY_VAL60,
MY_VAL61,
MY_VAL62,
MY_VAL63,
MY_VAL64,
MY_VAL65,
MY_VAL66,
MY_VAL67,
MY_VAL68,
MY_VAL69,
MY_VAL70,
MY_VAL71,
MY_VAL72,
MY_VAL73,
MY_VAL74,
MY_VAL75,
MY_VAL76,
MY_VAL77,
MY_VAL78,
MY_VAL79,
MY_VAL80,
MY_VAL81,
MY_VAL82,
MY_VAL83,
MY_VAL84,
MY_VAL85,
MY_VAL86,
MY_VAL87,
MY_VAL88,
MY_VAL89,
MY_VAL90,
MY_VAL91,
MY_VAL92,
MY_VAL93,
MY_VAL94,
MY_VAL95,
MY_VAL96,
MY_VAL97,
MY_VAL98,
MY_VAL99,
MY_VAL100,
MY_VAL101,
MY_VAL102,
MY_VAL103,
MY_VAL104,
MY_VAL105,
MY_VAL106,
MY_VAL107,
MY_VAL108,
MY_VAL109,
MY_VAL110,
MY_VAL111,
MY_VAL112,
MY_VAL113,
MY_VAL114,
MY_VAL115,
MY_VAL116,
MY_VAL117,
MY_VAL118,
MY_VAL119,
MY_VAL120,
MY_VAL121,
MY_VAL122,
MY_VAL123,
MY_VAL124,
MY_VAL125,
MY_VAL126,
MY_VAL127,
MY_VAL128, // #error: The enum value would implicitly be 128 which does not fit in 'ichar'
MY_VAL129,
}

View File

@@ -3,14 +3,14 @@ enum Inf
{
A,
B,
C = 10000
C
}
enum Inf2 : char
{
A,
B,
C = 129,
C,
}
define BooInf = Inf;
@@ -34,7 +34,7 @@ fn void enumInferenceTest()
return;
case B:
return;
case (Inf2)(111):
case (Inf2)(2):
x1 += 1;
return;
default:

View File

@@ -1,6 +1,6 @@
enum EnumTest : long
{
VALUE1 = 4,
VALUE1,
VALUE2
}
@@ -8,7 +8,7 @@ define Frob = long;
enum EnumTestAlias : Frob
{
VALUE1 = 4,
VALUE1,
VALUE2
}
@@ -18,17 +18,6 @@ enum EnumTestDefault
VALUE2
}
enum EnumTestNoOverflowAfterLong : long
{
VALUE = 0x7FFF_FFFF_FFFF_FFFE,
VALUE_NO_EXCEED
}
enum EnumTestSmall : ushort
{
VALUE = 0xFF,
VALUE2 = 0xFFFF
}
enum EnumWithErrorData2 : int (int bar, )
{
@@ -41,6 +30,6 @@ enum EnumTestErrorType4
enum EnumTest5
{
B = 0,
B,
C,
}

View File

@@ -1,4 +0,0 @@
enum EnumTestOverflow
{
VALUE = 0x80000000i64, // #error: Cannot narrow 'long' to 'int'
}