1 /* PR c/88383 - ICE calling _builtin_has_attribute(r, aligned(N)))
2    on an overaligned reference r
3    PR c/89288 - ICE in tree_code_size, at tree.c:865
4    { dg-options "-Wall -ftrack-macro-expansion=0" }
5    { dg-options "-Wall -Wno-narrowing -Wno-unused -ftrack-macro-expansion=0" { target c++ } }  */
6 
7 #define ATTR(...) __attribute__ ((__VA_ARGS__))
8 
9 #define A(expect, sym, attr)						\
10   typedef int Assert [1 - 2 * !(__builtin_has_attribute (sym, attr) == expect)]
11 
12 typedef ATTR (aligned (8)) int Int8;
13 
14 /* The attribute applies to the array, not to the type of its elements.  */
15 extern ATTR (aligned (8)) char i8arr[];
16 
17 /* The attribute applies to the pointer, not to the type it points to.  */
18 extern ATTR (aligned (8)) int *ptr;
19 extern Int8 *i8ptr;
20 
21 #if __cplusplus
22 
23 /* Similarly here, the attribute applies to the reference, not to its type.  */
24 extern ATTR (aligned (8)) int &ref;
25 extern Int8 &i8ref;
26 
27 #else
28 
29 /* Fake references in C.  */
30 extern ATTR (aligned (8)) int ref;
31 Int8 i8ref;
32 
33 #endif
34 
35 void test (void)
36 {
37   /* Verify that the built-in detects the attribute on the array. */
38   A (1, i8arr, aligned);
39   A (0, i8arr, aligned (1));
40   A (0, i8arr, aligned (2));
41   A (0, i8arr, aligned (4));
42   A (1, i8arr, aligned (8));
43   A (0, i8arr, aligned (16));
44 
45   A (0, i8arr + 1, aligned);
46   A (0, i8arr + 2, aligned (1));
47   A (0, i8arr + 3, aligned (8));
48 
49   /* Verify the builtin detects the absence of the attribute on
50      the elements.  */
51   A (0, i8arr[0], aligned);
52   A (0, *i8arr,   aligned);
53 
54   /* Verify that the built-in doesn't confuse the attribute on
55      the pointer type with that to the pointed to type.  This
56      also exercises PR c/89288.  */
57   A (0, (Int8*)0, aligned);
58   A (0, (int*)0,  aligned);
59   A (0, (void*)0, aligned);
60   A (0, 0,        aligned);
61 
62   /* Verify that the built-in detects the attribute on the pointer
63      itself. */
64   A (1, ptr, aligned);
65   A (0, ptr, aligned (1));
66   A (0, ptr, aligned (2));
67   A (0, ptr, aligned (4));
68   A (1, ptr, aligned (8));
69   A (0, ptr, aligned (16));
70 
71   A (0, ptr + 1, aligned);
72   A (0, ptr + 2, aligned (1));
73   A (0, ptr + 3, aligned (8));
74 
75   /* The pointed to type is not declared with attribute aligned.  */
76   A (0, *ptr, aligned);
77   A (0, *ptr, aligned (1));
78   A (0, *ptr, aligned (2));
79   A (0, *ptr, aligned (4));
80   A (0, *ptr, aligned (8));
81   A (0, *ptr, aligned (16));
82 
83   A (0, *ptr + 1, aligned);
84   A (0, *ptr + 2, aligned (1));
85   A (0, *ptr + 3, aligned (8));
86 
87   /* Verify that the built-in correctly detects the attribute on
88      the type of the lvalue referenced by the pointer. */
89   A (0, i8ptr,     aligned);
90   A (0, i8ptr,     aligned (8));
91   A (0, i8ptr + 1, aligned);
92   A (0, i8ptr + 3, aligned (8));
93   A (1, *i8ptr,    aligned);
94   A (0, *i8ptr,    aligned (1));
95   A (0, *i8ptr,    aligned (2));
96   A (0, *i8ptr,    aligned (4));
97   A (1, *i8ptr,    aligned (8));
98   A (0, *i8ptr,    aligned (16));
99 
100   /* The reference itself is declared aligned, even though the type
101      it refers to isn't.  But see PR c++/88362.  */
102   A (1, ref, aligned);
103   A (0, ref, aligned (1));
104   A (0, ref, aligned (2));
105   A (0, ref, aligned (4));
106   A (1, ref, aligned (8));
107   A (0, ref, aligned (16));
108 
109   /* Also verify that assignment expressions are accepted.  */
110   A (0, ref = 1,  aligned);
111   A (0, ref += 2, aligned (1));
112   A (0, ref /= 3, aligned (8));
113 
114 }
115