aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/addr_builtin-1.c
blob: 4a0888a55d3e8c4053d10eae8b435d8629740681 (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/* PR66516 - missing diagnostic on taking the address of a builtin function
   { dg-do compile }  */

typedef void (F)(void);
typedef __UINTPTR_TYPE__ uintptr_t;

/* Utility function to test passing built-in functions as an ordinary
   argument and via the ellipsis.  */
static void func_arg (F *p, ...) { (void)p; }

static F* test_taking_address_of_gcc_builtin (void)
{
  F *p;
  void *q;
  uintptr_t a;

  /* Call, cast to void, and id are allowed.  */
  __builtin_trap ();
  (void)__builtin_trap;
  __builtin_trap;

  {
    typedef __typeof__ (__builtin_trap) F;     /* Okay.  */
  }

  /* Address and indirection operators.  */
  p = &__builtin_trap;               /* { dg-error "built-in function" }  */
  p = *__builtin_trap;               /* { dg-error "built-in function" }  */

  /* Unary NOT.  */
  a = !__builtin_trap;               /* { dg-error "built-in function" }  */

  /* Sizeof and _Alignof are disallowed by C but allowed by GCC
     and there's no reason to reject built-ins as operands since
     doing so doesn't yield their address.  */
#pragma GCC diagnostic push
  /* Disable: invalid application of 'sizeof' to a function type.  */
#pragma GCC diagnostic ignored "-Wpointer-arith"
  a = sizeof __builtin_trap;
#pragma GCC diagnostic pop

#ifndef __STDC_VERSION__
#  pragma GCC diagnostic push
  /* Disable: ISO C90 does not support '_Alignof'.  */
#  pragma GCC diagnostic ignored "-Wpedantic"
#endif

  a = _Alignof __builtin_trap;

#ifndef __STDC_VERSION__
#  pragma GCC diagnostic pop
#endif

  /* Casts.  */
  p = (F*)__builtin_trap;            /* { dg-error "built-in function" }  */
  a = (uintptr_t)__builtin_trap;     /* { dg-error "built-in function" }  */

  /* Additive operator.  */
  p = __builtin_trap + 0;            /* { dg-error "built-in function" }  */
  p = __builtin_trap - 0;            /* { dg-error "built-in function" }  */
  a = __builtin_trap - p;            /* { dg-error "built-in function" }  */
  a = p - __builtin_trap;            /* { dg-error "built-in function" }  */

  /* Relational operators.  */
  a = __builtin_trap < p;            /* { dg-error "built-in function" }  */
  a = p < __builtin_trap;            /* { dg-error "built-in function" }  */

  a = __builtin_trap <= p;           /* { dg-error "built-in function" }  */
  a = p <= __builtin_trap;           /* { dg-error "built-in function" }  */

  a = __builtin_trap > p;            /* { dg-error "built-in function" }  */
  a = p > __builtin_trap;            /* { dg-error "built-in function" }  */

  a = __builtin_trap > p;            /* { dg-error "built-in function" }  */
  a = p > __builtin_trap;            /* { dg-error "built-in function" }  */

  a = __builtin_trap <= p;           /* { dg-error "built-in function" }  */
  a = p <= __builtin_trap;           /* { dg-error "built-in function" }  */

  a = __builtin_trap <= p;           /* { dg-error "built-in function" }  */
  a = p <= __builtin_trap;           /* { dg-error "built-in function" }  */

  /* Equality operators.  */
  a = __builtin_trap == p;           /* { dg-error "built-in function" }  */
  a = p == __builtin_trap;           /* { dg-error "built-in function" }  */
  a = __builtin_trap != p;           /* { dg-error "built-in function" }  */
  a = p != __builtin_trap;           /* { dg-error "built-in function" }  */

  /* Logical AND and OR.  */
  a = __builtin_trap && p;           /* { dg-error "built-in function" }  */
  a = p && __builtin_trap;           /* { dg-error "built-in function" }  */

  a = __builtin_trap || p;           /* { dg-error "built-in function" }  */
  a = p || __builtin_trap;           /* { dg-error "built-in function" }  */

  /* Conditional operator.  */
  a = __builtin_trap ? 1 : 0;        /* { dg-error "built-in function" }  */
  p = a ? __builtin_trap : 0;        /* { dg-error "built-in function" }  */
  p = a ? 0 : __builtin_trap;        /* { dg-error "built-in function" }  */

  /* Assignment operator.  */
  p = __builtin_trap;                /* { dg-error "built-in function" }  */

  q = __builtin_trap;                /* { dg-error "built-in function" }  */
  a = __builtin_trap;                /* { dg-error "built-in function" }  */

  /* Passing as an argument.  */
  func_arg (__builtin_trap);         /* { dg-error "built-in function" }  */

  /* Passing through the ellipsis.  */
  func_arg (0, __builtin_trap);      /* { dg-error "built-in function" }  */

  /* Return statement.  */
  return __builtin_trap;             /* { dg-error "built-in function" }  */

  (void)a;
  (void)p;
  (void)q;
}

/* Helper declarations to verify that it's possible to take the address
   of a user-declared function that's also a GCC built-in.  */
extern int abs (int);

extern __SIZE_TYPE__ strlen (const char*);

/* Taking the address of a builtin with a library "fallback" must be
   allowed, either using the __builtin_xxx form or the xxx form, when
   the library fallback is declared either explicitly or implicitly
   by virtue of first calling the function.  */
void test_taking_address_of_library_builtin (int i)
{
  {
    typedef int F (int);

    /* Compute the address of libc's abs using the implicitly declared
       __builtin_abs form (all expressions are valid).  */
    F *p = __builtin_abs;
    p = &__builtin_abs;
    p = *__builtin_abs;

    /* Compute the address of libc's abs declared above.  */
    p = abs;
    p = &abs;
    p = *abs;
    (void)p;
  }

  {
    typedef __SIZE_TYPE__ size_t;
    typedef size_t F (const char*);

    /* Compute the address of libc's strlen using the implicitly
       declared __builtin_strlen form.  */
    F *p = __builtin_strlen;
    p = &__builtin_strlen;
    p = *__builtin_strlen;

    /* Compute the address of libc's strlen declared above.  */
    p = strlen;
    p = &strlen;
    p = *strlen;
    (void)p;
  }

  {
    typedef int F (int);

    /* Compute the address of libc's isxxx functions using the implicitly
       declared __builtin_xxx form.  */
    F *p = __builtin_isalnum;
    p = &__builtin_isalpha;
    p = *__builtin_iscntrl;

    /* According to C90 (see also the discussion in c/67386):
       If the expression that precedes the parenthesized argument list
       in a function call consists solely of an identifier, and if no
       declaration is visible for this identifier, the identifier is
       implicitly declared exactly as if, in the innermost block
       containing the function call, the declaration
       extern int identifier();
       appeared.  */

    /* Call the functions first to have their declarations "injected"
       into the enclosing block.  Suppress warnings.  */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
    i = isalnum (i) || isalpha (i) || iscntrl (i);
#pragma GCC diagnostic pop

    /* Take the address of the functions relying on their declarations
       having been implicitly provided by the calls above.  */
    p = isalnum;
    p = &isalpha;
    p = *iscntrl;
    (void)p;
  }
}