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;
}
}
|