If a condition is always zero/non-zero we can omit the
then or else code. This is complicated a bit by having to
deal with labels that might make such code reachable without
us yet knowing during parsing.
Not fully thought out. You can't jump inside stmt exprs,
but you can jump out of them. So there's a difference
between undefined but declared labels at the end of stmt
exprs and those defined inside. Additionally it should
also be checked if a label defined inside a stmt expr
was tentatively created as declared from outside.
I'm not prepared doing that right now, so simply revert.
This reverts commit 9160e4cab9147d77840cc44a285031fdb4640cf9.
One can't jump into statement expressions from outside
them, like the following:
int i = ({ label: foo(); 42; });
goto label;
We reject this by making the labels simply not available
outside (GCC has a nicer error message about jumping into
a statement expression).
In statement expression we really mustn't emit backward jumps
under nocode_wanted (they will form infinte loops as no expressions
are evaluated). Do-while and explicit loop with gotos weren't
handled.
The return value of statement expressions might refer to local
symbols, so those can't be popped. The old error message always
was just a band-aid, and since disabling it for pointer types it
wasn't effective anyway. It also never considered that also the
vtop->sym member might have referred to such symbols (see the
testcase with the local static, that used to segfault).
For fixing this (can be seen better with valgrind and SYM_DEBUG)
simply leave local symbols of stmt exprs on the stack.
But like GCC do warn about changes in signedness. The latter
leads to some changes in gen_assign_cast to not also warn about
unsigned* = int*
(where GCC warns, but only with extra warnings).
For
union U { struct {int a,b}; int c; };
union U u = {{ 1, 2, }};
The unnamed first member of union U needs to actually exist in the
structure so initializer parsing isn't confused about the double braces.
That means also the a and b members must be part of _that_, not of
union U directly. Which in turn means we need to do a bit more work
for field lookup.
See the testcase extension for more things that need to work.
Remove dead code and variables. Properly check for unions when
skipping fields in initializers. Make tests2/*.expect depend
on the .c files so they are automatically rebuilt when the latter
change.
E.g. "struct { struct S s; int a;} = { others, 42 };"
if 'others' is also a 'struct S'. Also when the value is a
compound literal. See added testcases.
Start reimplementing the whole initializer handling to be
conforming to ISO C. This patch just reimplements current
functionality to prepare for further changes, all tests pass.
This snippet is valid:
void foo(void);
... foo + 42 ...
the function designator is converted to pointer to function
implicitely. gen_op didn't do that and bailed out.
This must compile:
typedef int arrtype1[];
arrtype1 sinit19 = {1};
arrtype1 sinit20 = {2,3};
and generate two arrays of one resp. two elements. Before the fix
the determined size of the first array was encoded in the type
directly, so sinit20 couldn't be parsed anymore (because arrtype1
was thought to be only one element long).
Given this code:
struct __attribute__((...)) Name {...};
TCC was eating "Name", hence generating an anonymous struct.
It also didn't apply any packed attributes to the parsed
members. Both fixed. The testcase also contains a case
that isn't yet handled by TCC (under a BROKEN #define).
add_elf_sym is a confusing name because it is not clear what the
function does compared to put_elf_sym. As a matter of fact, put_elf_sym
also adds a symbol in a symbol table. Besides, "add_elf_sym" fails to
convey that the function can be used to update a symbol (for instance
its value). "set_elf_sym" seems like a more appropriate name: it will
set a symbol to a given set of properties (value, size, etc.) and create
a new one if non exist for that name as one would expect.
With the last improvements to lexpand it's now harmful
to use on native 64bit platforms when not necessary. For gv_dup
it's not necessary there. It can still be used with really
transforming a 64bit value into two 32bit ones.
Previously, long longs were 'lexpand'ed into two registers
always.
Now, it expands
- constants into two constants (lo-part, hi-part)
- variables into two lvalues with offset+4 for the hi-part.
This makes long long operations look a bit nicer.
Also: don't apply i386 'inc/dec' optimization if carry
generation is wanted.
gen_cast() failed to truncate long long's if they
were unsigned, which was causing mess on the vstack.
There was a similar bug here
tccgen: 32bits: fix PTR +/- long long
ed15cddacd
Both were not visible until this patch
tccgen: arm/i386: save_reg_upstack
b691585785
I'd still assume that this patch is correct per se.
Also:
- remove 2x !nocode_wanted (we are already under a general
"else if (!nocode_wanted)" clause above).
__GNUC__ nowadays as macro seems to mean the "GNU C dialect"
rather than the compiler itself. See also
http://gcc.gnu.org/ml/gcc/2008-07/msg00026.html
This patch will probably cause problems of various kinds but
maybe we should try nonetheless.
Previously in order to perform a ll+ll operation tcc
was trying to 'lexpand' PTR in gen_opl which did
not work well. The case:
int printf(const char *, ...);
char t[] = "012345678";
int main(void)
{
char *data = t;
unsigned long long r = 4;
unsigned a = 5;
unsigned long long b = 12;
*(unsigned*)(data + r) += a - b;
printf("data %s\n", data);
return 0;
}