mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Ordinal based enums.
This commit is contained in:
@@ -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!;
|
||||
}
|
||||
}
|
||||
|
||||
277
lib/std/libc.c3
277
lib/std/libc.c3
@@ -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 */
|
||||
|
||||
@@ -417,9 +417,8 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Expr *expr;
|
||||
Expr **args;
|
||||
uint64_t ordinal;
|
||||
uint32_t ordinal;
|
||||
DeclId parent;
|
||||
} EnumConstantDecl;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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 }
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ fn void example_for()
|
||||
|
||||
enum Height : uint
|
||||
{
|
||||
LOW = 0,
|
||||
LOW,
|
||||
MEDIUM,
|
||||
HIGH,
|
||||
}
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -75,7 +75,7 @@ fn void test10()
|
||||
|
||||
enum Enum : int
|
||||
{
|
||||
A = 127,
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
enum EnumTestOverflow
|
||||
{
|
||||
VALUE = 0x80000000i64, // #error: Cannot narrow 'long' to 'int'
|
||||
}
|
||||
Reference in New Issue
Block a user