(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
addr_builtin-1.c
       1  /* PR66516 - missing diagnostic on taking the address of a builtin function
       2     { dg-do compile }  */
       3  
       4  typedef void (F)(void);
       5  typedef __UINTPTR_TYPE__ uintptr_t;
       6  
       7  /* Utility function to test passing built-in functions as an ordinary
       8     argument and via the ellipsis.  */
       9  static void func_arg (F *p, ...) { (void)p; }
      10  
      11  static F* test_taking_address_of_gcc_builtin (void)
      12  {
      13    F *p;
      14    void *q;
      15    uintptr_t a;
      16  
      17    /* Call, cast to void, and id are allowed.  */
      18    __builtin_trap ();
      19    (void)__builtin_trap;
      20    __builtin_trap;
      21  
      22    {
      23      typedef __typeof__ (__builtin_trap) F;     /* Okay.  */
      24    }
      25  
      26    /* Address and indirection operators.  */
      27    p = &__builtin_trap;               /* { dg-error "built-in function" }  */
      28    p = *__builtin_trap;               /* { dg-error "built-in function" }  */
      29  
      30    /* Unary NOT.  */
      31    a = !__builtin_trap;               /* { dg-error "built-in function" }  */
      32  
      33    /* Sizeof and _Alignof are disallowed by C but allowed by GCC
      34       and there's no reason to reject built-ins as operands since
      35       doing so doesn't yield their address.  */
      36  #pragma GCC diagnostic push
      37    /* Disable: invalid application of 'sizeof' to a function type.  */
      38  #pragma GCC diagnostic ignored "-Wpointer-arith"
      39    a = sizeof __builtin_trap;
      40  #pragma GCC diagnostic pop
      41  
      42  #ifndef __STDC_VERSION__
      43  #  pragma GCC diagnostic push
      44    /* Disable: ISO C90 does not support '_Alignof'.  */
      45  #  pragma GCC diagnostic ignored "-Wpedantic"
      46  #endif
      47  
      48    a = _Alignof __builtin_trap;
      49  
      50  #ifndef __STDC_VERSION__
      51  #  pragma GCC diagnostic pop
      52  #endif
      53  
      54    /* Casts.  */
      55    p = (F*)__builtin_trap;            /* { dg-error "built-in function" }  */
      56    a = (uintptr_t)__builtin_trap;     /* { dg-error "built-in function" }  */
      57  
      58    /* Additive operator.  */
      59    p = __builtin_trap + 0;            /* { dg-error "built-in function" }  */
      60    p = __builtin_trap - 0;            /* { dg-error "built-in function" }  */
      61    a = __builtin_trap - p;            /* { dg-error "built-in function" }  */
      62    a = p - __builtin_trap;            /* { dg-error "built-in function" }  */
      63  
      64    /* Relational operators.  */
      65    a = __builtin_trap < p;            /* { dg-error "built-in function" }  */
      66    a = p < __builtin_trap;            /* { dg-error "built-in function" }  */
      67  
      68    a = __builtin_trap <= p;           /* { dg-error "built-in function" }  */
      69    a = p <= __builtin_trap;           /* { dg-error "built-in function" }  */
      70  
      71    a = __builtin_trap > p;            /* { dg-error "built-in function" }  */
      72    a = p > __builtin_trap;            /* { dg-error "built-in function" }  */
      73  
      74    a = __builtin_trap > p;            /* { dg-error "built-in function" }  */
      75    a = p > __builtin_trap;            /* { dg-error "built-in function" }  */
      76  
      77    a = __builtin_trap <= p;           /* { dg-error "built-in function" }  */
      78    a = p <= __builtin_trap;           /* { dg-error "built-in function" }  */
      79  
      80    a = __builtin_trap <= p;           /* { dg-error "built-in function" }  */
      81    a = p <= __builtin_trap;           /* { dg-error "built-in function" }  */
      82  
      83    /* Equality operators.  */
      84    a = __builtin_trap == p;           /* { dg-error "built-in function" }  */
      85    a = p == __builtin_trap;           /* { dg-error "built-in function" }  */
      86    a = __builtin_trap != p;           /* { dg-error "built-in function" }  */
      87    a = p != __builtin_trap;           /* { dg-error "built-in function" }  */
      88  
      89    /* Logical AND and OR.  */
      90    a = __builtin_trap && p;           /* { dg-error "built-in function" }  */
      91    a = p && __builtin_trap;           /* { dg-error "built-in function" }  */
      92  
      93    a = __builtin_trap || p;           /* { dg-error "built-in function" }  */
      94    a = p || __builtin_trap;           /* { dg-error "built-in function" }  */
      95  
      96    /* Conditional operator.  */
      97    a = __builtin_trap ? 1 : 0;        /* { dg-error "built-in function" }  */
      98    p = a ? __builtin_trap : 0;        /* { dg-error "built-in function" }  */
      99    p = a ? 0 : __builtin_trap;        /* { dg-error "built-in function" }  */
     100  
     101    /* Assignment operator.  */
     102    p = __builtin_trap;                /* { dg-error "built-in function" }  */
     103  
     104    q = __builtin_trap;                /* { dg-error "built-in function" }  */
     105    a = __builtin_trap;                /* { dg-error "built-in function" }  */
     106  
     107    /* Passing as an argument.  */
     108    func_arg (__builtin_trap);         /* { dg-error "built-in function" }  */
     109  
     110    /* Passing through the ellipsis.  */
     111    func_arg (0, __builtin_trap);      /* { dg-error "built-in function" }  */
     112  
     113    /* Return statement.  */
     114    return __builtin_trap;             /* { dg-error "built-in function" }  */
     115  
     116    (void)a;
     117    (void)p;
     118    (void)q;
     119  }
     120  
     121  /* Helper declarations to verify that it's possible to take the address
     122     of a user-declared function that's also a GCC built-in.  */
     123  extern int abs (int);
     124  
     125  extern __SIZE_TYPE__ strlen (const char*);
     126  
     127  /* Taking the address of a builtin with a library "fallback" must be
     128     allowed, either using the __builtin_xxx form or the xxx form, when
     129     the library fallback is declared either explicitly or implicitly
     130     by virtue of first calling the function.  */
     131  void test_taking_address_of_library_builtin (int i)
     132  {
     133    {
     134      typedef int F (int);
     135  
     136      /* Compute the address of libc's abs using the implicitly declared
     137         __builtin_abs form (all expressions are valid).  */
     138      F *p = __builtin_abs;
     139      p = &__builtin_abs;
     140      p = *__builtin_abs;
     141  
     142      /* Compute the address of libc's abs declared above.  */
     143      p = abs;
     144      p = &abs;
     145      p = *abs;
     146      (void)p;
     147    }
     148  
     149    {
     150      typedef __SIZE_TYPE__ size_t;
     151      typedef size_t F (const char*);
     152  
     153      /* Compute the address of libc's strlen using the implicitly
     154         declared __builtin_strlen form.  */
     155      F *p = __builtin_strlen;
     156      p = &__builtin_strlen;
     157      p = *__builtin_strlen;
     158  
     159      /* Compute the address of libc's strlen declared above.  */
     160      p = strlen;
     161      p = &strlen;
     162      p = *strlen;
     163      (void)p;
     164    }
     165  
     166    {
     167      typedef int F (int);
     168  
     169      /* Compute the address of libc's isxxx functions using the implicitly
     170         declared __builtin_xxx form.  */
     171      F *p = __builtin_isalnum;
     172      p = &__builtin_isalpha;
     173      p = *__builtin_iscntrl;
     174  
     175      /* According to C90 (see also the discussion in c/67386):
     176         If the expression that precedes the parenthesized argument list
     177         in a function call consists solely of an identifier, and if no
     178         declaration is visible for this identifier, the identifier is
     179         implicitly declared exactly as if, in the innermost block
     180         containing the function call, the declaration
     181         extern int identifier();
     182         appeared.  */
     183  
     184      /* Call the functions first to have their declarations "injected"
     185         into the enclosing block.  Suppress warnings.  */
     186  #pragma GCC diagnostic push
     187  #pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
     188      i = isalnum (i) || isalpha (i) || iscntrl (i);
     189  #pragma GCC diagnostic pop
     190  
     191      /* Take the address of the functions relying on their declarations
     192         having been implicitly provided by the calls above.  */
     193      p = isalnum;
     194      p = &isalpha;
     195      p = *iscntrl;
     196      (void)p;
     197    }
     198  }