Hi,Thomas
fixstruct.patch
Let tcc compile yasm software
fixsym.patch
Make the following code to compile
int foo();
int main()
{
int foo();
return 0;
}
fixbitfields.patch
Nothing bug
Patch above, I request to join mob
pass test: gnumake yasm
在 2014年08月13日 21:43, Thomas Preud'homme 写道:
Le lundi 11 août 2014, 00:39:17 jiang a écrit :
+/* gen_ctrl */
+enum {
+ CTRL_NONE,
+ CTRL_CALL,
+ CTRL_FOCE,
+ CTRL_ARGS,
+ CTRL_RETS,
+ CTRL_INIT,
+ CTRL_USED,
+};
+ST_DATA int gen_ctrl;
This is one of my local branch code, want to join the mob after
Alright, I don't really want to see your local branch as long as it's not
ready. Just remove the unused enum for now and add them later in the patches
that add the pieces you are still working on.
Why this vtop > (vstack + 1)? What's so special about a stack with 3
entries or more? It looks fishy.
For example the following expression:
a = b = c; -> (a = (b = c));
Requires three SValue, will be greater than vstack + 1, ret equal to
1. Return right value
a = b
Less than or equal vstack + 1, ret equal to 0.
Does not return the right value
Generate less machine code
Maybe but that seems wrong. Why not have some code for when you have 3
assignments? It's inelegant as it is now.
You should only deal with one assignment at a time so 2 Svalue. In the first
example you give, it means dealing with b = c, then return the Svalue that
correspond to it and then process the a = result assignment that has only 2
Svalue. Improving the right way would mean not generating the code right away
and doing a pass after that.
The final result of your patch should be quite small. If not, either I
underestimate the difficulty of this bug fix (it's quite possible) or you
overcomplicated things.
Cheers,
Thomas
commit 1c0c88408b56d0e4e36b795b7d92f25f6606988a
Author: Jiang <30155...@qq.com>
Date: Mon Aug 18 20:25:19 2014 +0800
fix bitfields
see:
http://lists.nongnu.org/archive/html/tinycc-devel/2014-07/msg00023.html
Conflicts:
tests/tests2/03_struct.c
diff --git a/tcc.h b/tcc.h
index c93cedf..fb618ec 100644
--- a/tcc.h
+++ b/tcc.h
@@ -1192,6 +1192,13 @@ ST_DATA int func_var; /* true if current function is variadic */
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA char *funcname;
+/* gen_ctrl */
+enum {
+ CTRL_NONE,
+ CTRL_FOCE,
+ CTRL_INIT,
+};
+ST_DATA int gen_ctrl;
ST_INLN int is_float(int t);
ST_FUNC int ieee_finite(double d);
diff --git a/tccgen.c b/tccgen.c
index d3d1026..e321f96 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -70,6 +70,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in
ST_DATA int func_vc;
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
ST_DATA char *funcname;
+ST_DATA int gen_ctrl;
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
@@ -1017,6 +1018,7 @@ ST_FUNC void lexpand_nr(void)
}
#endif
+#ifndef TCC_TARGET_X86_64
/* build a long long from two ints */
static void lbuild(int t)
{
@@ -1025,6 +1027,7 @@ static void lbuild(int t)
vtop[-1].type.t = t;
vpop();
}
+#endif
/* rotate n first stack elements to the bottom
I1 ... In -> I2 ... In I1 [top is right]
@@ -1087,7 +1090,8 @@ static void gv_dup(void)
int rc, t, r, r1;
SValue sv;
- t = vtop->type.t;
+#ifndef TCC_TARGET_X86_64
+ t = VT_INT;
if ((t & VT_BTYPE) == VT_LLONG) {
lexpand();
gv_dup();
@@ -1097,15 +1101,16 @@ static void gv_dup(void)
vrotb(4);
/* stack: H L L1 H1 */
lbuild(t);
- vrotb(3);
- vrotb(3);
+ vrott(3);
vswap();
lbuild(t);
vswap();
- } else {
+ } else
+#else
+ t = vtop->type.t;
+#endif
+ {
/* duplicate value */
- rc = RC_INT;
- sv.type.t = VT_INT;
if (is_float(t)) {
rc = RC_FLOAT;
#ifdef TCC_TARGET_X86_64
@@ -1113,8 +1118,9 @@ static void gv_dup(void)
rc = RC_ST0;
}
#endif
- sv.type.t = t;
- }
+ }else
+ rc = RC_INT;
+ sv.type.t = t;
r = gv(rc);
r1 = get_reg(rc);
sv.r = r;
@@ -1909,8 +1915,11 @@ static void force_charshort_cast(int t)
/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
static void gen_cast(CType *type)
{
- int sbt, dbt, sf, df, c, p;
+ int sbt, dbt, dt, sf, df, c, p, bitfield;
+ CType dtype;
+ dtype = *type;
+ bitfield = dtype.t & VT_BITFIELD;
/* special delayed cast for char/short */
/* XXX: in some cases (multiple cascaded casts), it may still
be incorrect */
@@ -1924,10 +1933,11 @@ static void gen_cast(CType *type)
gv(RC_INT);
}
- dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
+ dbt = dtype.t & (VT_BTYPE | VT_UNSIGNED);
+ dt = dbt & VT_BTYPE;
sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
- if (sbt != dbt) {
+ if (sbt != dbt || bitfield) {
sf = is_float(sbt);
df = is_float(dbt);
c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
@@ -1959,6 +1969,8 @@ static void gen_cast(CType *type)
vtop->c.d = (double)vtop->c.ld;
} else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
vtop->c.ull = (unsigned long long)vtop->c.ld;
+ if(bitfield)
+ goto cast_bitfield;
} else if (sf && dbt == VT_BOOL) {
vtop->c.i = (vtop->c.ld != 0);
} else {
@@ -1975,24 +1987,53 @@ static void gen_cast(CType *type)
else if (sbt != VT_LLONG)
vtop->c.ll = vtop->c.i;
- if (dbt == (VT_LLONG|VT_UNSIGNED))
+ if (dbt == (VT_LLONG|VT_UNSIGNED)){
vtop->c.ull = vtop->c.ll;
- else if (dbt == VT_BOOL)
+ if(bitfield)
+ goto cast_bitfield;
+ }else if (dbt == VT_BOOL)
vtop->c.i = (vtop->c.ll != 0);
#ifdef TCC_TARGET_X86_64
else if (dbt == VT_PTR)
;
#endif
else if (dbt != VT_LLONG) {
- int s = 0;
- if ((dbt & VT_BTYPE) == VT_BYTE)
- s = 24;
- else if ((dbt & VT_BTYPE) == VT_SHORT)
- s = 16;
- if(dbt & VT_UNSIGNED)
- vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
- else
- vtop->c.i = ((int)vtop->c.ll << s) >> s;
+ unsigned long long ull;
+ long long ll;
+ int s, warr;
+cast_bitfield:
+ warr = 0;
+ if(bitfield){
+ s = 64 - ((dtype.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
+ dtype.t = dtype.t & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
+ }else if (dt == VT_BYTE){
+ s = 56;
+ }else if (dt == VT_SHORT){
+ s = 48;
+ }else{
+ s = 32;
+ }
+
+ ull = (vtop->c.ull << s) >> s;
+ ll = (vtop->c.ll << s) >> s;
+ if(ull != vtop->c.ull && ll != vtop->c.ll){
+ warr = 1;
+ }
+ if(warr){
+ if(dt == VT_ENUM)
+ dbt |= VT_UNSIGNED;
+ if(gen_ctrl != CTRL_FOCE){
+ if(dt == VT_ENUM)
+ tcc_warning("large integer implicitly truncated to unsigned type");
+ else
+ tcc_warning("overflow in implicit constant conversion");
+ }
+ }
+ if(dbt & VT_UNSIGNED){
+ vtop->c.ull = ull;
+ }else{
+ vtop->c.ll = ll;
+ }
}
}
} else if (p && dbt == VT_BOOL) {
@@ -2018,14 +2059,33 @@ static void gen_cast(CType *type)
dbt != VT_LLONG)
dbt = VT_INT;
gen_cvt_ftoi1(dbt);
- if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
+ if (dbt == VT_INT && (dtype.t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
/* additional cast for char/short... */
vtop->type.t = dbt;
gen_cast(type);
}
}
+ } else if (dbt == VT_BOOL) {
+ /* scalar to bool */
+ vpushi(0);
+ gen_op(TOK_NE);
+ }else if(bitfield){
+ int bits, bit_size = (dtype.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
+
+ dtype.t = dtype.t & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
+ gen_cast(&dtype);
+ if (dt == VT_LLONG) {
+ bits = 64 - bit_size;
+ } else
+ bits = 32 - bit_size;
+ vpushi(bits);
+ gen_op(TOK_SHL);
+ vpushi(bits);
+ /* NOTE: transformed to SHR if unsigned */
+ gen_op(TOK_SAR);
+ }else
#ifndef TCC_TARGET_X86_64
- } else if ((dbt & VT_BTYPE) == VT_LLONG) {
+ if ((dbt & VT_BTYPE) == VT_LLONG) {
if ((sbt & VT_BTYPE) != VT_LLONG) {
/* scalar to long long */
/* machine independent conversion */
@@ -2048,12 +2108,11 @@ static void gen_cast(CType *type)
vtop[-1].r2 = vtop->r;
vpop();
}
+ }
#else
- } else if ((dbt & VT_BTYPE) == VT_LLONG ||
- (dbt & VT_BTYPE) == VT_PTR ||
- (dbt & VT_BTYPE) == VT_FUNC) {
- if ((sbt & VT_BTYPE) != VT_LLONG &&
- (sbt & VT_BTYPE) != VT_PTR &&
+ if((dbt & VT_BTYPE) == VT_LLONG || (dbt & VT_BTYPE) == VT_PTR ||
+ (dbt & VT_BTYPE) == VT_FUNC) {
+ if ((sbt & VT_BTYPE) != VT_LLONG && (sbt & VT_BTYPE) != VT_PTR &&
(sbt & VT_BTYPE) != VT_FUNC) {
/* need to convert from 32bit to 64bit */
int r = gv(RC_INT);
@@ -2063,13 +2122,9 @@ static void gen_cast(CType *type)
o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
}
}
+ }
#endif
- } else if (dbt == VT_BOOL) {
- /* scalar to bool */
- vpushi(0);
- gen_op(TOK_NE);
- } else if ((dbt & VT_BTYPE) == VT_BYTE ||
- (dbt & VT_BTYPE) == VT_SHORT) {
+ else if ((dbt & VT_BTYPE) == VT_BYTE || (dbt & VT_BTYPE) == VT_SHORT) {
if (sbt == VT_PTR) {
vtop->type.t = VT_INT;
tcc_warning("nonportable conversion from pointer to char/short");
@@ -2081,7 +2136,7 @@ static void gen_cast(CType *type)
/* from long long: just take low order word */
lexpand();
vpop();
- }
+ }
/* if lvalue and single word type, nothing to do because
the lvalue already contains the real type size (see
VT_LVAL_xxx constants) */
@@ -2093,7 +2148,7 @@ static void gen_cast(CType *type)
vtop->r = (vtop->r & ~VT_LVAL_TYPE)
| (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
}
- vtop->type = *type;
+ vtop->type = dtype;
}
/* return type size as known at compile time. Put alignment at 'a' */
@@ -2463,24 +2518,35 @@ static void gen_assign_cast(CType *dt)
/* store vtop in lvalue pushed on stack */
ST_FUNC void vstore(void)
{
- int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
+ int sbt, dbt, ft, cc, r, t, size, align, bit_size, bit_pos, rc, delayed_cast, ret;
ft = vtop[-1].type.t;
sbt = vtop->type.t & VT_BTYPE;
dbt = ft & VT_BTYPE;
- if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
- (sbt == VT_INT && dbt == VT_SHORT))
- && !(vtop->type.t & VT_BITFIELD)) {
+ ret = delayed_cast = 0;
+ cc = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
+ if (ft & VT_BITFIELD) {
+ ret = (vtop > (vstack + 1) || gen_ctrl == CTRL_INIT);
+ gen_cast(&vtop[-1].type);
+ if(dbt == VT_BOOL)
+ vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
+ if(ret){
+ if((vtop->r & (VT_VALMASK|VT_LVAL|VT_SYM)) < VT_CONST){
+ gv_dup();
+ }else{
+ vpushv(&vtop[0]);
+ }
+ vrott(3);
+ }
+ }else if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
+ (sbt == VT_INT && dbt == VT_SHORT)) && !cc) {
/* optimize char/short casts */
delayed_cast = VT_MUSTCAST;
- vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
/* XXX: factorize */
if (ft & VT_CONSTANT)
tcc_warning("assignment of read-only location");
} else {
- delayed_cast = 0;
- if (!(ft & VT_BITFIELD))
- gen_assign_cast(&vtop[-1].type);
+ gen_assign_cast(&vtop[-1].type);
}
if (sbt == VT_STRUCT) {
@@ -2522,37 +2588,18 @@ ST_FUNC void vstore(void)
/* bitfield store handling */
bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
+
/* remove bit field info to avoid loops */
vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
- /* duplicate source into other register */
- gv_dup();
- vswap();
- vrott(3);
-
- if((ft & VT_BTYPE) == VT_BOOL) {
- gen_cast(&vtop[-1].type);
- vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
- }
+ vpushi(bit_pos);
+ gen_op(TOK_SHL);
/* duplicate destination */
- vdup();
- vtop[-1] = vtop[-2];
+ vpushv(&vtop[-1]);
- /* mask and shift source */
- if((ft & VT_BTYPE) != VT_BOOL) {
- if((ft & VT_BTYPE) == VT_LLONG) {
- vpushll((1ULL << bit_size) - 1ULL);
- } else {
- vpushi((1 << bit_size) - 1);
- }
- gen_op('&');
- }
- vpushi(bit_pos);
- gen_op(TOK_SHL);
/* load destination, mask and or with source */
- vswap();
- if((ft & VT_BTYPE) == VT_LLONG) {
+ if(dbt == VT_LLONG) {
vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
} else {
vpushi(~(((1 << bit_size) - 1) << bit_pos));
@@ -2563,8 +2610,8 @@ ST_FUNC void vstore(void)
vstore();
/* pop off shifted source from "duplicate source..." above */
- vpop();
-
+ if(ret)
+ vtop--;
} else {
#ifdef CONFIG_TCC_BCHECK
/* bound check case */
@@ -3610,7 +3657,7 @@ static void vpush_tokc(int t)
ST_FUNC void unary(void)
{
- int n, t, align, size, r, sizeof_caller;
+ int n, t, align, size, r, sizeof_caller, save_ctrl;
CType type;
Sym *s;
AttributeDef ad;
@@ -3719,7 +3766,10 @@ ST_FUNC void unary(void)
return;
}
unary();
+ save_ctrl = gen_ctrl;
+ gen_ctrl = CTRL_FOCE;
gen_cast(&type);
+ gen_ctrl = save_ctrl;
}
} else if (tok == '{') {
/* save all registers */
@@ -5132,9 +5182,8 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
static void init_putv(CType *type, Section *sec, unsigned long c,
int v, int expr_type)
{
- int saved_global_expr, bt, bit_pos, bit_size;
+ int saved_global_expr, bt, bit_pos, bit_size, save_ctrl;
void *ptr;
- unsigned long long bit_mask;
CType dtype;
switch(expr_type) {
@@ -5152,7 +5201,10 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
tcc_error("initializer element is not constant");
break;
case EXPR_ANY:
+ save_ctrl = gen_ctrl;
+ gen_ctrl = CTRL_INIT;
expr_eq();
+ gen_ctrl = save_ctrl;
break;
}
@@ -5173,11 +5225,9 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
if (!(type->t & VT_BITFIELD)) {
bit_pos = 0;
bit_size = 32;
- bit_mask = -1LL;
} else {
- bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
- bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
- bit_mask = (1LL << bit_size) - 1;
+ bit_pos = (dtype.t >> VT_STRUCT_SHIFT) & 0x3f;
+ bit_size = (dtype.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
}
if ((vtop->r & VT_SYM) &&
(bt == VT_BYTE ||
@@ -5191,10 +5241,10 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
case VT_BOOL:
vtop->c.i = (vtop->c.i != 0);
case VT_BYTE:
- *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
+ *(char *)ptr |= vtop->c.i << bit_pos;
break;
case VT_SHORT:
- *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
+ *(short *)ptr |= vtop->c.i << bit_pos;
break;
case VT_DOUBLE:
*(double *)ptr = vtop->c.d;
@@ -5203,19 +5253,19 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
*(long double *)ptr = vtop->c.ld;
break;
case VT_LLONG:
- *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
+ *(long long *)ptr |= vtop->c.ll << bit_pos;
break;
case VT_PTR:
if (vtop->r & VT_SYM) {
greloc(sec, vtop->sym, c, R_DATA_PTR);
}
- *(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos;
+ *(addr_t *)ptr |= vtop->c.ptr_offset << bit_pos;
break;
default:
if (vtop->r & VT_SYM) {
greloc(sec, vtop->sym, c, R_DATA_PTR);
}
- *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
+ *(int *)ptr |= vtop->c.i << bit_pos;
break;
}
vtop--;
diff --git a/tests/tests2/03_struct.c b/tests/tests2/03_struct.c
index 3b99e30..8b3acee 100644
--- a/tests/tests2/03_struct.c
+++ b/tests/tests2/03_struct.c
@@ -13,12 +13,24 @@ static int eval_rept()
return 0;
}
+struct command_switch {
+ unsigned int env:1; /* Can come from MAKEFLAGS. */
+ unsigned int toenv:1; /* Should be put in MAKEFLAGS. */
+ unsigned int no_makefile:1; /* Don't propagate when remaking makefiles. */
+};
+static const struct command_switch switches = {1, 1, 3};
+
struct fred
{
int boris;
int natasha;
};
+void foo(int a, int b, int c)
+{
+ printf("%d / %d / %d\n", a, b, c);
+}
+
int main()
{
struct fred bloggs;
@@ -43,5 +55,40 @@ int main()
printf("%d\n", jones[1].boris);
printf("%d\n", jones[1].natasha);
- return 0;
+ struct sbf1 {
+ int f1 : 3;
+ int : 2;
+ int f2 : 1;
+ int : 0;
+ int f3 : 5;
+ int f4 : 7;
+ unsigned int f5 : 7;
+ } st1;
+ st1.f1 = st1.f2 = st1.f3 = st1.f4 = st1.f5 = 3;
+ printf("%d %d %d %d %d\n",
+ st1.f1, st1.f2, st1.f3, st1.f4, st1.f5);
+
+ struct { unsigned a:9, b:7, c:5; } s1;
+ s1.a = s1.b = s1.c = 3;
+ printf("%d / %d / %d\n", s1.a, s1.b, s1.c);
+
+ struct {
+ unsigned a:9, b:5, c:7;
+ } s2, *ps = &s2;
+ int n = 250;
+
+ int ii = ps->a = ps->b = ps->c = n + 4;
+ printf("%d / %d / %d\n", ps->a, ps->b, ps->c);
+ printf("%d\n", ii);
+
+ ps->a = n + 4;
+ ps->b = n + 4;
+ ps->c = n + 4;
+ printf("%d / %d / %d\n", ps->a, ps->b, ps->c);
+
+ printf("%d, %d, %d\n", switches.env, switches.toenv, switches.no_makefile);
+
+ foo(ps->a = n + 4, ps->b = n + 4, ps->c = n + 4);
+
+ return 0;
}
diff --git a/tests/tests2/03_struct.expect b/tests/tests2/03_struct.expect
index ecbf589..e6a0db1 100644
--- a/tests/tests2/03_struct.expect
+++ b/tests/tests2/03_struct.expect
@@ -1,6 +1,15 @@
+03_struct.c:8: warning: overflow in implicit constant conversion
+03_struct.c:51: warning: overflow in implicit constant conversion
12
34
12
34
56
78
+-1 -1 3 3 3
+3 / 3 / 3
+30 / 30 / 126
+30
+254 / 30 / 126
+1, 1, 1
+254 / 30 / 126
commit 0c67ef96bc161927ea6562f6ba0fa3578132de38
Author: Jiang <30155...@qq.com>
Date: Mon Aug 18 19:38:23 2014 +0800
Let the following be compiled:
struct buffered_lines_head {
int *slh_first;
};
static int eval_rept()
{
struct buffered_lines_head {
int *slh_first;
} lines;
return 0;
}
int main()
{
struct buffered_lines_head ppp;
ppp.slh_first = 0;
return 0;
}
diff --git a/tccgen.c b/tccgen.c
index 5fd127f..639ad64 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -317,7 +317,7 @@ static void apply_visibility(Sym *sym, CType *type)
ElfW(Sym) *esym;
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
- vis >>= VT_VIS_SHIFT;
+ vis >>= VT_VIS_SHIFT;
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis;
}
}
@@ -2851,15 +2851,17 @@ static void struct_decl(CType *type, int u, int tdef)
/* we put an undefined size for struct/union */
s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
s->r = 0; /* default alignment is zero as gcc */
- /* put struct/union/enum name in type */
do_decl:
- type->t = u;
- type->ref = s;
-
if (tok == '{') {
+ if (s->c != -1){
+ if(local_stack){
+ s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
+ s->r = 0; /* default alignment is zero as gcc */
+ }else{
+ tcc_error("struct/union/enum already defined");
+ }
+ }
next();
- if (s->c != -1)
- tcc_error("struct/union/enum already defined");
/* cannot be empty */
c = 0;
/* non empty enums are not allowed */
@@ -2900,9 +2902,9 @@ static void struct_decl(CType *type, int u, int tdef)
while (tok != '}') {
parse_btype(&btype, &ad);
while (1) {
- if (flexible)
- tcc_error("flexible array member '%s' not at the end of struct",
- get_tok_str(v, NULL));
+ if (flexible)
+ tcc_error("flexible array member '%s' not at the end of struct",
+ get_tok_str(v, NULL));
bit_size = -1;
v = 0;
type1 = btype;
@@ -3035,6 +3037,9 @@ static void struct_decl(CType *type, int u, int tdef)
s->r = maxalign;
}
}
+ /* put struct/union/enum name in type */
+ type->t = u;
+ type->ref = s;
}
/* return 1 if basic type is a type size (short, long, long long) */
@@ -5704,12 +5709,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
} else {
/* push global reference */
sym = get_sym_ref(type, sec, addr, size);
- vpushsym(type, sym);
+ vpushsym(type, sym);
}
/* patch symbol weakness */
if (type->t & VT_WEAK)
weaken_symbol(sym);
- apply_visibility(sym, type);
+ apply_visibility(sym, type);
#ifdef CONFIG_TCC_BCHECK
/* handles bounds now because the symbol must be defined
before for the relocation */
@@ -6027,10 +6032,10 @@ static int decl0(int l, int is_for_loop_init)
if (sym->type.t & VT_STATIC)
type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
- /* If the definition has no visibility use the
- one from prototype. */
- if (! (type.t & VT_VIS_MASK))
- type.t |= sym->type.t & VT_VIS_MASK;
+ /* If the definition has no visibility use the
+ one from prototype. */
+ if (! (type.t & VT_VIS_MASK))
+ type.t |= sym->type.t & VT_VIS_MASK;
if (!is_compatible_types(&sym->type, &type)) {
func_error1:
diff --git a/tests/tests2/03_struct.c b/tests/tests2/03_struct.c
index c5d48c5..3b99e30 100644
--- a/tests/tests2/03_struct.c
+++ b/tests/tests2/03_struct.c
@@ -1,5 +1,18 @@
#include <stdio.h>
+truct buffered_lines_head {
+ int *slh_first;
+};
+
+static int eval_rept()
+{
+ /* Test locally defined */
+ struct buffered_lines_head {
+ int *slh_first;
+ } lines;
+ return 0;
+}
+
struct fred
{
int boris;
@@ -8,24 +21,27 @@ struct fred
int main()
{
- struct fred bloggs;
+ struct fred bloggs;
+ struct buffered_lines_head tst;
+ /* Test locally defined */
+ tst.slh_first = 0;
- bloggs.boris = 12;
- bloggs.natasha = 34;
+ bloggs.boris = 12;
+ bloggs.natasha = 34;
- printf("%d\n", bloggs.boris);
- printf("%d\n", bloggs.natasha);
+ printf("%d\n", bloggs.boris);
+ printf("%d\n", bloggs.natasha);
- struct fred jones[2];
- jones[0].boris = 12;
- jones[0].natasha = 34;
- jones[1].boris = 56;
- jones[1].natasha = 78;
+ struct fred jones[2];
+ jones[0].boris = 12;
+ jones[0].natasha = 34;
+ jones[1].boris = 56;
+ jones[1].natasha = 78;
- printf("%d\n", jones[0].boris);
- printf("%d\n", jones[0].natasha);
- printf("%d\n", jones[1].boris);
- printf("%d\n", jones[1].natasha);
+ printf("%d\n", jones[0].boris);
+ printf("%d\n", jones[0].natasha);
+ printf("%d\n", jones[1].boris);
+ printf("%d\n", jones[1].natasha);
return 0;
}
commit f9bc17c8d074d5b908d57998ef10924e467465ee
Author: Jiang <30155...@qq.com>
Date: Sat Aug 16 21:19:57 2014 +0800
external_global_sym -> external_sym
diff --git a/tccgen.c b/tccgen.c
index 639ad64..d3d1026 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -3972,7 +3972,7 @@ ST_FUNC void unary(void)
#endif
)
tcc_warning("implicit declaration of function '%s'", name);
- s = external_global_sym(t, &func_old_type, 0);
+ s = external_sym(t, &func_old_type, 0, NULL);
}
if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
(VT_STATIC | VT_INLINE | VT_FUNC)) {
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel