History

mutiples fix for _Generic

* check that _Generic don't match unsigned char * with char * this case is usefull as with -funsigned-char, 'char *' are unsigned * change VT_LONG so it's now a qualifier VT_LONG are never use for code generation, but only durring parsing state, in _Generic we need to be able to make diference between 'long' and 'long long' So VT_LONG is now use as a type qualifier, it's old behaviour is still here, but we can keep trace of what was a long and what wasn't * add TOK_CLONG and TOK_CULONG tcc was directly converting value like '7171L' into TOK_CLLONG or TOK_CINT depending of the machine architecture. because of that, we was unable to make diference between a long and a long long, which doesn't work with _Generic. So now 7171L is a TOK_CLONG, and we can handle _Generic properly * check that _Generic can make diference between long and long long * uncomment "type match twice" as it should now pass tests on any platforms * add inside_generic global the point of this variable is to use VT_LONG in comparaison only when we are evaluating a _Generic. problem is with my lastest patchs tcc can now make the diference between a 'long long' and a 'long', but in 64 bit stddef.h typedef uint64_t as typedef signed long long int int64_t and stdint.h as unsigned long int, so tcc break when stdint.h and stddef.h are include together. Another solution woud be to modifie include/stddef.h so it define uint64_t as unsigned long int when processor is 64 bit, but this could break some legacy code, so for now, VT_LONG are use only inside generc. * check that _Generic parse first argument correctly * check that _Generic evaluate correctly exresion like "f() / 2"

matthias committed 9 years ago

Commit fdc18d31 parent 0cc24d05 files · +106 −23Browse files

Unified · Split

5 files
  1. tcc.h +11 −2
  2. tccgen.c +42 −14
  3. tccpp.c +36 −3
  4. tests/tests2/94_generic.c +13 −3
  5. tests/tests2/94_generic.expect +4 −1
tcc.h+11−2
@@ -849,7 +849,6 @@ struct filespec { · 848 unmodified lines
849849 #define VT_DOUBLE 9 /* IEEE double */
850850 #define VT_LDOUBLE 10 /* IEEE long double */
851851 #define VT_BOOL 11 /* ISOC99 boolean type */
852−#define VT_LONG 12 /* long integer (NEVER USED as type, only during parsing) */
853852 #define VT_QLONG 13 /* 128-bit integer. Only used for x86-64 ABI */
854853 #define VT_QFLOAT 14 /* 128-bit float. Only used for x86-64 ABI */
855854
@@ -860,6 +859,7 @@ struct filespec { · 4 unmodified lines
860859 #define VT_CONSTANT 0x0100 /* const modifier */
861860 #define VT_VOLATILE 0x0200 /* volatile modifier */
862861 #define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
862+#define VT_LONG 0x0800
863863
864864 /* storage */
865865 #define VT_EXTERN 0x00001000 /* extern definition */
@@ -939,7 +939,16 @@ struct filespec { · 73 unmodified lines
939939 #define TOK_TWOSHARPS 0xca /* ## preprocessing token */
940940 #define TOK_PLCHLDR 0xcb /* placeholder token as defined in C99 */
941941 #define TOK_NOSUBST 0xcc /* means following token has already been pp'd */
942−#define TOK_PPJOIN 0xce /* A '##' in the right position to mean pasting */
942+#define TOK_PPJOIN 0xcd /* A '##' in the right position to mean pasting */
943+
944+#define TOK_CLONG 0xce /* long constant */
945+#define TOK_CULONG 0xcf /* unsigned long constant */
946+
947+
948+#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
949+ #define TCC_LONG_ARE_64_BIT
950+#endif
951+
943952
944953 #define TOK_SHL 0x01 /* shift left */
945954 #define TOK_SAR 0x02 /* signed shift right */
tccgen.c+42−14
@@ -42,6 +42,7 @@ ST_DATA Sym *local_label_stack; · 41 unmodified lines
4242 static int local_scope;
4343 static int in_sizeof;
4444 static int section_sym;
45+static int inside_generic;
4546
4647 ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */
4748 ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */
@@ -2218,6 +2219,10 @@ redo: · 2170 unmodified lines
22182219 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
22192220 /* cast to biggest op */
22202221 t = VT_LLONG;
2222+ /* check if we need to keep type as long or as long long */
2223+ if ((t1 & VT_LONG && (t2 & (VT_BTYPE | VT_LONG)) != VT_LLONG) ||
2224+ (t2 & VT_LONG && (t1 & (VT_BTYPE | VT_LONG)) != VT_LLONG))
2225+ t |= VT_LONG;
22212226 /* convert to unsigned if it does not fit in a long long */
22222227 if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) ||
22232228 (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED))
@@ -2226,7 +2231,11 @@ redo: · 2 unmodified lines
22262231 } else {
22272232 /* integer operations */
22282233 t = VT_INT;
2229− /* convert to unsigned if it does not fit in an integer */
2234+
2235+ if ((t1 & VT_LONG) || (t2 & VT_LONG))
2236+ t |= VT_LONG;
2237+
2238+ /* convert to unsigned if it does not fit in an integer */
22302239 if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) ||
22312240 (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED))
22322241 t |= VT_UNSIGNED;
@@ -2723,6 +2732,11 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 490 unmodified lines
27232732 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
27242733 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
27252734 }
2735+
2736+ if (!inside_generic) {
2737+ t1 &= ~VT_LONG;
2738+ t2 &= ~VT_LONG;
2739+ }
27262740 /* Default Vs explicit signedness only matters for char */
27272741 if ((t1 & VT_BTYPE) != VT_BYTE) {
27282742 t1 &= ~VT_DEFSIGN;
@@ -2799,6 +2813,12 @@ static void type_to_str(char *buf, int buf_size, · 70 unmodified lines
27992813 tstr = "enum ";
28002814 goto tstruct;
28012815 }
2816+
2817+ if (!bt && VT_LONG & t) {
2818+ tstr = "long";
2819+ goto add_tstr;
2820+ }
2821+
28022822 switch(bt) {
28032823 case VT_VOID:
28042824 tstr = "void";
@@ -2815,9 +2835,6 @@ static void type_to_str(char *buf, int buf_size, · 10 unmodified lines
28152835 case VT_INT:
28162836 tstr = "int";
28172837 goto add_tstr;
2818− case VT_LONG:
2819− tstr = "long";
2820− goto add_tstr;
28212838 case VT_LLONG:
28222839 tstr = "long long";
28232840 goto add_tstr;
@@ -3960,10 +3977,10 @@ static int parse_btype(CType *type, AttributeDef *ad) · 1136 unmodified lines
39603977 case TOK_LONG:
39613978 if ((t & VT_BTYPE) == VT_DOUBLE) {
39623979 #ifndef TCC_TARGET_PE
3963− t = (t & ~VT_BTYPE) | VT_LDOUBLE;
3980+ t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LDOUBLE;
39643981 #endif
3965− } else if ((t & VT_BTYPE) == VT_LONG) {
3966− t = (t & ~VT_BTYPE) | VT_LLONG;
3982+ } else if (t & VT_LONG) {
3983+ t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LLONG;
39673984 } else {
39683985 u = VT_LONG;
39693986 goto basic_type;
@@ -3984,11 +4001,11 @@ static int parse_btype(CType *type, AttributeDef *ad) · 14 unmodified lines
39844001 u = VT_FLOAT;
39854002 goto basic_type;
39864003 case TOK_DOUBLE:
3987− if ((t & VT_BTYPE) == VT_LONG) {
4004+ if (t & VT_LONG) {
39884005 #ifdef TCC_TARGET_PE
3989− t = (t & ~VT_BTYPE) | VT_DOUBLE;
4006+ t = (t & ~(VT_LONG | VT_BTYPE)) | VT_DOUBLE;
39904007 #else
3991− t = (t & ~VT_BTYPE) | VT_LDOUBLE;
4008+ t = (t & ~(VT_LONG | VT_BTYPE)) | VT_LDOUBLE;
39924009 #endif
39934010 } else {
39944011 u = VT_DOUBLE;
@@ -4122,7 +4139,7 @@ the_end: · 127 unmodified lines
41224139 }
41234140
41244141 /* long is never used as type */
4125− if ((t & VT_BTYPE) == VT_LONG)
4142+ if (t & VT_LONG)
41264143 #if PTR_SIZE == 8 && !defined TCC_TARGET_PE
41274144 t = (t & ~VT_BTYPE) | VT_LLONG;
41284145 #else
@@ -4552,7 +4569,16 @@ ST_FUNC void unary(void) · 423 unmodified lines
45524569 case TOK_CLDOUBLE:
45534570 t = VT_LDOUBLE;
45544571 goto push_tokc;
4555−
4572+ case TOK_CLONG:
4573+ case TOK_CULONG:
4574+ #ifdef TCC_LONG_ARE_64_BIT
4575+ t = VT_LLONG | VT_LONG;
4576+ #else
4577+ t = VT_INT | VT_LONG;
4578+ #endif
4579+ if (tok == TOK_CULONG)
4580+ t |= VT_UNSIGNED;
4581+ goto push_tokc;
45564582 case TOK___FUNCTION__:
45574583 if (!gnu_ext)
45584584 goto tok_identifier;
@@ -4906,8 +4932,9 @@ ST_FUNC void unary(void) · 347 unmodified lines
49064932
49074933 next();
49084934 skip('(');
4935+ inside_generic = 1;
49094936 expr_type(&controlling_type, expr_eq);
4910− controlling_type.t &= ~(VT_CONSTANT|VT_VOLATILE|VT_ARRAY);
4937+ controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY);
49114938 for (;;) {
49124939 learn = 0;
49134940 skip(',');
@@ -4926,7 +4953,7 @@ ST_FUNC void unary(void) · 12 unmodified lines
49264953 type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT);
49274954 if (compare_types(&controlling_type, &cur_type, 0)) {
49284955 if (has_match) {
4929− // tcc_error("type match twice");
4956+ tcc_error("type match twice");
49304957 }
49314958 has_match = 1;
49324959 learn = 1;
@@ -4950,6 +4977,7 @@ ST_FUNC void unary(void) · 17 unmodified lines
49504977 }
49514978 begin_macro(str, 1);
49524979 next();
4980+ inside_generic = 0;
49534981 expr_eq();
49544982 if (tok != TOK_EOF)
49554983 expect(",");
tccpp.c+36−3
@@ -480,6 +480,8 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv) · 479 unmodified lines
480480 switch(v) {
481481 case TOK_CINT:
482482 case TOK_CUINT:
483+ case TOK_CLONG:
484+ case TOK_CULONG:
483485 case TOK_CLLONG:
484486 case TOK_CULLONG:
485487 /* XXX: not quite exact, but only useful for testing */
@@ -1014,6 +1016,10 @@ static inline int tok_size(const int *p) · 528 unmodified lines
10141016 case TOK_LCHAR:
10151017 case TOK_CFLOAT:
10161018 case TOK_LINENUM:
1019+#ifndef TCC_LONG_ARE_64_BIT
1020+ case TOK_CLONG;
1021+ case TOK_CULONG;
1022+#endif
10171023 return 1 + 1;
10181024 case TOK_STR:
10191025 case TOK_LSTR:
@@ -1023,6 +1029,10 @@ static inline int tok_size(const int *p) · 3 unmodified lines
10231029 case TOK_CDOUBLE:
10241030 case TOK_CLLONG:
10251031 case TOK_CULLONG:
1032+#ifdef TCC_LONG_ARE_64_BIT
1033+ case TOK_CLONG;
1034+ case TOK_CULONG;
1035+#endif
10261036 return 1 + 2;
10271037 case TOK_CLDOUBLE:
10281038 return 1 + LDOUBLE_SIZE / 4;
@@ -1138,6 +1148,10 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) · 109 unmodified lines
11381148 case TOK_LCHAR:
11391149 case TOK_CFLOAT:
11401150 case TOK_LINENUM:
1151+#ifndef TCC_LONG_ARE_64_BIT
1152+ case TOK_CLONG:
1153+ case TOK_CULONG:
1154+#endif
11411155 str[len++] = cv->tab[0];
11421156 break;
11431157 case TOK_PPNUM:
@@ -1158,6 +1172,10 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) · 14 unmodified lines
11581172 case TOK_CDOUBLE:
11591173 case TOK_CLLONG:
11601174 case TOK_CULLONG:
1175+#ifdef TCC_LONG_ARE_64_BIT
1176+ case TOK_CLONG:
1177+ case TOK_CULONG:
1178+#endif
11611179 #if LDOUBLE_SIZE == 8
11621180 case TOK_CLDOUBLE:
11631181 #endif
@@ -1213,6 +1231,10 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) · 49 unmodified lines
12131231 case TOK_CCHAR:
12141232 case TOK_LCHAR:
12151233 case TOK_LINENUM:
1234+#ifndef TCC_LONG_ARE_64_BIT
1235+ case TOK_CLONG:
1236+ case TOK_CULONG:
1237+#endif
12161238 tab[0] = *p++;
12171239 cv->i = (*t == TOK_CUINT) ? (unsigned)cv->i : (int)cv->i;
12181240 break;
@@ -1230,6 +1252,10 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) · 11 unmodified lines
12301252 case TOK_CDOUBLE:
12311253 case TOK_CLLONG:
12321254 case TOK_CULLONG:
1255+#ifdef TCC_LONG_ARE_64_BIT
1256+ case TOK_CLONG:
1257+ case TOK_CULONG:
1258+#endif
12331259 n = 2;
12341260 goto copy;
12351261 case TOK_CLDOUBLE:
@@ -2407,9 +2433,7 @@ static void parse_number(const char *p) · 1171 unmodified lines
24072433 if (lcount && *(p - 1) != ch)
24082434 tcc_error("incorrect integer suffix: %s", p1);
24092435 lcount++;
2410−#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
24112436 if (lcount == 2)
2412−#endif
24132437 must_64bit = 1;
24142438 ch = *p++;
24152439 } else if (t == 'U') {
@@ -2426,6 +2450,13 @@ static void parse_number(const char *p) · 10 unmodified lines
24262450 if (n & 0xffffffff00000000LL || must_64bit) {
24272451 tok = TOK_CLLONG;
24282452 n1 = n >> 32;
2453+ } else if (lcount) {
2454+#ifdef TCC_LONG_ARE_64_BIT
2455+ n1 = n >> 32;
2456+#else
2457+ n1 = n;
2458+#endif
2459+ tok = TOK_CLONG;
24292460 } else {
24302461 tok = TOK_CINT;
24312462 n1 = n;
@@ -2435,7 +2466,9 @@ static void parse_number(const char *p) · 3 unmodified lines
24352466 if (ucount || ((n1 >> 31) && (b != 10))) {
24362467 if (tok == TOK_CLLONG)
24372468 tok = TOK_CULLONG;
2438− else
2469+ else if (tok == TOK_CLONG)
2470+ tok = TOK_CULONG;
2471+ else
24392472 tok = TOK_CUINT;
24402473 /* If decimal and no unsigned suffix, bump to 64 bits or throw error */
24412474 } else if (n1 >> 31) {
tests/tests2/94_generic.c+13−3
@@ -20,6 +20,8 @@ int b_f() · 19 unmodified lines
2020 return 10;
2121 }
2222
23+typedef int int_type1;
24+
2325 #define gen_sw(a) _Generic(a, const char *: 1, default: 8, int: 123);
2426
2527 int main()
@@ -28,24 +30,32 @@ int main() · 2 unmodified lines
2830 struct b titi;
2931 const int * const ptr;
3032 const char *ti;
33+ int_type1 i2;
3134
3235 i = _Generic(a, int: a_f, const int: b_f)();
3336 printf("%d\n", i);
37+ i = _Generic(a, int: a_f() / 2, const int: b_f() / 2);
38+ printf("%d\n", i);
3439 i = _Generic(ptr, int *:1, int * const:2, default:20);
3540 printf("%d\n", i);
3641 i = gen_sw(a);
3742 printf("%d\n", i);
3843 i = _Generic(titi, struct a:1, struct b:2, default:20);
3944 printf("%d\n", i);
45+ i = _Generic(i2, char: 1, int : 0);
46+ printf("%d\n", i);
4047 i = _Generic(a, char:1, int[4]:2, default:5);
4148 printf("%d\n", i);
4249 i = _Generic(17, int :1, int **:2);
4350 printf("%d\n", i);
44− i = _Generic(17L, int :1, long :2);
51+ i = _Generic(17L, int :1, long :2, long long : 3);
4552 printf("%d\n", i);
46− i = _Generic("17, io", const char *:1, char *:3, const int :2);
53+ i = _Generic("17, io", char *: 3, const char *: 1);
4754 printf("%d\n", i);
48− i = _Generic(ti, const char *:1, char *:3, const int :2);
55+ i = _Generic(ti, const unsigned char *:1, const char *:4, char *:3,
56+ const signed char *:2);
4957 printf("%d\n", i);
58+ printf("%s\n", _Generic(i + 2L, long: "long", int: "int",
59+ long long: "long long"));
5060 return 0;
5161 }
tests/tests2/94_generic.expect+4−1
@@ -1,9 +1,12 @@
11 20
2+10
23 20
34 123
45 2
6+0
57 5
68 1
79 2
810 3
9−1
11+4
12+long

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t