'long' review

add some features for more complete 'long' support

tcc.h:
- use LONG_SIZE=4/8 instead of TCC_LONG_ARE_64_BIT
tccgen.c:
- add ptrdiff_type, update size_type
- support shift and ?: operations
- support long enum types
- display 'long' from type_to_str
- nwchar_t is unsigned short on windows
- unrelated: use memcpy in init_putv for long doubles to avoid
  random bytes in the image (if tcc was compiled by gcc) for
  diff purposes.
tccpp.c:
- make parse_number return correct types
- improve multi-character-constants 'XX' 'abcd'
Changelog:
- update
master
grischka 2017-09-24 18:57:48 +02:00
parent 870271ea07
commit 1443039416
6 changed files with 164 additions and 176 deletions

View File

@ -9,11 +9,10 @@ User interface:
- -mno-sse on x86-64 disables use of SSE instructions
- @listfile support (Vlad Vissoultchev)
- tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka)
- CPATH, C_INCLUDE_PATH and LD_LIBRARY_PATH environment variables support
- CPATH, C_INCLUDE_PATH and LIBRARY_PATH environment variables support
(Andrew Aladjev, Urs Janssen)
Platforms:
- Bootstrap native Windows 32/64 compiler using Cygwin+gcc (Christian Jullien)
- new AARCH64 (arm64) target (Edmund Grimley Evans)
- vastly improved support for ARM hard float calling convention
(Thomas Preud'homme, Daniel Glöckner)
@ -22,6 +21,7 @@ Platforms:
- ABI tests with native compiler using libtcc (James Lyon)
- UNICODE startup code supports wmain and wWinMain (YX Hao)
- shared libraries for x86_64 (Michael Matz)
- Bootstrap native Windows 32/64 compiler using Cygwin+gcc (Christian Jullien)
Features:
- VLA (variable length array) improved (James Lyon, Pip Cet)
@ -35,6 +35,8 @@ Features:
- standard conforming (and GCC compatible) struct initialization
(Michael Matz)
- bit-field layout made compatible with GCC (Michael Matz)
- UTF8 in string literals supported (Zdenek Pavlas)
_ _Generic(...) supported (Matthias Gatto)
Licensing:
- TinyCC partly relicensed to MIT license (See RELICENSING file).

View File

@ -836,21 +836,21 @@ LIBTCCAPI TCCState *tcc_new(void)
# endif
/* TinyCC & gcc defines */
#if defined(TCC_TARGET_PE) && PTR_SIZE == 8
#if PTR_SIZE == 4
/* 32bit systems. */
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
tcc_define_symbol(s, "__ILP32__", NULL);
#elif LONG_SIZE == 4
/* 64bit Windows. */
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long long");
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long long");
tcc_define_symbol(s, "__LLP64__", NULL);
#elif PTR_SIZE == 8
#else
/* Other 64bit systems. */
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned long");
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "long");
tcc_define_symbol(s, "__LP64__", NULL);
#else
/* Other 32bit systems. */
tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
tcc_define_symbol(s, "__ILP32__", NULL);
#endif
#if defined(TCC_MUSL)

23
tcc.h
View File

@ -361,6 +361,12 @@ extern long double strtold (const char *__nptr, char **__endptr);
/* target address type */
#define addr_t ElfW(Addr)
#if PTR_SIZE == 8 && !defined TCC_TARGET_PE
# define LONG_SIZE 8
#else
# define LONG_SIZE 4
#endif
/* -------------------------------------------- */
#define INCLUDE_STACK_SIZE 32
@ -880,14 +886,14 @@ struct filespec {
#define VT_CONSTANT 0x0100 /* const modifier */
#define VT_VOLATILE 0x0200 /* volatile modifier */
#define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
#define VT_LONG 0x0800
#define VT_LONG 0x0800 /* long type (also has VT_INT rsp. VT_LLONG) */
/* storage */
#define VT_EXTERN 0x00001000 /* extern definition */
#define VT_STATIC 0x00002000 /* static variable */
#define VT_TYPEDEF 0x00004000 /* typedef definition */
#define VT_INLINE 0x00008000 /* inline definition */
/* currently unused: 0x0800, 0x000[1248]0000 */
/* currently unused: 0x000[1248]0000 */
#define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */
#define VT_STRUCT_MASK (((1 << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD)
@ -906,7 +912,6 @@ struct filespec {
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
/* token values */
/* warning: the following compare tokens depend on i386 asm code */
@ -947,6 +952,7 @@ struct filespec {
#define TOK_PPNUM 0xbe /* preprocessor number */
#define TOK_PPSTR 0xbf /* preprocessor string */
#define TOK_LINENUM 0xc0 /* line number info */
#define TOK_TWODOTS 0xa8 /* C++ token ? */
/* <-- */
#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
@ -961,15 +967,8 @@ struct filespec {
#define TOK_PLCHLDR 0xcb /* placeholder token as defined in C99 */
#define TOK_NOSUBST 0xcc /* means following token has already been pp'd */
#define TOK_PPJOIN 0xcd /* A '##' in the right position to mean pasting */
#define TOK_CLONG 0xce /* long constant */
#define TOK_CULONG 0xcf /* unsigned long constant */
#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
#define TCC_LONG_ARE_64_BIT
#endif
#define TOK_CLONG 0xce /* long constant */
#define TOK_CULONG 0xcf /* unsigned long constant */
#define TOK_SHL 0x01 /* shift left */
#define TOK_SAR 0x02 /* signed shift right */

173
tccgen.c
View File

@ -61,7 +61,7 @@ ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc
ST_DATA const char *funcname;
ST_DATA int g_debug;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type, ptrdiff_type;
ST_DATA struct switch_t {
struct case_t {
@ -240,9 +240,14 @@ ST_FUNC int tccgen_compile(TCCState *s1)
char_pointer_type.t = VT_BYTE;
mk_pointer(&char_pointer_type);
#if PTR_SIZE == 4
size_type.t = VT_INT;
size_type.t = VT_INT | VT_UNSIGNED;
ptrdiff_type.t = VT_INT;
#elif LONG_SIZE == 4
size_type.t = VT_LLONG | VT_UNSIGNED;
ptrdiff_type.t = VT_LLONG;
#else
size_type.t = VT_LLONG;
size_type.t = VT_LONG | VT_LLONG | VT_UNSIGNED;
ptrdiff_type.t = VT_LONG | VT_LLONG;
#endif
func_old_type.t = VT_FUNC;
func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
@ -2127,12 +2132,7 @@ redo:
}
vrott(3);
gen_opic(op);
/* set to integer type */
#if PTR_SIZE == 8
vtop->type.t = VT_LLONG;
#else
vtop->type.t = VT_INT;
#endif
vtop->type.t = ptrdiff_type.t;
vswap();
gen_op(TOK_PDIV);
} else {
@ -2218,14 +2218,15 @@ redo:
t = bt1 == VT_LLONG ? VT_LLONG : VT_INT;
if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (t | VT_UNSIGNED))
t |= VT_UNSIGNED;
t |= (VT_LONG & t1);
goto std_op;
} else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
/* cast to biggest op */
t = VT_LLONG;
/* check if we need to keep type as long or as long long */
if ((t1 & VT_LONG && (t2 & (VT_BTYPE | VT_LONG)) != VT_LLONG) ||
(t2 & VT_LONG && (t1 & (VT_BTYPE | VT_LONG)) != VT_LLONG))
t |= VT_LONG;
t = VT_LLONG | VT_LONG;
if (bt1 == VT_LLONG)
t &= t1;
if (bt2 == VT_LLONG)
t &= t2;
/* convert to unsigned if it does not fit in a long long */
if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) ||
(t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED))
@ -2233,12 +2234,8 @@ redo:
goto std_op;
} else {
/* integer operations */
t = VT_INT;
if ((t1 & VT_LONG) || (t2 & VT_LONG))
t |= VT_LONG;
/* convert to unsigned if it does not fit in an integer */
t = VT_INT | (VT_LONG & (t1 | t2));
/* convert to unsigned if it does not fit in an integer */
if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) ||
(t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED))
t |= VT_UNSIGNED;
@ -2741,7 +2738,6 @@ static int compare_types(CType *type1, CType *type2, int unqualified)
t1 &= ~VT_DEFSIGN;
t2 &= ~VT_DEFSIGN;
}
/* XXX: bitfields ? */
if (t1 != t2)
return 0;
@ -2790,14 +2786,7 @@ static void type_to_str(char *buf, int buf_size,
t = type->t;
bt = t & VT_BTYPE;
buf[0] = '\0';
if (t & VT_CONSTANT)
pstrcat(buf, buf_size, "const ");
if (t & VT_VOLATILE)
pstrcat(buf, buf_size, "volatile ");
if ((t & (VT_DEFSIGN | VT_UNSIGNED)) == (VT_DEFSIGN | VT_UNSIGNED))
pstrcat(buf, buf_size, "unsigned ");
else if (t & VT_DEFSIGN)
pstrcat(buf, buf_size, "signed ");
if (t & VT_EXTERN)
pstrcat(buf, buf_size, "extern ");
if (t & VT_STATIC)
@ -2806,17 +2795,20 @@ static void type_to_str(char *buf, int buf_size,
pstrcat(buf, buf_size, "typedef ");
if (t & VT_INLINE)
pstrcat(buf, buf_size, "inline ");
if (t & VT_VOLATILE)
pstrcat(buf, buf_size, "volatile ");
if (t & VT_CONSTANT)
pstrcat(buf, buf_size, "const ");
if (((t & VT_DEFSIGN) && bt == VT_BYTE)
|| ((t & VT_UNSIGNED)
&& (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG)
&& !IS_ENUM(t)
))
pstrcat(buf, buf_size, (t & VT_UNSIGNED) ? "unsigned " : "signed ");
buf_size -= strlen(buf);
buf += strlen(buf);
if (IS_ENUM(t)) {
tstr = "enum ";
goto tstruct;
}
if (!bt && VT_LONG & t) {
tstr = "long";
goto add_tstr;
}
switch(bt) {
case VT_VOID:
@ -2833,10 +2825,16 @@ static void type_to_str(char *buf, int buf_size,
goto add_tstr;
case VT_INT:
tstr = "int";
goto add_tstr;
goto maybe_long;
case VT_LLONG:
tstr = "long long";
goto add_tstr;
maybe_long:
if (t & VT_LONG)
tstr = "long";
if (!IS_ENUM(t))
goto add_tstr;
tstr = "enum ";
goto tstruct;
case VT_FLOAT:
tstr = "float";
goto add_tstr;
@ -2902,7 +2900,7 @@ static void type_to_str(char *buf, int buf_size,
casts if needed. */
static void gen_assign_cast(CType *dt)
{
CType *st, *type1, *type2, tmp_type1, tmp_type2;
CType *st, *type1, *type2;
char buf1[256], buf2[256];
int dbt, sbt;
@ -2958,7 +2956,7 @@ static void gen_assign_cast(CType *dt)
in pointer target signedness. Do warn for different
base types, though, in particular for unsigned enums
and signed int targets. */
if ((type1->t & VT_BTYPE) != (type2->t & VT_BTYPE)
if ((type1->t & (VT_BTYPE|VT_LONG)) != (type2->t & (VT_BTYPE|VT_LONG))
|| IS_ENUM(type1->t) || IS_ENUM(type2->t)
)
tcc_warning("assignment from incompatible pointer type");
@ -2982,11 +2980,7 @@ static void gen_assign_cast(CType *dt)
break;
case VT_STRUCT:
case_VT_STRUCT:
tmp_type1 = *dt;
tmp_type2 = *st;
tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
if (!is_compatible_unqualified_types(dt, st)) {
error:
type_to_str(buf1, sizeof(buf1), st, NULL);
type_to_str(buf2, sizeof(buf2), dt, NULL);
@ -3775,10 +3769,10 @@ do_decl:
t.t = VT_INT;
if (nl >= 0) {
if (pl != (unsigned)pl)
t.t = VT_LLONG;
t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG);
t.t |= VT_UNSIGNED;
} else if (pl != (int)pl || nl != (int)nl)
t.t = VT_LLONG;
t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG);
s->type.t = type->t = t.t | VT_ENUM;
s->c = 0;
/* set type for enum members */
@ -3791,7 +3785,8 @@ do_decl:
if (ll == (unsigned)ll)
continue;
}
ss->type.t = (ss->type.t & ~VT_BTYPE) | VT_LLONG;
ss->type.t = (ss->type.t & ~VT_BTYPE)
| (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG);
}
} else {
c = 0;
@ -3964,7 +3959,7 @@ static int parse_btype(CType *type, AttributeDef *ad)
bt = u;
}
if (u != VT_INT)
t = (t & ~VT_BTYPE) | u;
t = (t & ~(VT_BTYPE|VT_LONG)) | u;
typespec_found = 1;
break;
case TOK_VOID:
@ -3978,11 +3973,9 @@ static int parse_btype(CType *type, AttributeDef *ad)
goto basic_type;
case TOK_LONG:
if ((t & VT_BTYPE) == VT_DOUBLE) {
#ifndef TCC_TARGET_PE
t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LDOUBLE;
#endif
} else if (t & VT_LONG) {
t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LLONG;
t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE;
} else if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) {
t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LLONG;
} else {
u = VT_LONG;
goto basic_type;
@ -4003,12 +3996,8 @@ static int parse_btype(CType *type, AttributeDef *ad)
u = VT_FLOAT;
goto basic_type;
case TOK_DOUBLE:
if (t & VT_LONG) {
#ifdef TCC_TARGET_PE
t = (t & ~(VT_LONG | VT_BTYPE)) | VT_DOUBLE;
#else
t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LDOUBLE;
#endif
if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) {
t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE;
} else {
u = VT_DOUBLE;
goto basic_type;
@ -4098,7 +4087,7 @@ static int parse_btype(CType *type, AttributeDef *ad)
parse_attribute(ad);
if (ad->attr_mode) {
u = ad->attr_mode -1;
t = (t & ~VT_BTYPE) | u;
t = (t & ~(VT_BTYPE|VT_LONG)) | u;
}
break;
/* GNUC typeof */
@ -4118,7 +4107,7 @@ static int parse_btype(CType *type, AttributeDef *ad)
s = sym_find(tok);
if (!s || !(s->type.t & VT_TYPEDEF))
goto the_end;
t &= ~VT_BTYPE;
t &= ~(VT_BTYPE|VT_LONG);
u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u;
type->t = (s->type.t & ~VT_TYPEDEF) | u;
type->ref = s->type.ref;
@ -4139,13 +4128,13 @@ the_end:
if ((t & (VT_DEFSIGN|VT_BTYPE)) == VT_BYTE)
t |= VT_UNSIGNED;
}
/* long is never used as type */
if (t & VT_LONG)
#if PTR_SIZE == 8 && !defined TCC_TARGET_PE
t = (t & ~VT_BTYPE) | VT_LLONG;
#else
t = (t & ~VT_BTYPE) | VT_INT;
/* VT_LONG is used just as a modifier for VT_INT / VT_LLONG */
bt = t & (VT_BTYPE|VT_LONG);
if (bt == VT_LONG)
t |= LONG_SIZE == 8 ? VT_LLONG : VT_INT;
#ifdef TCC_TARGET_PE
if (bt == VT_LDOUBLE)
t = (t & ~(VT_BTYPE|VT_LONG)) | VT_DOUBLE;
#endif
type->t = t;
return type_found;
@ -4544,9 +4533,13 @@ ST_FUNC void unary(void)
case TOK_EXTENSION:
next();
goto tok_next;
case TOK_LCHAR:
#ifdef TCC_TARGET_PE
t = VT_SHORT|VT_UNSIGNED;
goto push_tokc;
#endif
case TOK_CINT:
case TOK_CCHAR:
case TOK_LCHAR:
t = VT_INT;
push_tokc:
type.t = t;
@ -4572,14 +4565,10 @@ ST_FUNC void unary(void)
t = VT_LDOUBLE;
goto push_tokc;
case TOK_CLONG:
t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG;
goto push_tokc;
case TOK_CULONG:
#ifdef TCC_LONG_ARE_64_BIT
t = VT_LLONG | VT_LONG;
#else
t = VT_INT | VT_LONG;
#endif
if (tok == TOK_CULONG)
t |= VT_UNSIGNED;
t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED;
goto push_tokc;
case TOK___FUNCTION__:
if (!gnu_ext)
@ -5491,7 +5480,11 @@ static void expr_cond(void)
}
} else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
/* cast to biggest op */
type.t = VT_LLONG;
type.t = VT_LLONG | VT_LONG;
if (bt1 == VT_LLONG)
type.t &= t1;
if (bt2 == VT_LLONG)
type.t &= t2;
/* convert to unsigned if it does not fit in a long long */
if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) ||
(t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED))
@ -5518,7 +5511,7 @@ static void expr_cond(void)
type.t = VT_VOID;
} else {
/* integer operations */
type.t = VT_INT;
type.t = VT_INT | (VT_LONG & (t1 | t2));
/* convert to unsigned if it does not fit in an integer */
if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) ||
(t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED))
@ -6490,20 +6483,20 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
*(double *)ptr = vtop->c.d;
break;
case VT_LDOUBLE:
if (sizeof(long double) == LDOUBLE_SIZE)
*(long double *)ptr = vtop->c.ld;
else if (sizeof(double) == LDOUBLE_SIZE)
*(double *)ptr = (double)vtop->c.ld;
#if (defined __i386__ || defined __x86_64__) && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64)
else if (sizeof (long double) >= 10)
memcpy(memset(ptr, 0, LDOUBLE_SIZE), &vtop->c.ld, 10);
if (sizeof (long double) >= 10) /* zero pad ten-byte LD */
memcpy(ptr, &vtop->c.ld, 10);
#ifdef __TINYC__
else if (sizeof (long double) == sizeof (double))
__asm__("fldl %1\nfstpt %0\n" : "=m"
(memset(ptr, 0, LDOUBLE_SIZE), ptr) : "m" (vtop->c.ld));
__asm__("fldl %1\nfstpt %0\n" : "=m" (ptr) : "m" (vtop->c.ld));
#endif
else
#endif
else
if (sizeof(long double) == LDOUBLE_SIZE)
*(long double*)ptr = vtop->c.ld;
else if (sizeof(double) == LDOUBLE_SIZE)
*(double *)ptr = (double)vtop->c.ld;
else
tcc_error("can't cross compile long double constants");
break;
#if PTR_SIZE != 8

122
tccpp.c
View File

@ -89,7 +89,7 @@ static const unsigned char tok_two_chars[] =
'^','=', TOK_A_XOR,
'|','=', TOK_A_OR,
'-','>', TOK_ARROW,
'.','.', 0xa8, // C++ token ?
'.','.', TOK_TWODOTS,
'#','#', TOK_TWOSHARPS,
0
};
@ -1017,23 +1017,18 @@ static inline int tok_size(const int *p)
case TOK_LCHAR:
case TOK_CFLOAT:
case TOK_LINENUM:
#ifndef TCC_LONG_ARE_64_BIT
case TOK_CLONG;
case TOK_CULONG;
#endif
return 1 + 1;
case TOK_STR:
case TOK_LSTR:
case TOK_PPNUM:
case TOK_PPSTR:
return 1 + ((sizeof(CString) + ((CString *)(p+1))->size + 3) >> 2);
case TOK_CLONG:
case TOK_CULONG:
return 1 + LONG_SIZE / 4;
case TOK_CDOUBLE:
case TOK_CLLONG:
case TOK_CULLONG:
#ifdef TCC_LONG_ARE_64_BIT
case TOK_CLONG;
case TOK_CULONG;
#endif
return 1 + 2;
case TOK_CLDOUBLE:
return 1 + LDOUBLE_SIZE / 4;
@ -1149,7 +1144,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
case TOK_LCHAR:
case TOK_CFLOAT:
case TOK_LINENUM:
#ifndef TCC_LONG_ARE_64_BIT
#if LONG_SIZE == 4
case TOK_CLONG:
case TOK_CULONG:
#endif
@ -1173,7 +1168,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
case TOK_CDOUBLE:
case TOK_CLLONG:
case TOK_CULLONG:
#ifdef TCC_LONG_ARE_64_BIT
#if LONG_SIZE == 8
case TOK_CLONG:
case TOK_CULONG:
#endif
@ -1227,17 +1222,20 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv)
tab = cv->tab;
switch(*t = *p++) {
#if LONG_SIZE == 4
case TOK_CLONG:
#endif
case TOK_CINT:
case TOK_CUINT:
case TOK_CCHAR:
case TOK_LCHAR:
case TOK_LINENUM:
#ifndef TCC_LONG_ARE_64_BIT
case TOK_CLONG:
cv->i = *p++;
break;
#if LONG_SIZE == 4
case TOK_CULONG:
#endif
tab[0] = *p++;
cv->i = (*t == TOK_CUINT) ? (unsigned)cv->i : (int)cv->i;
case TOK_CUINT:
cv->i = (unsigned)*p++;
break;
case TOK_CFLOAT:
tab[0] = *p++;
@ -1253,7 +1251,7 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv)
case TOK_CDOUBLE:
case TOK_CLLONG:
case TOK_CULLONG:
#ifdef TCC_LONG_ARE_64_BIT
#if LONG_SIZE == 8
case TOK_CLONG:
case TOK_CULONG:
#endif
@ -2206,23 +2204,24 @@ static void parse_string(const char *s, int len)
tcc_free(p);
if (sep == '\'') {
int char_size;
int char_size, i, n, c;
/* XXX: make it portable */
if (!is_long)
char_size = 1;
tok = TOK_CCHAR, char_size = 1;
else
char_size = sizeof(nwchar_t);
if (tokcstr.size <= char_size)
tok = TOK_LCHAR, char_size = sizeof(nwchar_t);
n = tokcstr.size / char_size - 1;
if (n < 1)
tcc_error("empty character constant");
if (tokcstr.size > 2 * char_size)
if (n > 1)
tcc_warning("multi-character character constant");
if (!is_long) {
tokc.i = *(int8_t *)tokcstr.data;
tok = TOK_CCHAR;
} else {
tokc.i = *(nwchar_t *)tokcstr.data;
tok = TOK_LCHAR;
for (c = i = 0; i < n; ++i) {
if (is_long)
c = ((nwchar_t *)tokcstr.data)[i];
else
c = (c << 8) | ((char *)tokcstr.data)[i];
}
tokc.i = c;
} else {
tokc.str.size = tokcstr.size;
tokc.str.data = tokcstr.data;
@ -2456,7 +2455,7 @@ static void parse_number(const char *p)
}
} else {
unsigned long long n, n1;
int lcount, ucount, must_64bit;
int lcount, ucount, ov = 0;
const char *p1;
/* integer number */
@ -2483,14 +2482,13 @@ static void parse_number(const char *p)
n1 = n;
n = n * b + t;
/* detect overflow */
/* XXX: this test is not reliable */
if (n < n1)
tcc_error("integer constant overflow");
if (n1 >= 0x1000000000000000ULL && n / b != n1)
ov = 1;
}
/* Determine the characteristics (unsigned and/or 64bit) the type of
the constant must have according to the constant suffix(es) */
lcount = ucount = must_64bit = 0;
lcount = ucount = 0;
p1 = p;
for(;;) {
t = toup(ch);
@ -2500,8 +2498,6 @@ static void parse_number(const char *p)
if (lcount && *(p - 1) != ch)
tcc_error("incorrect integer suffix: %s", p1);
lcount++;
if (lcount == 2)
must_64bit = 1;
ch = *p++;
} else if (t == 'U') {
if (ucount >= 1)
@ -2513,38 +2509,36 @@ static void parse_number(const char *p)
}
}
/* Whether 64 bits are needed to hold the constant's value */
if (n & 0xffffffff00000000LL || must_64bit) {
tok = TOK_CLLONG;
n1 = n >> 32;
} else if (lcount) {
#ifdef TCC_LONG_ARE_64_BIT
n1 = n >> 32;
#else
n1 = n;
#endif
tok = TOK_CLONG;
} else {
tok = TOK_CINT;
n1 = n;
/* Determine if it needs 64 bits and/or unsigned in order to fit */
if (ucount == 0 && b == 10) {
if (lcount <= (LONG_SIZE == 4)) {
if (n >= 0x80000000U)
lcount = (LONG_SIZE == 4) + 1;
}
if (n >= 0x8000000000000000ULL)
ov = 1, ucount = 1;
} else {
if (lcount <= (LONG_SIZE == 4)) {
if (n >= 0x100000000ULL)
lcount = (LONG_SIZE == 4) + 1;
else if (n >= 0x80000000U)
ucount = 1;
}
if (n >= 0x8000000000000000ULL)
ucount = 1;
}
/* Whether type must be unsigned to hold the constant's value */
if (ucount || ((n1 >> 31) && (b != 10))) {
if (tok == TOK_CLLONG)
tok = TOK_CULLONG;
else if (tok == TOK_CLONG)
tok = TOK_CULONG;
else
tok = TOK_CUINT;
/* If decimal and no unsigned suffix, bump to 64 bits or throw error */
} else if (n1 >> 31) {
if (tok == TOK_CINT)
if (ov)
tcc_warning("integer constant overflow");
tok = TOK_CINT;
if (lcount) {
tok = TOK_CLONG;
if (lcount == 2)
tok = TOK_CLLONG;
else
tcc_error("integer constant overflow");
}
}
if (ucount)
++tok; /* TOK_CU... */
tokc.i = n;
}
if (ch)

View File

@ -113,7 +113,7 @@ for %%f in (*tcc.exe *tcc.dll) do @del %%f
:compiler
%CC% -o libtcc.dll -shared ..\libtcc.c %D% -DLIBTCC_AS_DLL
@if errorlevel 1 goto :the_end
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE=0
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D% -DONE_SOURCE"=0"
%CC% -o %PX%-tcc.exe ..\tcc.c %DX%
@if (%TCC_FILES%)==(no) goto :files-done