{ dg-skip-if "No section attribute" { { hppa*-*-hpux* } && { ! lp64 } } }
{ dg-options "-Wall -ftrack-macro-expansion=0" }
{ dg-options "-Wall -Wno-narrowing -Wno-unused -ftrack-macro-expansion=0" { target c++ } }
- { dg-additional-options "-DSKIP_ALIAS" { target *-*-darwin* } }
+ { dg-additional-options "-DSKIP_ALIAS" { target *-*-darwin* } }
*/
#define ATTR(...) __attribute__ ((__VA_ARGS__))
A (0, gpak[0].c, packed);
A (0, gpak[1].s, packed);
A (1, gpak->a, packed);
- A (1, (*gpak).a[0], packed);
+ /* It's the array that's declared packed but not its elements. */
+ A (0, (*gpak).a[0], packed);
/* The following fails because in C it's represented as
INDIRECT_REF (POINTER_PLUS (NOP_EXPR (ADDR_EXPR (gpak)), ...))
A (0, p->c, packed);
A (0, p->s, packed);
A (1, p->a, packed);
- A (1, p->a[0], packed);
+ /* It's the array that's declared packed but not its elements. */
+ A (0, p->a[0], packed);
/* Similar to the comment above.
A (1, *p->a, packed); */
}
A (1, iv16, vector_size (16));
A (0, iv16, vector_size (32));
+ /* Verify that the attribute not detected on an array of vectors
+ but is detected on its elements. */
+ typedef ATTR (vector_size (8)) float afv8_t[4];
+ A (0, afv8_t, vector_size);
+ A (0, afv8_t, vector_size (1));
+ A (0, afv8_t, vector_size (2));
+ A (0, afv8_t, vector_size (4));
+ A (0, afv8_t, vector_size (8));
+ A (0, afv8_t, vector_size (16));
+
+ A (1, __typeof__ ((*(afv8_t*)0)[0]), vector_size);
+ A (0, __typeof__ ((*(afv8_t*)0)[1]), vector_size (1));
+ A (0, __typeof__ ((*(afv8_t*)0)[2]), vector_size (2));
+ A (0, __typeof__ ((*(afv8_t*)0)[3]), vector_size (4));
+ A (1, __typeof__ ((*(afv8_t*)0)[0]), vector_size (8));
+ A (0, __typeof__ ((*(afv8_t*)0)[1]), vector_size (16));
+
+ A (1, __typeof__ (**(afv8_t*)0), vector_size);
+ A (0, __typeof__ (**(afv8_t*)0), vector_size (1));
+ A (0, __typeof__ (**(afv8_t*)0), vector_size (2));
+ A (0, __typeof__ (**(afv8_t*)0), vector_size (4));
+ A (1, __typeof__ (**(afv8_t*)0), vector_size (8));
+ A (0, __typeof__ (**(afv8_t*)0), vector_size (16));
+
ATTR (vector_size (8)) float afv8[4];
- A (1, afv8, vector_size);
+ A (0, afv8, vector_size);
A (0, afv8, vector_size (1));
A (0, afv8, vector_size (2));
A (0, afv8, vector_size (4));
- A (1, afv8, vector_size (8));
+ A (0, afv8, vector_size (8));
A (0, afv8, vector_size (16));
+
+ A (1, afv8[0], vector_size);
+ A (0, afv8[1], vector_size (1));
+ A (0, afv8[2], vector_size (2));
+ A (0, afv8[3], vector_size (4));
+ A (1, afv8[0], vector_size (8));
+ A (0, afv8[1], vector_size (16));
+
+ A (1, *afv8, vector_size);
+ A (0, *afv8, vector_size (1));
+ A (0, *afv8, vector_size (2));
+ A (0, *afv8, vector_size (4));
+ A (1, *afv8, vector_size (8));
+ A (0, *afv8, vector_size (16));
+
+ /* sizeof (long double) is 12 on i386. */
+ enum { VecSize = 8 * sizeof (long double) };
+ ATTR (vector_size (VecSize)) long double aldv[1][2][3];
+ A (0, aldv, vector_size);
+ A (0, aldv[0], vector_size);
+ A (0, aldv[0][0], vector_size);
+ A (1, aldv[0][0][0], vector_size);
+ A (0, aldv[0][0][1], vector_size (VecSize / 2));
+ A (1, aldv[0][0][2], vector_size (VecSize));
+
+ A (0, aldv[0][0][0][0], vector_size);
+
+ A (0, *aldv, vector_size);
+ A (0, **aldv, vector_size);
+ A (1, ***aldv, vector_size);
+ A (1, ***aldv, vector_size (VecSize));
}
--- /dev/null
+/* PR c/88383 - ICE calling _builtin_has_attribute(r, aligned(N)))
+ on an overaligned reference r
+ PR c/89288 - ICE in tree_code_size, at tree.c:865
+ { dg-options "-Wall -ftrack-macro-expansion=0" }
+ { dg-options "-Wall -Wno-narrowing -Wno-unused -ftrack-macro-expansion=0" { target c++ } } */
+
+#define ATTR(...) __attribute__ ((__VA_ARGS__))
+
+#define A(expect, sym, attr) \
+ typedef int Assert [1 - 2 * !(__builtin_has_attribute (sym, attr) == expect)]
+
+typedef ATTR (aligned (8)) int Int8;
+
+/* The attribute applies to the array, not to the type of its elements. */
+extern ATTR (aligned (8)) char i8arr[];
+
+/* The attribute applies to the pointer, not to the type it points to. */
+extern ATTR (aligned (8)) int *ptr;
+extern Int8 *i8ptr;
+
+#if __cplusplus
+
+/* Similarly here, the attribute applies to the reference, not to its type. */
+extern ATTR (aligned (8)) int &ref;
+extern Int8 &i8ref;
+
+#else
+
+/* Fake references in C. */
+extern ATTR (aligned (8)) int ref;
+Int8 i8ref;
+
+#endif
+
+void test (void)
+{
+ /* Verify that the built-in detects the attribute on the array. */
+ A (1, i8arr, aligned);
+ A (0, i8arr, aligned (1));
+ A (0, i8arr, aligned (2));
+ A (0, i8arr, aligned (4));
+ A (1, i8arr, aligned (8));
+ A (0, i8arr, aligned (16));
+
+ A (0, i8arr + 1, aligned);
+ A (0, i8arr + 2, aligned (1));
+ A (0, i8arr + 3, aligned (8));
+
+ /* Verify the builtin detects the absence of the attribute on
+ the elements. */
+ A (0, i8arr[0], aligned);
+ A (0, *i8arr, aligned);
+
+ /* Verify that the built-in doesn't confuse the attribute on
+ the pointer type with that to the pointed to type. This
+ also exercises PR c/89288. */
+ A (0, (Int8*)0, aligned);
+ A (0, (int*)0, aligned);
+ A (0, (void*)0, aligned);
+ A (0, 0, aligned);
+
+ /* Verify that the built-in detects the attribute on the pointer
+ itself. */
+ A (1, ptr, aligned);
+ A (0, ptr, aligned (1));
+ A (0, ptr, aligned (2));
+ A (0, ptr, aligned (4));
+ A (1, ptr, aligned (8));
+ A (0, ptr, aligned (16));
+
+ A (0, ptr + 1, aligned);
+ A (0, ptr + 2, aligned (1));
+ A (0, ptr + 3, aligned (8));
+
+ /* The pointed to type is not declared with attribute aligned. */
+ A (0, *ptr, aligned);
+ A (0, *ptr, aligned (1));
+ A (0, *ptr, aligned (2));
+ A (0, *ptr, aligned (4));
+ A (0, *ptr, aligned (8));
+ A (0, *ptr, aligned (16));
+
+ A (0, *ptr + 1, aligned);
+ A (0, *ptr + 2, aligned (1));
+ A (0, *ptr + 3, aligned (8));
+
+ /* Verify that the built-in correctly detects the attribute on
+ the type of the lvalue referenced by the pointer. */
+ A (0, i8ptr, aligned);
+ A (0, i8ptr, aligned (8));
+ A (0, i8ptr + 1, aligned);
+ A (0, i8ptr + 3, aligned (8));
+ A (1, *i8ptr, aligned);
+ A (0, *i8ptr, aligned (1));
+ A (0, *i8ptr, aligned (2));
+ A (0, *i8ptr, aligned (4));
+ A (1, *i8ptr, aligned (8));
+ A (0, *i8ptr, aligned (16));
+
+ /* The reference itself is declared aligned, even though the type
+ it refers to isn't. But see PR c++/88362. */
+ A (1, ref, aligned);
+ A (0, ref, aligned (1));
+ A (0, ref, aligned (2));
+ A (0, ref, aligned (4));
+ A (1, ref, aligned (8));
+ A (0, ref, aligned (16));
+
+ /* Also verify that assignment expressions are accepted. */
+ A (0, ref = 1, aligned);
+ A (0, ref += 2, aligned (1));
+ A (0, ref /= 3, aligned (8));
+
+}
--- /dev/null
+/* Verify that __builtin_has_attribute detects attributes aligned
+ and packed in various forms of array dereferencing and indirection
+ expressions correspondingly to __alignof__.
+ { dg-do compile }
+ { dg-options "-Wall -Wno-unused -ftrack-macro-expansion=0" } */
+
+#define ATTR(...) __attribute__ ((__VA_ARGS__))
+#define ALIGN(N) ATTR (aligned (N))
+
+#define Assert(expr) typedef int _Assert [1 - 2 * !(expr)]
+
+/* Verify that __builtin_has_attribute (EXPR, align (ALIGN)) returns
+ the EXPECTed result. When EXPECT is true, verify that the EXPression
+ has the expected ALIGNment. */
+#define A3(expect, expr, align) do { \
+ Assert (!expect || __alignof__ (expr) == align); \
+ Assert (expect == __builtin_has_attribute (expr, aligned (align))); \
+ } while (0)
+
+#define A(expect, expr) \
+ Assert (expect == __builtin_has_attribute (expr, aligned)) \
+
+enum { PA = __alignof__ (void*) };
+
+/* Define pointer to pointer types, with different alignments
+ at each level of indirection. */
+typedef struct S8 { char a[8]; } S8;
+typedef ALIGN (8) S8 I8;
+typedef ALIGN (16) I8 *P16_I8;
+typedef P16_I8 *P_P16_I8;
+typedef ALIGN (32) P_P16_I8 *P32_P_P16_I8;
+typedef P32_P_P16_I8 *P_P32_P_P16_I8;
+typedef ALIGN (64) P_P32_P_P16_I8 *P64_P_P32_P_P16_I8;
+
+Assert ( 8 == __alignof__ (I8));
+Assert (16 == __alignof__ (P16_I8));
+Assert (PA == __alignof__ (P_P16_I8));
+Assert (32 == __alignof__ (P32_P_P16_I8));
+Assert (PA == __alignof__ (P_P32_P_P16_I8));
+Assert (64 == __alignof__ (P64_P_P32_P_P16_I8));
+
+
+/* Similar to the pointer of pointers above, define array of array
+ types, with different alignments at each level of indirection. */
+typedef struct S64 { char a[64]; } S64;
+typedef ALIGN (64) S64 I64;
+typedef ALIGN (32) I64 A32_I64[3];
+typedef A32_I64 A_A32_I64[5];
+typedef ALIGN (16) A_A32_I64 A16_A_A32_I64[7];
+typedef A16_A_A32_I64 A_A16_A_A32_I64[11];
+typedef ALIGN (8) A_A16_A_A32_I64 A8_A_A16_A_A32_I64[13];
+
+Assert (64 == __alignof__ (I64));
+Assert (32 == __alignof__ (A32_I64));
+/* With no explicit alignment, an array of overaligned elements
+ is considered to have the alignment of its elements. */
+Assert (32 == __alignof__ (A_A32_I64));
+Assert (16 == __alignof__ (A16_A_A32_I64));
+Assert (16 == __alignof__ (A_A16_A_A32_I64));
+Assert ( 8 == __alignof__ (A8_A_A16_A_A32_I64));
+
+
+void test_arrays (void)
+{
+ /* Verify that the aligned attribute on each of the composite types
+ is detected corresponding to the result of __alignof__. */
+ A (1, (*(A8_A_A16_A_A32_I64*)0));
+ A3 (1, (*(A8_A_A16_A_A32_I64*)0), 8);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0], 8);
+ /* GCC propagates the user-align bit from element types to their
+ arrays but it doesn't propagate the attribute itself. The built-in
+ considers both the bit and the attribute so it succeeds below even
+ though the referenced type isn't declared with the attribute. */
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0], 8);
+ A3 (1, (*(A8_A_A16_A_A32_I64*)0)[0], 16);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0], 32);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1], 8);
+ A3 (1, (*(A8_A_A16_A_A32_I64*)0)[0][1], 16);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1], 32);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1][2], 16);
+ A3 (1, (*(A8_A_A16_A_A32_I64*)0)[0][1][2], 32);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1][2], 64);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1][2][3], 16);
+ A3 (1, (*(A8_A_A16_A_A32_I64*)0)[0][1][2][3], 32);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1][2][3], 64);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1][2][3][4], 32);
+ A3 (1, (*(A8_A_A16_A_A32_I64*)0)[0][1][2][3][4], 64);
+ A3 (0, (*(A8_A_A16_A_A32_I64*)0)[0][1][2][3][4], 128);
+
+ A8_A_A16_A_A32_I64 a;
+ A3 (0, a[0], 8);
+ A3 (1, a[0], 16);
+ A3 (0, a[0], 32);
+ A3 (0, a[0][1], 8);
+ A3 (1, a[0][1], 16);
+ A3 (0, a[0][1], 32);
+ A3 (0, a[0][1][2], 16);
+ A3 (1, a[0][1][2], 32);
+ A3 (0, a[0][1][2], 64);
+ A3 (0, a[0][1][2][3], 16);
+ A3 (1, a[0][1][2][3], 32);
+ A3 (0, a[0][1][2][3], 64);
+ A3 (0, a[0][1][2][3][4], 32);
+ A3 (1, a[0][1][2][3][4], 64);
+ A3 (0, a[0][1][2][3][4], 128);
+}
+
+void test_pointers (void)
+{
+ /* Verify that the aligned attribute on each of the composite pointer
+ types is detected corresponding to the result of __alignof__. */
+ A (1, I8);
+ A3 (0, I8, 4);
+ A3 (1, I8, 8);
+
+ A (1, P16_I8);
+ A3 (0, P16_I8, 8);
+ A3 (1, P16_I8, 16);
+
+ A (0, P_P16_I8);
+ A3 (0, P_P16_I8, 8);
+ A3 (0, P_P16_I8, 16);
+
+ A (1, P32_P_P16_I8);
+ A3 (0, P32_P_P16_I8, 8);
+ A3 (0, P32_P_P16_I8, 16);
+ A3 (1, P32_P_P16_I8, 32);
+
+ A (0, P_P32_P_P16_I8);
+
+ A (1, P64_P_P32_P_P16_I8);
+ A3 (0, P64_P_P32_P_P16_I8, 8);
+ A3 (0, P64_P_P32_P_P16_I8, 16);
+ A3 (0, P64_P_P32_P_P16_I8, 32);
+ A3 (1, P64_P_P32_P_P16_I8, 64);
+
+
+ /* Verify that the attribute on each of the composite types is detected
+ in the type of each of the indirection expressions. */
+ A (1, *(P16_I8)0);
+ A3 (1, *(P16_I8)0, 8);
+ A3 (0, *(P16_I8)0, 16);
+
+ A (1, *(P_P16_I8)0);
+ A3 (0, *(P_P16_I8)0, 8);
+ A3 (1, *(P_P16_I8)0, 16);
+
+ A (0, *(P32_P_P16_I8)0);
+ A3 (0, *(P32_P_P16_I8)0, 8);
+ A3 (0, *(P32_P_P16_I8)0, 16);
+ A3 (0, *(P32_P_P16_I8)0, 32);
+
+ A (1, *(P_P32_P_P16_I8)0);
+ A3 (1, *(P_P32_P_P16_I8)0, 32);
+
+ A (0, *(P64_P_P32_P_P16_I8)0);
+
+ /* Verify that the attribute on each of the composite types is detected
+ in the type of each of the subscipting expressions. */
+ A (1, ((P16_I8)0)[0]);
+ A3 (1, ((P16_I8)0)[1], 8);
+ A3 (0, ((P16_I8)0)[2], 16);
+
+ A (1, ((P_P16_I8)0)[3]);
+ A3 (0, ((P_P16_I8)0)[4], 8);
+ A3 (1, ((P_P16_I8)0)[5], 16);
+
+ A (0, ((P32_P_P16_I8)0)[6]);
+ A3 (0, ((P32_P_P16_I8)0)[7], 8);
+ A3 (0, ((P32_P_P16_I8)0)[8], 16);
+ A3 (0, ((P32_P_P16_I8)0)[9], 32);
+
+ A (1, ((P_P32_P_P16_I8)0)[10]);
+ A3 (1, ((P_P32_P_P16_I8)0)[11], 32);
+
+ A (0, ((P64_P_P32_P_P16_I8)0)[12]);
+
+
+ /* Verify that the attribute on each of the composite types is detected
+ in the type of each of the subscipting expression involving variables. */
+
+ I8 i8;
+ P16_I8 p16_i8 = &i8;
+ P_P16_I8 p_p16_i8 = &p16_i8;
+ P32_P_P16_I8 p32_p_p16_i8 = &p_p16_i8;
+ P_P32_P_P16_I8 p_p32_p_p16_i8 = &p32_p_p16_i8;
+ P64_P_P32_P_P16_I8 p64_p_p32_p_p16_i8 = &p_p32_p_p16_i8;
+
+ A (1, p16_i8[0]);
+ A3 (1, p16_i8[1], 8);
+ A3 (0, p16_i8[2], 16);
+
+ A (1, p_p16_i8[3]);
+ A3 (0, p_p16_i8[4], 8);
+ A3 (1, p_p16_i8[5], 16);
+
+ A (0, p32_p_p16_i8[6]);
+ A3 (0, p32_p_p16_i8[7], 8);
+ A3 (0, p32_p_p16_i8[8], 16);
+ A3 (0, p32_p_p16_i8[9], 32);
+
+ A (1, p_p32_p_p16_i8[10]);
+ A3 (1, p_p32_p_p16_i8[11], 32);
+
+
+ A (1, p_p16_i8[0][1]);
+ A3 (1, p_p16_i8[1][2], 8);
+ A3 (0, p_p16_i8[2][3], 16);
+
+
+ A (0, p64_p_p32_p_p16_i8[0]);
+
+ A (1, p64_p_p32_p_p16_i8[0][1]);
+ A3 (0, p64_p_p32_p_p16_i8[0][2], 16);
+ A3 (1, p64_p_p32_p_p16_i8[0][3], 32);
+ A3 (0, p64_p_p32_p_p16_i8[0][4], 64);
+
+ A (0, p64_p_p32_p_p16_i8[0][1][2]);
+
+ A (1, p64_p_p32_p_p16_i8[0][1][2][3]);
+ A3 (0, p64_p_p32_p_p16_i8[0][1][2][4], 8);
+ A3 (1, p64_p_p32_p_p16_i8[0][1][2][4], 16);
+ A3 (0, p64_p_p32_p_p16_i8[0][1][2][4], 32);
+
+ A (1, p64_p_p32_p_p16_i8[0][1][2][3][4]);
+ A3 (1, p64_p_p32_p_p16_i8[0][1][2][3][5], 8);
+ A3 (0, p64_p_p32_p_p16_i8[0][1][2][4][6], 16);
+
+
+ /* Same as above but using the indirection expression. */
+ A (0, *p64_p_p32_p_p16_i8);
+
+ A (1, **p64_p_p32_p_p16_i8);
+ A3 (0, **p64_p_p32_p_p16_i8, 16);
+ A3 (1, **p64_p_p32_p_p16_i8, 32);
+ A3 (0, **p64_p_p32_p_p16_i8, 64);
+
+ A (0, ***p64_p_p32_p_p16_i8);
+
+ A (1, ****p64_p_p32_p_p16_i8);
+ A3 (0, ****p64_p_p32_p_p16_i8, 8);
+ A3 (1, ****p64_p_p32_p_p16_i8, 16);
+ A3 (0, ****p64_p_p32_p_p16_i8, 32);
+
+ A (1, *****p64_p_p32_p_p16_i8);
+ A3 (1, *****p64_p_p32_p_p16_i8, 8);
+ A3 (0, *****p64_p_p32_p_p16_i8, 16);
+}
+
+
+S8 f_S8 (void);
+I8 f_I8 (void);
+P16_I8 f_P16_I8 (void);
+P_P16_I8 f_P_P16_I8 (void);
+P32_P_P16_I8 f_P32_P_P16_I8 (void);
+P_P32_P_P16_I8 f_P_P32_P_P16_I8 (void);
+P64_P_P32_P_P16_I8 f_P64_P_P32_P_P16_I8 (void);
+
+void test_function_call (void)
+{
+ /* Verify that the aligned attribute on each of the composite pointer
+ types returned by the functions is detected corresponding to
+ the result of __alignof__. */
+
+ A (0, f_S8 ());
+
+ A (1, f_I8 ());
+ A3 (1, f_I8 (), 8);
+ A3 (0, f_I8 (), 16);
+
+ A (1, f_P16_I8 ());
+ A3 (0, f_P16_I8 (), 8);
+ A3 (1, f_P16_I8 (), 16);
+ A3 (0, f_P16_I8 (), 32);
+
+ A (1, *f_P16_I8 ());
+ A3 (1, *f_P16_I8 (), 8);
+ A3 (0, *f_P16_I8 (), 16);
+
+ A (0, f_P_P16_I8 ());
+
+ A (1, *f_P_P16_I8 ());
+ A3 (0, *f_P_P16_I8 (), 8);
+ A3 (1, *f_P_P16_I8 (), 16);
+ A3 (0, *f_P_P16_I8 (), 32);
+
+ A (1, **f_P_P16_I8 ());
+ A3 (1, **f_P_P16_I8 (), 8);
+ A3 (0, **f_P_P16_I8 (), 16);
+ A3 (0, **f_P_P16_I8 (), 32);
+}
+
+
+void test_compound_literal (void)
+{
+ A (0, (S8){ });
+
+ A (1, (I8){ });
+ A3 (1, (I8){ }, 8);
+ A3 (0, (I8){ }, 16);
+
+ A (1, (I64){ });
+ A3 (0, (I64){ }, 8);
+ A3 (0, (I64){ }, 16);
+ A3 (0, (I64){ }, 32);
+ A3 (1, (I64){ }, 64);
+
+ A (1, (A32_I64){ 0 });
+ A3 (0, (A32_I64){ 0 }, 8);
+ A3 (0, (A32_I64){ 0 }, 16);
+ A3 (1, (A32_I64){ 0 }, 32);
+ A3 (0, (A32_I64){ 0 }, 64);
+
+ A (1, ((A32_I64){ 0 })[0]);
+ A3 (0, ((A32_I64){ 0 })[0], 8);
+ A3 (0, ((A32_I64){ 0 })[0], 16);
+ A3 (0, ((A32_I64){ 0 })[0], 32);
+ A3 (1, ((A32_I64){ 0 })[0], 64);
+}
+
+
+void test_ternary_expression (int i)
+{
+ A (0, (0 ? (S8){ } : (S8){ }));
+
+ A (1, (1 ? (I8){ } : (I8){ }));
+ A3 (1, (2 ? (I8){ } : (I8){ }), 8);
+ A3 (0, (3 ? (I8){ } : (I8){ }), 16);
+
+ A (1, (4 ? (I64){ } : (I64){ }));
+ A3 (0, (5 ? (I64){ } : (I64){ }), 8);
+ A3 (0, (6 ? (I64){ } : (I64){ }), 16);
+ A3 (0, (7 ? (I64){ } : (I64){ }), 32);
+ A3 (1, (8 ? (I64){ } : (I64){ }), 64);
+
+#if !__cplusplus
+ /* Suppress -Wc++-compat warning: converting an array compound literal
+ to a pointer is ill-formed in C++ */
+# pragma GCC diagnostic ignored "-Wc++-compat"
+
+ A (0, (9 ? (A32_I64){ } : (A32_I64){ }));
+ A3 (0, (i ? (A32_I64){ } : (A32_I64){ }), 8);
+ A3 (0, (i++ ? (A32_I64){ } : (A32_I64){ }), 16);
+ A3 (0, (++i ? (A32_I64){ } : (A32_I64){ }), 32);
+ A3 (0, (!i ? (A32_I64){ } : (A32_I64){ }), 64);
+
+ A (1, (0 ? (A32_I64){ } : (A32_I64){ })[0]);
+ A3 (0, (1 ? (A32_I64){ } : (A32_I64){ })[1], 8);
+ A3 (0, (2 ? (A32_I64){ } : (A32_I64){ })[2], 16);
+ A3 (0, (3 ? (A32_I64){ } : (A32_I64){ })[3], 32);
+ A3 (1, (3 ? (A32_I64){ } : (A32_I64){ })[i], 64);
+#endif
+}
+
+
+void test_comma_expression (int i)
+{
+#if __cplusplus
+ /* In C++, the type of the comma expressions whose operand is an array
+ is the array itself with any attributes it was defined with. */
+# define R 1
+#else
+ /* In C, the type of the comma expressions whose operand is an array
+ is a pointer type that does not include any attributes the array
+ was defined with. */
+# define R 0
+/* Suppress -Wc++-compat warning: converting an array compound literal
+ to a pointer is ill-formed in C++
+ G++ accepts the conversion in unevaluated contexts without a warning. */
+# pragma GCC diagnostic ignored "-Wc++-compat"
+#endif
+
+ A (0, (0, (S8){ }));
+
+ A (1, (0, (I8){ }));
+ A3 (1, (1, (I8){ }), 8);
+ A3 (0, (2, (I8){ }), 16);
+
+ A (1, (3, (I64){ }));
+ A3 (0, (4, (I64){ }), 8);
+ A3 (0, (5, (I64){ }), 16);
+ A3 (0, (6, (I64){ }), 32);
+ A3 (1, (7, (I64){ }), 64);
+
+ A (R, (8, (A32_I64){ }));
+ A3 (0, (9, (A32_I64){ }), 8);
+ A3 (0, ((void)0, (A32_I64){ }), 16);
+ A3 (R, ((I64){ },(A32_I64){ }), 32);
+ A3 (0, (0, (A32_I64){ }), 64);
+
+ A (1, (1, ((A32_I64){ })[0]));
+ A3 (0, (2, ((A32_I64){ })[0]), 8);
+ A3 (0, (i++, ((A32_I64){ })[0]), 16);
+ A3 (0, (++i, ((A32_I64){ })[0]), 32);
+ A3 (1, (i = 0, ((A32_I64){ })[0]), 64);
+}