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