Commit Graph

136 Commits (370547a550e73d91e95cac6145a7df7947025bb0)

Author SHA1 Message Date
Thomas Preud'homme 370547a550 Revert "Check whether structure fields have a type"
This reverts commit 981eb84d8a.
2013-01-31 13:02:04 +01:00
Thomas Preud'homme 981eb84d8a Check whether structure fields have a type 2013-01-31 12:32:31 +01:00
Domingo Alvarez Duarte 93785149ed Add predictability in CType initialization.
Initialize the ref field to 0 when manipulating a CType.

Signed-off-by: Thomas Preud'homme <robotux@celest.fr>
2013-01-31 12:04:10 +01:00
grischka c5892fe4f5 Revert "Optimize vswap()"
This reverts commit 63193d1794.

Had some problems (_STATIC_ASSERT) and was too ugly anyway.
For retry, I'd suggest to implement a general function
    static inline void memswap (void *p1, void* p2, size_t n);
and then use that.  If you do so, please keep the original code
as comment.
2013-01-14 18:41:37 +01:00
Thomas Preud'homme ea583f7b8a Fix C99ism in vswap()
Declare vtopl in vswap at the beginning of the function before any
assignments. Doing otherwise means C99 is assumed when compiling.
2013-01-13 23:38:33 +01:00
grischka 2358b378b3 tccpp: alternative fix for #include_next infinite loop bug
This replaces commit 3d409b0889

- revert old fix in libtcc.c
- #include_next: look up the file in the include stack to see
  if it is already included.
Also:
- streamline include code
- remove 'type' from struct CachedInclude (obsolete because we check
  full filename anyway)
- remove inc_type & inc_filename from struct Bufferedfile (obsolete)
- fix bug with TOK_FLAG_ENDIF not being reset
- unrelated: get rid of an 'variable potentially uninitialized' warning
2013-01-06 17:20:44 +01:00
Kirill Smelkov 63193d1794 Optimize vswap()
vswap() is called often enough and shows in profile and it was easy to
hand optimize swapping vtop[-1] and vtop[0] - instead of large (28 bytes
on i386) tmp variable and two memory to memory copies, let's swap areas
by longs through registers with streamlined assembly.

For

    $ ./tcc -B. -bench -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -c tcc.c

before:

 # Overhead      Command        Shared Object                                          Symbol
 # ........  ...........  ...................  ..............................................
 #
     15.19%          tcc  tcc                  [.] next_nomacro1
      5.19%          tcc  libc-2.13.so         [.] _int_malloc
      4.57%          tcc  tcc                  [.] next
      3.36%          tcc  tcc                  [.] tok_str_add2
      3.03%          tcc  tcc                  [.] macro_subst_tok
      2.93%          tcc  tcc                  [.] macro_subst
      2.53%          tcc  tcc                  [.] next_nomacro_spc
      2.49%          tcc  tcc                  [.] vswap
      2.36%          tcc  libc-2.13.so         [.] _int_free

       │    ST_FUNC void vswap(void)
       │    {
  1,96 │      push   %edi
  2,65 │      push   %esi
  1,08 │      sub    $0x20,%esp
       │        SValue tmp;
       │
       │        /* cannot let cpu flags if other instruction are generated. Also
       │           avoid leaving VT_JMP anywhere except on the top of the stack
       │           because it would complicate the code generator. */
       │        if (vtop >= vstack) {
  0,98 │      mov    0x8078cac,%eax
       │      cmp    $0x8078d3c,%eax
  1,18 │   ┌──jb     24
       │   │        int v = vtop->r & VT_VALMASK;
  1,08 │   │  mov    0x8(%eax),%edx
  0,78 │   │  and    $0x3f,%edx
       │   │        if (v == VT_CMP || (v & ~1) == VT_JMP)
  0,78 │   │  cmp    $0x33,%edx
  0,69 │   │↓ je     54
  0,59 │   │  and    $0xfffffffe,%edx
  0,49 │   │  cmp    $0x34,%edx
  0,29 │   │↓ je     54
       │   │            gv(RC_INT);
       │   │    }
       │   │    tmp = vtop[0];
  1,08 │24:└─→lea    0x4(%esp),%edi
  0,39 │      mov    $0x7,%ecx
       │      mov    %eax,%esi
 14,41 │      rep    movsl %ds:(%esi),%es:(%edi)
       │        vtop[0] = vtop[-1];
  9,51 │      lea    -0x1c(%eax),%esi
  1,96 │      mov    $0x7,%cl
       │      mov    %eax,%edi
 17,06 │      rep    movsl %ds:(%esi),%es:(%edi)
       │        vtop[-1] = tmp;
 10,20 │      mov    0x8078cac,%edi
  2,35 │      sub    $0x1c,%edi
  0,78 │      lea    0x4(%esp),%esi
       │      mov    $0x7,%cl
 15,20 │      rep    movsl %ds:(%esi),%es:(%edi)
       │    }
  9,90 │      add    $0x20,%esp
  2,25 │      pop    %esi
  1,67 │      pop    %edi
  0,69 │      ret

after:

 # Overhead      Command        Shared Object                                          Symbol
 # ........  ...........  ...................  ..............................................
 #
     15.27%          tcc  tcc                  [.] next_nomacro1
      5.08%          tcc  libc-2.13.so         [.] _int_malloc
      4.57%          tcc  tcc                  [.] next
      3.17%          tcc  tcc                  [.] tok_str_add2
      3.12%          tcc  tcc                  [.] macro_subst
      2.99%          tcc  tcc                  [.] macro_subst_tok
      2.43%          tcc  tcc                  [.] next_nomacro_spc
      2.32%          tcc  libc-2.13.so         [.] _int_free

      . . .

      0.71%          tcc  tcc                  [.] vswap

       │    ST_FUNC void vswap(void)
       │    {
  7,22 │      push   %eax
       │        /* cannot let cpu flags if other instruction are generated. Also
       │           avoid leaving VT_JMP anywhere except on the top of the stack
       │           because it would complicate the code generator. */
       │        if (vtop >= vstack) {
 11,34 │      mov    0x8078cac,%eax
  2,75 │      cmp    $0x8078d3c,%eax
  0,34 │   ┌──jb     20
       │   │        int v = vtop->r & VT_VALMASK;
  0,34 │   │  mov    0x8(%eax),%edx
  8,93 │   │  and    $0x3f,%edx
       │   │        if (v == VT_CMP || (v & ~1) == VT_JMP)
  2,06 │   │  cmp    $0x33,%edx
  2,41 │   │↓ je     74
  2,41 │   │  and    $0xfffffffe,%edx
  0,34 │   │  cmp    $0x34,%edx
  2,41 │   │↓ je     74
       │   │        vtopl[-1*VSIZEL + i] = tmpl;    \
       │   │      } do {} while (0)
       │   │
       │   │    VSWAPL(15); VSWAPL(14); VSWAPL(13); VSWAPL(12);
       │   │    VSWAPL(11); VSWAPL(10); VSWAPL( 9); VSWAPL( 8);
       │   │    VSWAPL( 7); VSWAPL( 6); VSWAPL( 5); VSWAPL( 4);
  2,06 │20:└─→mov    0x18(%eax),%edx
  1,37 │      mov    -0x4(%eax),%ecx
  2,06 │      mov    %ecx,0x18(%eax)
  1,37 │      mov    %edx,-0x4(%eax)
  2,06 │      mov    0x14(%eax),%edx
  2,06 │      mov    -0x8(%eax),%ecx
  2,41 │      mov    %ecx,0x14(%eax)
  3,09 │      mov    %edx,-0x8(%eax)
  3,09 │      mov    0x10(%eax),%edx
  1,72 │      mov    -0xc(%eax),%ecx
  2,75 │      mov    %ecx,0x10(%eax)
  1,72 │      mov    %edx,-0xc(%eax)
       │        VSWAPL( 3); VSWAPL( 2); VSWAPL( 1); VSWAPL( 0);
  2,41 │      mov    0xc(%eax),%edx
  2,41 │      mov    -0x10(%eax),%ecx
  2,41 │      mov    %ecx,0xc(%eax)
  0,69 │      mov    %edx,-0x10(%eax)
  1,72 │      mov    0x8(%eax),%edx
  0,69 │      mov    -0x14(%eax),%ecx
  1,03 │      mov    %ecx,0x8(%eax)
  1,37 │      mov    %edx,-0x14(%eax)
  1,37 │      mov    0x4(%eax),%edx
  0,69 │      mov    -0x18(%eax),%ecx
  3,09 │      mov    %ecx,0x4(%eax)
  2,06 │      mov    %edx,-0x18(%eax)
  1,37 │      mov    (%eax),%edx
  2,41 │      mov    -0x1c(%eax),%ecx
  1,37 │      mov    %ecx,(%eax)
  4,12 │      mov    %edx,-0x1c(%eax)
       │        }
       │
       │    #   undef VSWAPL
       │    #   undef VSIZEL
       │    }
  1,03 │      pop    %eax
  3,44 │      ret

Overal speedup:

    # best of 5 runs
    before: 8268 idents, 47203 lines, 1526763 bytes, 0.148 s, 319217 lines/s, 10.3 MB/s
    after:  8273 idents, 47231 lines, 1527685 bytes, 0.146 s, 324092 lines/s, 10.5 MB/s

Static ASSERT macro taken from CCAN's[1] build_assert[2] which is in
public domain.

[1] http://ccodearchive.net/
[2] http://git.ozlabs.org/?p=ccan;a=blob;f=ccan/build_assert/build_assert.h;h=24e59c44cd930173178ac9b6e101b0af64a879e9;hb=HEAD
2012-12-21 20:46:26 +04:00
Kirill Smelkov 43a11a7ed1 Make tcc work after self-compiling with bounds-check enabled
For vstack Fabrice used the trick to initialize vtop to &vstack[-1], so
that on first push, vtop becomes &vstack[0] and a value is also stored
there - everything works.

Except that when tcc is compiled with bounds-checking enabled, vstack - 1
returns INVALID_POINTER and oops...

Let's workaround it with artificial 1 vstack slot which will not be
used, but only serve as an indicator that pointing to &vstack[-1] is ok.

Now, tcc, after being self-compiled with -b works:

    $ ./tcc -B. -o tccb  -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" tcc.c  -ldl
    $ cd tests
    $ ../tcc -B.. -run tcctest.c >1
    $ ../tccb -B.. -run tcctest.c >2
    $ diff -u 1 2

and note, tcc's compilation speed is not affected:

    $ ./tcc -B. -bench -DONE_SOURCE -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\" -c tcc.c

    before: 8270 idents, 47221 lines, 1527730 bytes, 0.152 s, 309800 lines/s, 10.0 MB/s
    after:  8271 idents, 47221 lines, 1527733 bytes, 0.152 s, 310107 lines/s, 10.0 MB/s

But note, that `tcc -b -run tcc` is still broken - for example it crashes
on
    $ cat x.c
    double get100 () { return 100.0; }

    $ ./tcc -B. -b -DTCC_TARGET_I386 -DCONFIG_MULTIARCHDIR=\"i386-linux-gnu\"  -run   \
        -DONE_SOURCE ./tcc.c -B. -c x.c
    Runtime error: dereferencing invalid pointer
    ./tccpp.c:1953: at 0xa7beebdf parse_number() (included from ./libtcc.c, ./tcc.c)
    ./tccpp.c:3003: by 0xa7bf0708 next() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4465: by 0xa7bfe348 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:4440: by 0xa7bfe212 block() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5529: by 0xa7c01929 gen_function() (included from ./libtcc.c, ./tcc.c)
    ./tccgen.c:5767: by 0xa7c02602 decl0() (included from ./libtcc.c, ./tcc.c)

that's because lib/bcheck.c runtime needs more fixes -- see next
patches.
2012-12-09 18:06:09 +04:00
Kirill Smelkov b2a02961b4 Add support for __builtin_frame_address(level)
Continuing d6072d37 (Add __builtin_frame_address(0)) implement
__builtin_frame_address for levels greater than zero, in order for
tinycc to be able to compile its own lib/bcheck.c after
cffb7af9 (lib/bcheck: Prevent __bound_local_new / __bound_local_delete
from being miscompiled).

I'm new to the internals, and used the most simple way to do it.
Generated code is not very good for levels >= 2, compare

                gcc                         tcc

    level=0     mov    %ebp,%eax            lea    0x0(%ebp),%eax

    level=1     mov    0x0(%ebp),%eax       mov    0x0(%ebp),%eax

    level=2     mov    0x0(%ebp),%eax       mov    0x0(%ebp),%eax
                mov    (%eax),%eax          mov    %eax,-0x10(%ebp)
                                            mov    -0x10(%ebp),%eax
                                            mov    (%eax),%eax

    level=3     mov    0x0(%ebp),%eax       mov    0x0(%ebp),%eax
                mov    (%eax),%eax          mov    (%eax),%ecx
                mov    (%eax),%eax          mov    (%ecx),%eax

But this is still an improvement and for bcheck we need level=1 for
which the code is good.

For the tests I had to force gcc use -O0 to not inline the functions.
And -fno-omit-frame-pointer just in case.

If someone knows how to improve the generated code - help is
appreciated.

Thanks,
Kirill

Cc: Michael Matz <matz@suse.de>
Cc: Shinichiro Hamaji <shinichiro.hamaji@gmail.com>
2012-11-16 10:22:14 +04:00
Hitoshi Mitake 5eb64357b1 forbid invalid comparison of struct
Current tcc permits comparison of structs and comparison between
struct and other typed values.
2012-11-05 22:34:43 +09:00
Thomas Preud'homme 508df168f4 Fix commit 85f6fad3a6
Don't reset nocode_wanted with saved_nocode_wanted if it hasn't been
modified (and hence saved_nocode_wanted is uninitialized).
2012-10-25 20:14:55 +02:00
Thomas Preud'homme cf95ac399c Error out in case of variable name clash
Error out when two local variable with same name are defined in the same
scope. This fixes bug #15597 in savannah's BTS.
2012-10-25 19:40:50 +02:00
Thomas Preud'homme 85f6fad3a6 Forbid VLA as static variables
Currently, VLA are not forbidden for static variable. This leads to
problems even if for fixed-size array when the size expression uses the
ternary operator (cond ? then-value : else-value) because it is parsed
as a general expression which leads to code generated in this case.

This commit solve the problem by forbidding VLA for static variables.
Although not required for the fix, avoiding code generation when the
expression is constant would be a nice addition though.
2012-10-25 18:07:13 +02:00
Thomas Preud'homme d1694f7d7e get_reg(): try to free r2 for an SValue first
To be able to load a long long value correctly on i386, gv() rely on the
fact that when get_reg() look at an SValue it tries first to free the
register in r2 and then r. More information about the context can be
found at
http://lists.nongnu.org/archive/html/tinycc-devel/2012-06/msg00017.html
and later at
http://lists.nongnu.org/archive/html/tinycc-devel/2012-07/msg00021.html
2012-07-11 23:39:05 +02:00
Vincent Lefevre d27a0b3548 Incorrect shift result type on unsigned short first argument.
The code for shifts is now similar to code for binary arithmetic operations,
except that only the first argument is considered, as required by the ISO C
standard.
2012-07-06 14:22:37 +02:00
Vincent Lefevre 240064c03b Incorrect shift result type with 64-bit ABI
On 2012-06-26 15:07:57 +0200, Vincent Lefevre wrote:
> ISO C99 TC3 says: [6.5.7#3] "The integer promotions are performed on
> each of the operands. The type of the result is that of the promoted
> left operand."

I've written a patch (attached). Now the shift problems no longer
occur with the testcase and with GNU MPFR's "make check".

--
Vincent Lefèvre <vincent@vinc17.net> - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)
2012-06-27 08:23:52 -04:00
Thomas Preud'homme 7f6095bfec Add support for arm hardfloat calling convention
See Procedure Call Standard for the ARM Architecture (AAPCS) for more
details.
2012-06-05 23:09:55 +02:00
Thomas Preud'homme bfb00494eb Fix removal of vnrott
Make vrotb ST_FUNC so that arm-gen.c can use vrotb.
2012-06-05 23:09:55 +02:00
Michael Matz 9ca9c82ff8 Fix comparing comparisons
Sometimes the result of a comparison is not directly used in a jump,
but in arithmetic or further comparisons.  If those further things
do a vswap() with the VT_CMP as current top, and then generate
instructions for the new top, this most probably destroys the flags
(e.g. if it's a bitfield load like in the example).

vswap() must do the same like vsetc() and not allow VT_CMP vtops
to be moved down.
2012-04-18 20:57:14 +02:00
Michael Matz 718fd591fa Make sizeof() be of type size_t
This matters when sizeof is directly used in arithmetic,
ala "uintptr_t t; t &= -sizeof(long)" (for alignment).  When sizeof
isn't size_t (as it's specified to be) this masking will truncate
the high bits of the uintptr_t object (if uintptr_t is larger than
uint).
2012-04-18 20:57:14 +02:00
Michael Matz 15f4ac2b1a Fix detection of labels with a typedef name
This needs to be accepted:
  typedef int foo;
  void f (void) { foo: return; }
namespaces for labels and types are different.  The problem is that
the block parser always tries to find a decl first and that routine
doesn't peek enough to detect this case.  Needs some adjustments
to unget_tok() so that we can call it even when we already called
it once, but next() didn't come around restoring the buffer yet.
(It lazily does so not when the buffer becomes empty, but rather
when the next call detects that the buffer is empty, i.e. it requires
two next() calls until the unget buffer gets switched back).
2012-04-18 20:57:13 +02:00
Michael Matz 5c0a2366a3 Fix bitfield loads into char/short.
Removes a premature optimization of char/short loads
rewriting the source type.  It did so also for bitfield
loads, thereby removing all the shifts/maskings.
2012-04-18 20:57:13 +02:00
Michael Matz 6471ec0a2b Fix conversion in a?0:ptr.
(cond ? 0 : ptr)->member wasn't handled correctly.  If one arm
is a null pointer constant (which also can be a pointer) the result
type is that of the other arm.
2012-04-18 20:57:13 +02:00
Thomas Preud'homme 53c5715cca Remove vnrott (duplicate vrotb) 2012-03-14 15:39:16 +01:00
Thomas Preud'homme 3ab269c56a Error out when assigning void value.
tcc should now error out when compiling code like:

VOID ExitProcess(UINT uExitCode);
(…)
retCode = ExitProcess(pi.dwProcessId);
2012-01-22 21:18:38 +01:00
grischka bf374a5f23 rename error/warning -> tcc_(error/warning) 2011-08-11 17:07:56 +02:00
grischka f115c12346 x86-64: fix flags and zero-pad long doubles
This fixes a bug introduced in commit
    8d107d9ffd
that produced wrong code because of interference between
0x10 bits VT_CONST and x86_64-gen.c:TREG_MEM

Also fully zero-pad long doubles on x86-64 to avoid random
bytes in output files which disturb file comparison.
2011-08-06 16:11:56 +02:00
grischka df9cce24a8 Accept colon separated paths with -L and -I
This allows passing colon separated paths to
  tcc_add_library_path
  tcc_add_sysinclude_path
  tcc_add_include_path

Also there are new configure variables
  CONFIG_TCC_LIBPATH
  CONFIG_TCC_SYSINCLUDE_PATHS
which define the lib/sysinclude paths all in one and can
be overridden from configure/make

For TCC_TARGET_PE semicolons (;) are used as separators

Also, \b in the path string is replaced by s->tcc_lib_path
(CONFIG_TCCDIR rsp. -B option)
2011-08-01 01:10:36 +02:00
Thomas Preud'homme 626a907451 Revert "Force const. expr. in expr_cond outside function"
This reverts commit b2f5ee9b2d as it's
useless on mob.
2011-07-31 17:18:19 +02:00
Thomas Preud'homme b2f5ee9b2d Force const. expr. in expr_cond outside function
Since no code should be generated outside a function, force expr_cond to
only consider constant expression when outside a function since the
generic code can generate some code.
2011-07-31 00:19:13 +02:00
Joe Soroka 9b52e16a50 re-added negative-array-size testcase and fixed fix for it 2011-07-22 02:09:28 -07:00
grischka d7d8458888 Revert "better constant handling for expr_cond"
It produced wrong code with one of my test projects.
This reverts commit cd3d1a45f3.
2011-07-16 15:53:30 +02:00
grischka 8d107d9ffd win64: va_arg with structures 2011-07-14 19:24:53 +02:00
grischka 232650f8b3 tccgen: reset aligned attribute for next type
Basically, with:
    typedef __attribute__((aligned(16))) struct _xyz {
         ...
    } xyz, *pxyz;

we want the struct aligned but not the pointer.

FIXME: This patch is a hack, waiting for someone in the knowledge
of correct __attribute__ semantics.
2011-07-14 19:00:46 +02:00
Joe Soroka c71798c376 handle arrays with a flexible member but no initializer 2011-07-11 00:18:36 -07:00
Joe Soroka cd3d1a45f3 better constant handling for expr_cond 2011-07-11 00:00:47 -07:00
Thomas Preud'homme ee06ef9dd3 Remove unused variables
Remove unused local variables and declare them conditionally when they
are used only on some architectures.
2011-05-16 14:15:32 +02:00
Joe Soroka 2b7a8eb8f5 use of TOK_alloca breaks cross compiler build
VLA inserts a call to alloca via enum TOK_alloca, but TOK_alloca
only exists on I386 and X86_64 targets.  This patch just emits an
error at compile-time if someone tries to compile some VLA code
for a TOK_alloca-less target. The best solution might be to just
push the problem to link-time, since the existence-or-not of a
alloca implementation can only be determined by linking.  It seems
like just declaring TOK_alloca unconditionally would achieve that,
but for now, this at least gets the cross compilers to build.
2011-04-12 00:17:08 -07:00
Joe Soroka 812781cd11 simplify/rollback VLA pointer subtraction
I don't know if it makes a difference to gen_op(TOK_PDIV) or not,
but logically the ptr1_is_vla test in TP's VLA patch seems out of
order, where the patch to fix it would be:
------------------------------------------------------------------
@@ -1581,15 +1581,15 @@ ST_FUNC void gen_op(int op)
                 u = pointed_size(&vtop[-1].type);
             }
             gen_opic(op);
+            if (ptr1_is_vla)
+                vswap();
             /* set to integer type */
 #ifdef TCC_TARGET_X86_64
             vtop->type.t = VT_LLONG;
 #else
             vtop->type.t = VT_INT;
 #endif
-            if (ptr1_is_vla)
-                vswap();
-            else
+            if (!ptr1_is_vla)
                 vpushi(u);
             gen_op(TOK_PDIV);
         } else {
------------------------------------------------------------------

Instead of that patch, which increases the complexity of the code,
this one fixes the problem by just rolling back and retrying with
a simpler approach.
2011-04-11 23:39:27 -07:00
Joe Soroka 1b8c094f39 remove no-longer-necessary naive fix for vla vstack leak 2011-04-09 23:04:01 -07:00
Joe Soroka c85f77de70 prevent internal segfault on apparent VLA at file scope 2011-04-09 22:59:35 -07:00
Joe Soroka 1446b543ae VLA fix [3/3]: store VLA sizeofs in anonymous runtime stack vars 2011-04-09 22:52:25 -07:00
Joe Soroka 7c7ca3c6aa VLA fix [2/3]: removed VT_ARRAY from VT_VLA types
A VLA is not really an array, it's a pointer-to-an-array.
Making this explicit allows us to back out a few parts
of the original VLA patch and paves the way for the next
part of the fix, where a VLA will be stored on the runtime
stack as a pointer-to-an-array, rather than on the compile-
time stack as a Sym*.
2011-04-08 01:09:39 -07:00
Joe Soroka 174d61a56e move a comment to its correct location 2011-04-08 00:46:32 -07:00
Joe Soroka b714af0405 add naive workaround for VLA vstack leak 2011-04-08 00:44:01 -07:00
Joe Soroka c94f80502e VLA bcheck works via bound alloca; add test, remove warning 2011-04-06 15:27:45 -07:00
Joe Soroka 810aca9e68 clarify post_type() VT_STORAGE handling by moving it out 2011-04-06 12:08:50 -07:00
Joe Soroka ace0f7f259 re-apply VLA by Thomas Preud'homme 2011-04-06 09:17:03 -07:00
Joe Soroka 17571298f3 handle c99 flexible array members less hackily 2011-03-18 17:50:42 -07:00
Joe Soroka 06a7c415a9 revert complicated & broken flexible array member handling 2011-03-18 17:47:35 -07:00