Mercurial > hg > CbC > CbC_gcc
diff gcc/testsuite/gcc.dg/addr_builtin-1.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/testsuite/gcc.dg/addr_builtin-1.c Fri Oct 27 22:46:09 2017 +0900 @@ -0,0 +1,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; + } +}