Bug 29970 - mixing ({...}) with VLA leads to massive breakage
Summary: mixing ({...}) with VLA leads to massive breakage
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL: https://gcc.gnu.org/pipermail/gcc-pat...
Keywords: ice-on-valid-code, patch, stmt-expr, wrong-code
: 99736 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-11-24 12:35 UTC by Al Viro
Modified: 2024-01-26 01:01 UTC (History)
9 users (show)

See Also:
Host: x86_64-unknown-linux-gnu
Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu
Known to work:
Known to fail: 4.3.2, 4.6.0, 5.3.0, 6.3.0, 7.0
Last reconfirmed: 2017-02-24 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Al Viro 2006-11-24 12:35:50 UTC
testcase 1:
int foo(int n)  // should not ICE
{
        return ({struct {int x[n];} x; x.x[12] = 1; x;}).x[12];
}
internal compiler error: in force_constant_size, at gimplify.c:708
testcase 2:
int foo(void)   // should not ICE
{
        return sizeof({int n = 20; struct {int x[n];} x; x.x[12] = 1; x;});
}
internal compiler error: in gimplify_var_or_parm_decl, at gimplify.c:1664
testcase 3:
int foo(void)   // should not return 0
{
        int n = 0;
        return sizeof({n = 10; struct {int x[n];} x; x;});
}
returns 0 (actually it's sizeof(int)*original value of n)
testcase 4:
int foo(void)   // should not ICE
{
        return (*({
                        int n = 20;
                        char (*x)[n][n] = malloc(n * n);
                        (*x)[12][1] = 1;
                        x;
                }))[12][1];
}
same ICE as in #2; note that here the only gccism in ({...})
testcase 5:
int foo(void)   // should return 1, returns 0
{
        int n = 0;
        return (*({
                        n = 20;
                        char (*x)[n][n] = malloc(n * n);
                        (*x)[12][1] = 1;
                        (*x)[0][1] = 0;
                        x;
                }))[12][1];
}
all writes go to the value-of-malloc + 1

Have fun...  A sane approach would be to require the type of
({...}) to make sense on the outside.  AFAICS, the root cause
of that crap is that ({...}) allows leaking types out of scope
where they are defined...

In any case, ICE even on violated constraints is Not Nice(tm),
especially when those constraints are never stated.  Note that
earlier versions (at least 4.0.2 and 4.1.1) also break on the
same testcases, so it's not a result of recent change - just a dark
corner that hadn't been thought through when designing semantics of
({...}).
Comment 1 jsm-csl@polyomino.org.uk 2006-11-24 13:56:46 UTC
Subject: Re:   New: mixing ({...}) with VLA leads to massive
 breakage

This looks much the same as bug 27301, though the additional testcases are 
useful.

Comment 2 Al Viro 2006-11-24 15:25:14 UTC
27301 looks similar to what the first one trips, but passing pointers
as suggested by #3 there is not a panacea - testcases 4 and 5
actually deal with that variant.  It really looks as if part (but not
all) information about the type dies when we leave the scope and
we end up stepping into that when working with object afterwards.
Comment 3 Andrew Pinski 2006-11-25 01:55:16 UTC
testcase 2 and 3 are a front-end issue as far as I can tell:
in .orginal:
    int n = 0;  // not there for 2 which causes the ICE
  return (int) ((long unsigned int) SAVE_EXPR <n> * 4);
Comment 4 Martin Sebor 2017-02-24 04:05:18 UTC
Confirmed with today's top of trunk (7.0).  It might be worthwhile to break up the test cases into individual bugs.

$ (set -x && cat t.c && for n in 1 2 3 4 5; do gcc -DTEST=$n -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout t.c; done)
+ cat t.c
#if TEST == 1
int foo(int n)  // should not ICE
{
        return ({struct {int x[n];} x; x.x[12] = 1; x;}).x[12];
}
#elif TEST == 2
int foo(void)   // should not ICE
{
        return sizeof({int n = 20; struct {int x[n];} x; x.x[12] = 1; x;});
}
#elif TEST == 3
int foo(void)   // should not return 0
{
        int n = 0;
        return sizeof({n = 10; struct {int x[n];} x; x;});
}
#elif TEST == 4
int foo(void)   // should not ICE
{
        return (*({
                        int n = 20;
                        char (*x)[n][n] = __builtin_malloc(n * n);
                        (*x)[12][1] = 1;
                        x;
                }))[12][1];
}
#elif TEST == 5
int foo(void)   // should return 1, returns 0
{
        int n = 0;
        return (*({
                        n = 20;
                        char (*x)[n][n] = __builtin_malloc(n * n);
                        (*x)[12][1] = 1;
                        (*x)[0][1] = 0;
                        x;
                }))[12][1];
}
#endif
+ for n in 1 2 3 4 5
+ gcc -DTEST=1 -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout t.c
t.c: In function ‘foo’:
t.c:4:30: warning: a member of a structure or union cannot have a variably modified type [-Wpedantic]
         return ({struct {int x[n];} x; x.x[12] = 1; x;}).x[12];
                              ^
t.c:4:16: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
         return ({struct {int x[n];} x; x.x[12] = 1; x;}).x[12];
                ^

;; Function foo (foo, funcdef_no=0, decl_uid=1795, cgraph_uid=0, symbol_order=0)

foo (int n)
{
  struct 
  {
    int x[0:D.1807];
  } * x.1;
  struct 
  {
    int x[0:D.1807];
  } * D.1814;
  sizetype _1;
  sizetype _2;
  int _16;

  <bb 2> [100.00%]:
  _1 = (sizetype) n_3(D);
  _2 = _1 * 4;
  _8 = __builtin_alloca_with_align (_2, 32);
  x.1_12 = __builtin_alloca_with_align (_2, 32);
  x.1_12->x[12] = 1;
  __builtin_memcpy (_8, x.1_12, _2);
  _16 = _8->x[12];
  return _16;

}


+ for n in 1 2 3 4 5
+ gcc -DTEST=2 -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout t.c
t.c: In function ‘foo’:
t.c:9:48: warning: a member of a structure or union cannot have a variably modified type [-Wpedantic]
         return sizeof({int n = 20; struct {int x[n];} x; x.x[12] = 1; x;});
                                                ^
t.c:9:22: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
         return sizeof({int n = 20; struct {int x[n];} x; x.x[12] = 1; x;});
                      ^
t.c:9:22: internal compiler error: in gimplify_var_or_parm_decl, at gimplify.c:2582
         return sizeof({int n = 20; struct {int x[n];} x; x.x[12] = 1; x;});
                ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0xb93ec7 gimplify_var_or_parm_decl
	/ssd/src/gcc/git-svn/gcc/gimplify.c:2582
0xbba91b gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11635
0xb8d9ba internal_get_tmp_var
	/ssd/src/gcc/git-svn/gcc/gimplify.c:567
0xb8dd96 get_initialized_tmp_var(tree_node*, gimple**, gimple**, bool)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:620
0xb9f95c gimplify_save_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:5762
0xbb9e44 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11490
0xbb934d gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11294
0xbbb651 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11921
0xbb934d gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11294
0xb9e1dd gimplify_modify_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:5457
0xbb8c6d gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11192
0xba23ca gimplify_stmt(tree_node**, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:6478
0xb8d545 gimplify_and_add(tree_node*, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:435
0xb907ab gimplify_return_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:1521
0xbb9c95 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11451
0xba23ca gimplify_stmt(tree_node**, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:6478
0xb8fbd2 gimplify_bind_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:1290
0xbb9938 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11391
0xba23ca gimplify_stmt(tree_node**, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:6478
0xbbcf89 gimplify_body(tree_node*, bool)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:12388
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
+ for n in 1 2 3 4 5
+ gcc -DTEST=3 -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout t.c
t.c: In function ‘foo’:
t.c:15:44: warning: a member of a structure or union cannot have a variably modified type [-Wpedantic]
         return sizeof({n = 10; struct {int x[n];} x; x;});
                                            ^
t.c:15:22: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
         return sizeof({n = 10; struct {int x[n];} x; x;});
                      ^

;; Function foo (foo, funcdef_no=0, decl_uid=1795, cgraph_uid=0, symbol_order=0)

foo ()
{
  <bb 2> [100.00%]:
  return 0;

}


+ for n in 1 2 3 4 5
+ gcc -DTEST=4 -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout t.c
t.c: In function ‘foo’:
t.c:20:18: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
         return (*({
                  ^
t.c:25:24: internal compiler error: in gimplify_var_or_parm_decl, at gimplify.c:2582
         return (*({
                ~~~~     
                         int n = 20;
                         ~~~~~~~~~~~
                         char (*x)[n][n] = __builtin_malloc(n * n);
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                         (*x)[12][1] = 1;
                         ~~~~~~~~~~~~~~~~
                         x;
                         ~~
                 }))[12][1];
                 ~~~~~~~^~~
0xb93ec7 gimplify_var_or_parm_decl
	/ssd/src/gcc/git-svn/gcc/gimplify.c:2582
0xbba91b gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11635
0xb8d9ba internal_get_tmp_var
	/ssd/src/gcc/git-svn/gcc/gimplify.c:567
0xb8dd96 get_initialized_tmp_var(tree_node*, gimple**, gimple**, bool)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:620
0xb9f95c gimplify_save_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:5762
0xbb9e44 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11490
0xbb934d gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11294
0xb9484f gimplify_compound_lval
	/ssd/src/gcc/git-svn/gcc/gimplify.c:2799
0xbb8ad1 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11144
0xbb934d gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11294
0xb9e1dd gimplify_modify_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:5457
0xbb8c6d gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11192
0xba23ca gimplify_stmt(tree_node**, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:6478
0xb8d545 gimplify_and_add(tree_node*, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:435
0xb907ab gimplify_return_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:1521
0xbb9c95 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11451
0xba23ca gimplify_stmt(tree_node**, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:6478
0xb8fbd2 gimplify_bind_expr
	/ssd/src/gcc/git-svn/gcc/gimplify.c:1290
0xbb9938 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:11391
0xba23ca gimplify_stmt(tree_node**, gimple**)
	/ssd/src/gcc/git-svn/gcc/gimplify.c:6478
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
+ for n in 1 2 3 4 5
+ gcc -DTEST=5 -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout t.c
t.c: In function ‘foo’:
t.c:31:18: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
         return (*({
                  ^

;; Function foo (foo, funcdef_no=0, decl_uid=1795, cgraph_uid=0, symbol_order=0)

foo ()
{
  <bb 2> [100.00%]:
  return 0;

}
Comment 5 Eric Gallager 2017-07-31 17:52:20 UTC
Related due to also mixing ({...}) with VLA: bug 30552. (Can stay separate since they're different testcases though)
Comment 6 Andrew Pinski 2021-03-23 19:33:22 UTC
*** Bug 99736 has been marked as a duplicate of this bug. ***
Comment 7 Tuna Gül 2021-03-23 19:45:01 UTC
I guess i can post a workaround here

This code doesnt compile:
"""
int main() {
	({
		unsigned int len = 10;
		struct {
			int array[len];
		} new_object;
		new_object;
	});
}
"""

But this does:

"""
unsigned int foo(unsigned int rv) { return rv; }

int main() {
	({
		unsigned int len = 10;
		struct {
			int array[foo(len)];
		} new_object;
		new_object;
	});
}
"""
Comment 8 Martin Uecker 2021-08-03 18:12:59 UTC
So according to my amateurish analysis, there seem to be at least three underlying issues:

- gimplify_compound_lval size expressions are gimplified too early. This
patch attempts to address this:

https://gcc.gnu.org/pipermail/gcc-patches/2021-August/576484.html

- inside sizeof, this seems to be a FE problem as the information from the statement expression is lost.

- and then there is another issue, when a variably-sized object (but not a pointer to it) is returned from the statement expression
Comment 9 Martin Uecker 2021-08-05 18:25:50 UTC
The sizeof problem is that in c_expr_sizeof_expr the argument of sizeof is only evaluated for VLAs but not for structs of variable size. The information about the size is then lost. Changing this fixes some more cases.

A third problem seems to be that in gimplify_target_expr the size expressions are also gimplified to early. Fixing this also seems to fix some of the cases, but then triggers some other down stream problems...
Comment 10 GCC Commits 2021-08-10 05:50:22 UTC
The master branch has been updated by Martin Uecker <uecker@gcc.gnu.org>:

https://gcc.gnu.org/g:0631faf87a197145acd833249bf8f20a1c4aaabf

commit r12-2830-g0631faf87a197145acd833249bf8f20a1c4aaabf
Author: Martin Uecker <muecker@gwdg.de>
Date:   Tue Aug 10 07:42:51 2021 +0200

    Evaluate arguments of sizeof that are structs of variable size.
    
    Evaluate arguments of sizeof for all types of variable size
    and not just for VLAs. This fixes some issues related to
    [PR29970] where statement expressions need to be evaluated
    so that the size is well defined.
    
    2021-08-10  Martin Uecker  <muecker@gwdg.de>
    
    gcc/c/
            PR c/29970
            * c-typeck.c (c_expr_sizeof_expr): Evaluate
            size expressions for structs of variable size.
    
    gcc/testsuite/
            PR c/29970
            * gcc.dg/vla-stexp-1.c: New test.
Comment 11 GCC Commits 2021-08-12 18:37:32 UTC
The master branch has been updated by Martin Uecker <uecker@gcc.gnu.org>:

https://gcc.gnu.org/g:d2ba65ab6010f0d507bf5512a0223692e6653b23

commit r12-2882-gd2ba65ab6010f0d507bf5512a0223692e6653b23
Author: Martin Uecker <muecker@gwdg.de>
Date:   Thu Aug 12 20:32:16 2021 +0200

    Evaluate type arguments of sizeof that are structs of variable size [PR101838]
    
    Evaluate type arguments of sizeof for all types of variable size
    and not just for VLAs. This fixes PR101838 and some issues related
    to PR29970 where statement expressions need to be evaluated so that
    the size is well defined.
    
    2021-08-12  Martin Uecker  <muecker@gwdg.de>
    
    gcc/c/
            PR c/101838
            PR c/29970
            * c-typeck.c (c_expr_sizeof_type): Evaluate
            size expressions for structs of variable size.
    
    gcc/testsuite/
            PR c/101838
            * gcc.dg/vla-stexp-2.c: New test.
Comment 12 Martin Uecker 2021-08-14 20:03:59 UTC
Another version of the patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-August/577402.html
Comment 13 Martin Uecker 2021-09-04 19:55:36 UTC
The remaining problem with constant index 0 for the patch mentioned above, appears to be related to fold_binary_loc which transforms (a + (x, 0)) to (x, a) which breaks if 'x' depends on something in 'a'.
Comment 14 Martin Uecker 2021-09-05 19:16:58 UTC
Another version of the patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-September/578844.html
Comment 15 Martin Uecker 2021-11-07 11:57:42 UTC
Another version of the patch:

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/583593.html
Comment 16 GCC Commits 2021-11-17 13:30:16 UTC
The master branch has been updated by Martin Uecker <uecker@gcc.gnu.org>:

https://gcc.gnu.org/g:4e6bf0b9dd5585df1a1472d6a93b9fff72fe2524

commit r12-5338-g4e6bf0b9dd5585df1a1472d6a93b9fff72fe2524
Author: Martin Uecker <uecker@gcc.gnu.org>
Date:   Wed Nov 17 14:20:59 2021 +0100

    Fix ICE when mixing VLAs and statement expressions [PR91038]
    
    When returning VM-types from statement expressions, this can
    lead to an ICE when declarations from the statement expression
    are referred to later. Most of these issues can be addressed by
    gimplifying the base expression earlier in gimplify_compound_lval.
    Another issue is fixed by wrapping the pointer expression in
    pointer_int_sum. This fixes PR91038 and some of the test cases
    from PR29970 (structs with VLA members need further work).
    
    gcc/
            PR c/91038
            PR c/29970
            * gimplify.c (gimplify_var_or_parm_decl): Update comment.
            (gimplify_compound_lval): Gimplify base expression first.
            (gimplify_target_expr): Add comment.
    
    gcc/c-family/
            PR c/91038
            PR c/29970
            * c-common.c (pointer_int_sum): Make sure pointer expressions
            are evaluated first when the size expression depends on for
            variably-modified types.
    
    gcc/testsuite/
            PR c/91038
            PR c/29970
            * gcc.dg/vla-stexp-3.c: New test.
            * gcc.dg/vla-stexp-4.c: New test.
            * gcc.dg/vla-stexp-5.c: New test.
            * gcc.dg/vla-stexp-6.c: New test.
            * gcc.dg/vla-stexp-7.c: New test.
            * gcc.dg/vla-stexp-8.c: New test.
            * gcc.dg/vla-stexp-9.c: New test.
Comment 17 Eric Gallager 2023-05-31 02:20:57 UTC
(In reply to CVS Commits from comment #16)
> The master branch has been updated by Martin Uecker <uecker@gcc.gnu.org>:
> 
> https://gcc.gnu.org/g:4e6bf0b9dd5585df1a1472d6a93b9fff72fe2524
> 
> commit r12-5338-g4e6bf0b9dd5585df1a1472d6a93b9fff72fe2524
> Author: Martin Uecker <uecker@gcc.gnu.org>
> Date:   Wed Nov 17 14:20:59 2021 +0100
> 
>     Fix ICE when mixing VLAs and statement expressions [PR91038]
>     
>     When returning VM-types from statement expressions, this can
>     lead to an ICE when declarations from the statement expression
>     are referred to later. Most of these issues can be addressed by
>     gimplifying the base expression earlier in gimplify_compound_lval.
>     Another issue is fixed by wrapping the pointer expression in
>     pointer_int_sum. This fixes PR91038 and some of the test cases
>     from PR29970 (structs with VLA members need further work).
>     
>     gcc/
>             PR c/91038
>             PR c/29970
>             * gimplify.c (gimplify_var_or_parm_decl): Update comment.
>             (gimplify_compound_lval): Gimplify base expression first.
>             (gimplify_target_expr): Add comment.
>     
>     gcc/c-family/
>             PR c/91038
>             PR c/29970
>             * c-common.c (pointer_int_sum): Make sure pointer expressions
>             are evaluated first when the size expression depends on for
>             variably-modified types.
>     
>     gcc/testsuite/
>             PR c/91038
>             PR c/29970
>             * gcc.dg/vla-stexp-3.c: New test.
>             * gcc.dg/vla-stexp-4.c: New test.
>             * gcc.dg/vla-stexp-5.c: New test.
>             * gcc.dg/vla-stexp-6.c: New test.
>             * gcc.dg/vla-stexp-7.c: New test.
>             * gcc.dg/vla-stexp-8.c: New test.
>             * gcc.dg/vla-stexp-9.c: New test.

Is this fixed now, or is it staying open for backports?
Comment 18 Martin Uecker 2023-05-31 05:01:36 UTC
What is not fixed is returning structs with VLA members as in the first three test cases, e.g. the second one still ICEs.
Comment 19 Gabriel Ravier 2024-01-26 01:01:41 UTC
Can also confirm this myself as I've also encountered this ICE in this code:

#include <stdio.h>

#define each(item, array) \
(typeof(*(array)) *foreach_p = (array), *foreach_p2 = foreach_p, (item) = {}; \
foreach_p < &((foreach_p2)[sizeof(array)/sizeof(*array)]); \
++foreach_p)if((__builtin_memcpy(&(item), foreach_p, sizeof((item)))), 0){}else

#define range1(_stop) (({ \
	typeof(_stop) stop = _stop; \
	struct{typeof((stop)) array[stop];}p = {}; \
	if(stop < 0){ \
		for(size_t i = 0; i > stop; --i) \
			p.array[-i] = i; \
	}else{ \
		for(size_t i = 0; i < stop; ++i) \
			p.array[i] = i; \
	} \
	p; \
}).array)

int main(){
	char group[][4] = {
		"egg",
		"one",
		"two",
		"moo",
	};
	for each(x, group){
		puts(x);
	}
	return sizeof(range1(6));
}

which I was able to minify to:

void f()
{
  (void)({
    int x = 1;
    struct {
      int array[x];
    } p;
    p;
  });
}

which roughly matches what testcase 2 does.