aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/c-c++-common/builtin-has-attribute-6.c
blob: 89cf4f23d4771004d86f74721b10eb481e3760a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* 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));

}