diff mbox series

[committed] d: Forbid taking the address of an intrinsic with no implementation

Message ID 20231017002328.3165172-1-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Forbid taking the address of an intrinsic with no implementation | expand

Commit Message

Iain Buclaw Oct. 17, 2023, 12:23 a.m. UTC
Hi,

This code fails to link:

    import core.math;
    real function(real) fn = &sin;

However, when called directly, the D intrinsic `sin()' is expanded by
the front-end into the GCC built-in `__builtin_sin()'.  This has been
fixed to now also expand the function when a reference is taken.

As there are D intrinsics and GCC built-ins that don't have a fallback
implementation, raise an error if taking the address is not possible.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32, and
committed to mainline.

Regards,
Iain.

---
gcc/d/ChangeLog:

	* d-tree.h (intrinsic_code): Update define for DEF_D_INTRINSIC.
	(maybe_reject_intrinsic): New prototype.
	* expr.cc (ExprVisitor::visit (SymOffExp *)): Call
	maybe_reject_intrinsic.
	* intrinsics.cc (intrinsic_decl): Add fallback field.
	(intrinsic_decls): Update define for DEF_D_INTRINSIC.
	(maybe_reject_intrinsic): New function.
	* intrinsics.def (DEF_D_LIB_BUILTIN): Update.
	(DEF_CTFE_BUILTIN): Update.
	(INTRINSIC_BSF): Declare as library builtin.
	(INTRINSIC_BSR): Likewise.
	(INTRINSIC_BT): Likewise.
	(INTRINSIC_BSF64): Likewise.
	(INTRINSIC_BSR64): Likewise.
	(INTRINSIC_BT64): Likewise.
	(INTRINSIC_POPCNT32): Likewise.
	(INTRINSIC_POPCNT64): Likewise.
	(INTRINSIC_ROL): Likewise.
	(INTRINSIC_ROL_TIARG): Likewise.
	(INTRINSIC_ROR): Likewise.
	(INTRINSIC_ROR_TIARG): Likewise.
	(INTRINSIC_ADDS): Likewise.
	(INTRINSIC_ADDSL): Likewise.
	(INTRINSIC_ADDU): Likewise.
	(INTRINSIC_ADDUL): Likewise.
	(INTRINSIC_SUBS): Likewise.
	(INTRINSIC_SUBSL): Likewise.
	(INTRINSIC_SUBU): Likewise.
	(INTRINSIC_SUBUL): Likewise.
	(INTRINSIC_MULS): Likewise.
	(INTRINSIC_MULSL): Likewise.
	(INTRINSIC_MULU): Likewise.
	(INTRINSIC_MULUI): Likewise.
	(INTRINSIC_MULUL): Likewise.
	(INTRINSIC_NEGS): Likewise.
	(INTRINSIC_NEGSL): Likewise.
	(INTRINSIC_TOPRECF): Likewise.
	(INTRINSIC_TOPREC): Likewise.
	(INTRINSIC_TOPRECL): Likewise.

gcc/testsuite/ChangeLog:

	* gdc.dg/builtins_reject.d: New test.
	* gdc.dg/intrinsics_reject.d: New test.
---
 gcc/d/d-tree.h                           |   3 +-
 gcc/d/expr.cc                            |   3 +
 gcc/d/intrinsics.cc                      |  47 ++++++++-
 gcc/d/intrinsics.def                     | 128 ++++++++++++-----------
 gcc/testsuite/gdc.dg/builtins_reject.d   |  17 +++
 gcc/testsuite/gdc.dg/intrinsics_reject.d |  87 +++++++++++++++
 6 files changed, 222 insertions(+), 63 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/builtins_reject.d
 create mode 100644 gcc/testsuite/gdc.dg/intrinsics_reject.d
diff mbox series

Patch

diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index b64a6fb46f9..66c2f2465c8 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -94,7 +94,7 @@  enum level_kind
 
 enum intrinsic_code
 {
-#define DEF_D_INTRINSIC(CODE, B, N, M, D, C) CODE,
+#define DEF_D_INTRINSIC(CODE, B, N, M, D, C, F) CODE,
 
 #include "intrinsics.def"
 
@@ -668,6 +668,7 @@  extern tree build_import_decl (Dsymbol *);
 /* In intrinsics.cc.  */
 extern void maybe_set_intrinsic (FuncDeclaration *);
 extern tree maybe_expand_intrinsic (tree);
+extern tree maybe_reject_intrinsic (tree);
 
 /* In modules.cc.  */
 extern void build_module_tree (Module *);
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index cc4aa03dfb9..52243e61899 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2050,6 +2050,9 @@  public:
     tree result = get_decl_tree (e->var);
     TREE_USED (result) = 1;
 
+    if (e->var->isFuncDeclaration ())
+      result = maybe_reject_intrinsic (result);
+
     if (declaration_reference_p (e->var))
       gcc_assert (POINTER_TYPE_P (TREE_TYPE (result)));
     else
diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc
index 583d5a9dea6..1b03e9edbdb 100644
--- a/gcc/d/intrinsics.cc
+++ b/gcc/d/intrinsics.cc
@@ -60,12 +60,15 @@  struct intrinsic_decl
 
   /* True if the intrinsic is only handled in CTFE.  */
   bool ctfeonly;
+
+  /* True if the intrinsic has a library implementation.  */
+  bool fallback;
 };
 
 static const intrinsic_decl intrinsic_decls[] =
 {
-#define DEF_D_INTRINSIC(CODE, BUILTIN, NAME, MODULE, DECO, CTFE) \
-    { CODE, BUILTIN, NAME, MODULE, DECO, CTFE },
+#define DEF_D_INTRINSIC(CODE, BUILTIN, NAME, MODULE, DECO, CTFE, FALLBACK) \
+    { CODE, BUILTIN, NAME, MODULE, DECO, CTFE, FALLBACK },
 
 #include "intrinsics.def"
 
@@ -1436,3 +1439,43 @@  maybe_expand_intrinsic (tree callexp)
       gcc_unreachable ();
     }
 }
+
+/* If FNDECL is an intrinsic, return the FUNCTION_DECL that has a library
+   fallback implementation of it, otherwise raise an error.  */
+
+tree
+maybe_reject_intrinsic (tree fndecl)
+{
+  gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
+
+  intrinsic_code intrinsic = DECL_INTRINSIC_CODE (fndecl);
+
+  if (intrinsic == INTRINSIC_NONE)
+    {
+      /* Not an intrinsic, but it still might be a declaration from the
+	 `gcc.builtins' module.  */
+      if (fndecl_built_in_p (fndecl) && DECL_IS_UNDECLARED_BUILTIN (fndecl)
+	  && !DECL_ASSEMBLER_NAME_SET_P (fndecl))
+	error ("built-in function %qE must be directly called", fndecl);
+
+      return fndecl;
+    }
+
+  /* Nothing to do if the intrinsic has a D library implementation.  */
+  if (intrinsic_decls[intrinsic].fallback)
+    return fndecl;
+
+  /* Check the GCC built-in decl if the intrinsic maps to one.  */
+  built_in_function code = intrinsic_decls[intrinsic].built_in;
+  if (code != BUILT_IN_NONE)
+    {
+      tree builtin = builtin_decl_explicit (code);
+      if (!DECL_IS_UNDECLARED_BUILTIN (builtin)
+	  || DECL_ASSEMBLER_NAME_SET_P (builtin))
+	return builtin;
+    }
+
+  /* It's a D language intrinsic with no library implementation.  */
+  error ("intrinsic function %qE must be directly called", fndecl);
+  return fndecl;
+}
diff --git a/gcc/d/intrinsics.def b/gcc/d/intrinsics.def
index 454bddfd186..e472cf70362 100644
--- a/gcc/d/intrinsics.def
+++ b/gcc/d/intrinsics.def
@@ -15,7 +15,7 @@  You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-/* DEF_D_INTRINSIC (CODE, BUILTIN, NAME, MODULE, DECO, CTFE)
+/* DEF_D_INTRINSIC (CODE, BUILTIN, NAME, MODULE, DECO, CTFE, FALLBACK)
    CODE	    The enum code used to refer to this intrinsic.
    BUILTIN  The enum code used to reference the function DECL_FUNCTION_CODE,
 	    if the intrinsic can be mapped 1:1 to a GCC built-in.
@@ -24,40 +24,45 @@  along with GCC; see the file COPYING3.  If not see
    DECO	    The function signature decoration of the intrinsic.
    CTFE	    True if the function is only handled as a built-in during CTFE,
 	    otherwise the runtime implementation is used.
+   FALLBACK True if the function has a D runtime library implementation.
 
    Used for declaring internally recognized functions that either map to a
    GCC builtin, or are specially handled by the compiler.  */
 
 /* A D built-in that has no runtime implementation.  */
 #define DEF_D_BUILTIN(C, B, N, M, D) \
-  DEF_D_INTRINSIC (C, B, N, M, D, false)
+  DEF_D_INTRINSIC (C, B, N, M, D, false, false)
+
+/* A D built-in that has a runtime implementation.  */
+#define DEF_D_LIB_BUILTIN(C, B, N, M, D) \
+  DEF_D_INTRINSIC (C, B, N, M, D, false, true)
 
 /* A D built-in that is specially recognized only during CTFE.  */
 #define DEF_CTFE_BUILTIN(C, B, N, M, D) \
-  DEF_D_INTRINSIC (C, B, N, M, D, true)
+  DEF_D_INTRINSIC (C, B, N, M, D, true, true)
 
 DEF_D_BUILTIN (INTRINSIC_NONE, BUILT_IN_NONE, 0, 0, 0)
 
 /* core.bitop intrinsics.  */
 
-DEF_D_BUILTIN (INTRINSIC_BSF, BUILT_IN_NONE, "bsf", "core.bitop",
-	       "FNaNbNiNfkZi")
-DEF_D_BUILTIN (INTRINSIC_BSR, BUILT_IN_NONE, "bsr", "core.bitop",
-	       "FNaNbNiNfkZi")
-DEF_D_BUILTIN (INTRINSIC_BT, BUILT_IN_NONE, "bt", "core.bitop",
-	       "FNaNbNiMxPkkZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_BSF, BUILT_IN_NONE, "bsf", "core.bitop",
+		   "FNaNbNiNfkZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_BSR, BUILT_IN_NONE, "bsr", "core.bitop",
+		   "FNaNbNiNfkZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_BT, BUILT_IN_NONE, "bt", "core.bitop",
+		   "FNaNbNiMxPkkZi")
 DEF_D_BUILTIN (INTRINSIC_BTC, BUILT_IN_NONE, "btc", "core.bitop",
 	       "FNaNbNiPkkZi")
 DEF_D_BUILTIN (INTRINSIC_BTR, BUILT_IN_NONE, "btr", "core.bitop",
 	       "FNaNbNiPkkZi")
 DEF_D_BUILTIN (INTRINSIC_BTS, BUILT_IN_NONE, "bts", "core.bitop",
 	       "FNaNbNiPkkZi")
-DEF_D_BUILTIN (INTRINSIC_BSF64, BUILT_IN_NONE, "bsf", "core.bitop",
-	       "FNaNbNiNfmZi")
-DEF_D_BUILTIN (INTRINSIC_BSR64, BUILT_IN_NONE, "bsr", "core.bitop",
-	       "FNaNbNiNfmZi")
-DEF_D_BUILTIN (INTRINSIC_BT64, BUILT_IN_NONE, "bt", "core.bitop",
-	       "FNaNbNiMxPmmZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_BSF64, BUILT_IN_NONE, "bsf", "core.bitop",
+		   "FNaNbNiNfmZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_BSR64, BUILT_IN_NONE, "bsr", "core.bitop",
+		   "FNaNbNiNfmZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_BT64, BUILT_IN_NONE, "bt", "core.bitop",
+		   "FNaNbNiMxPmmZi")
 DEF_D_BUILTIN (INTRINSIC_BTC64, BUILT_IN_NONE, "btc", "core.bitop",
 	       "FNaNbNiPmmZi")
 DEF_D_BUILTIN (INTRINSIC_BTR64, BUILT_IN_NONE, "btr", "core.bitop",
@@ -72,17 +77,19 @@  DEF_D_BUILTIN (INTRINSIC_BSWAP32, BUILT_IN_BSWAP32, "bswap", "core.bitop",
 DEF_D_BUILTIN (INTRINSIC_BSWAP64, BUILT_IN_BSWAP64, "bswap", "core.bitop",
 	       "FNaNbNiNfmZm")
 
-DEF_D_BUILTIN (INTRINSIC_POPCNT32, BUILT_IN_NONE, "popcnt", "core.bitop",
-	       "FNaNbNiNfkZi")
-DEF_D_BUILTIN (INTRINSIC_POPCNT64, BUILT_IN_NONE, "popcnt", "core.bitop",
-	       "FNaNbNiNfmZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_POPCNT32, BUILT_IN_NONE, "popcnt", "core.bitop",
+		   "FNaNbNiNfkZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_POPCNT64, BUILT_IN_NONE, "popcnt", "core.bitop",
+		   "FNaNbNiNfmZi")
 
-DEF_D_BUILTIN (INTRINSIC_ROL, BUILT_IN_NONE, "rol", "core.bitop", "FNa@1TkZ@1T")
-DEF_D_BUILTIN (INTRINSIC_ROL_TIARG, BUILT_IN_NONE, "rol", "core.bitop",
-	       "FNa@1TZ@1T")
-DEF_D_BUILTIN (INTRINSIC_ROR, BUILT_IN_NONE, "ror", "core.bitop", "FNa@1TkZ@1T")
-DEF_D_BUILTIN (INTRINSIC_ROR_TIARG, BUILT_IN_NONE, "ror", "core.bitop",
-	       "FNa@1TZ@1T")
+DEF_D_LIB_BUILTIN (INTRINSIC_ROL, BUILT_IN_NONE, "rol", "core.bitop",
+		   "FNa@1TkZ@1T")
+DEF_D_LIB_BUILTIN (INTRINSIC_ROL_TIARG, BUILT_IN_NONE, "rol", "core.bitop",
+		   "FNa@1TZ@1T")
+DEF_D_LIB_BUILTIN (INTRINSIC_ROR, BUILT_IN_NONE, "ror", "core.bitop",
+		   "FNa@1TkZ@1T")
+DEF_D_LIB_BUILTIN (INTRINSIC_ROR_TIARG, BUILT_IN_NONE, "ror", "core.bitop",
+		   "FNa@1TZ@1T")
 
 /* core.volatile intrinsics.  */
 
@@ -105,36 +112,36 @@  DEF_D_BUILTIN (INTRINSIC_VSTORE64, BUILT_IN_NONE, "volatileStore",
 
 /* core.checkedint intrinsics.  */
 
-DEF_D_BUILTIN (INTRINSIC_ADDS, BUILT_IN_NONE, "adds", "core.checkedint",
-	       "FiiKbZi")
-DEF_D_BUILTIN (INTRINSIC_ADDSL, BUILT_IN_NONE, "adds", "core.checkedint",
-	       "FllKbZl")
-DEF_D_BUILTIN (INTRINSIC_ADDU, BUILT_IN_NONE, "addu", "core.checkedint",
-	       "FkkKbZk")
-DEF_D_BUILTIN (INTRINSIC_ADDUL, BUILT_IN_NONE, "addu", "core.checkedint",
-	       "FmmKbZm")
-DEF_D_BUILTIN (INTRINSIC_SUBS, BUILT_IN_NONE, "subs", "core.checkedint",
-	       "FiiKbZi")
-DEF_D_BUILTIN (INTRINSIC_SUBSL, BUILT_IN_NONE, "subs", "core.checkedint",
-	       "FllKbZl")
-DEF_D_BUILTIN (INTRINSIC_SUBU, BUILT_IN_NONE, "subu", "core.checkedint",
-	       "FkkKbZk")
-DEF_D_BUILTIN (INTRINSIC_SUBUL, BUILT_IN_NONE, "subu", "core.checkedint",
-	       "FmmKbZm")
-DEF_D_BUILTIN (INTRINSIC_MULS, BUILT_IN_NONE, "muls", "core.checkedint",
-	       "FiiKbZi")
-DEF_D_BUILTIN (INTRINSIC_MULSL, BUILT_IN_NONE, "muls", "core.checkedint",
-	       "FllKbZl")
-DEF_D_BUILTIN (INTRINSIC_MULU, BUILT_IN_NONE, "mulu", "core.checkedint",
-	       "FkkKbZk")
-DEF_D_BUILTIN (INTRINSIC_MULUI, BUILT_IN_NONE, "mulu", "core.checkedint",
-	       "FmkKbZm")
-DEF_D_BUILTIN (INTRINSIC_MULUL, BUILT_IN_NONE, "mulu", "core.checkedint",
-	       "FmmKbZm")
-DEF_D_BUILTIN (INTRINSIC_NEGS, BUILT_IN_NONE, "negs", "core.checkedint",
-	       "FiKbZi")
-DEF_D_BUILTIN (INTRINSIC_NEGSL, BUILT_IN_NONE, "negs", "core.checkedint",
-	       "FlKbZl")
+DEF_D_LIB_BUILTIN (INTRINSIC_ADDS, BUILT_IN_NONE, "adds", "core.checkedint",
+		   "FiiKbZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_ADDSL, BUILT_IN_NONE, "adds", "core.checkedint",
+		   "FllKbZl")
+DEF_D_LIB_BUILTIN (INTRINSIC_ADDU, BUILT_IN_NONE, "addu", "core.checkedint",
+		   "FkkKbZk")
+DEF_D_LIB_BUILTIN (INTRINSIC_ADDUL, BUILT_IN_NONE, "addu", "core.checkedint",
+		   "FmmKbZm")
+DEF_D_LIB_BUILTIN (INTRINSIC_SUBS, BUILT_IN_NONE, "subs", "core.checkedint",
+		   "FiiKbZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_SUBSL, BUILT_IN_NONE, "subs", "core.checkedint",
+		   "FllKbZl")
+DEF_D_LIB_BUILTIN (INTRINSIC_SUBU, BUILT_IN_NONE, "subu", "core.checkedint",
+		   "FkkKbZk")
+DEF_D_LIB_BUILTIN (INTRINSIC_SUBUL, BUILT_IN_NONE, "subu", "core.checkedint",
+		   "FmmKbZm")
+DEF_D_LIB_BUILTIN (INTRINSIC_MULS, BUILT_IN_NONE, "muls", "core.checkedint",
+		   "FiiKbZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_MULSL, BUILT_IN_NONE, "muls", "core.checkedint",
+		   "FllKbZl")
+DEF_D_LIB_BUILTIN (INTRINSIC_MULU, BUILT_IN_NONE, "mulu", "core.checkedint",
+		   "FkkKbZk")
+DEF_D_LIB_BUILTIN (INTRINSIC_MULUI, BUILT_IN_NONE, "mulu", "core.checkedint",
+		   "FmkKbZm")
+DEF_D_LIB_BUILTIN (INTRINSIC_MULUL, BUILT_IN_NONE, "mulu", "core.checkedint",
+		   "FmmKbZm")
+DEF_D_LIB_BUILTIN (INTRINSIC_NEGS, BUILT_IN_NONE, "negs", "core.checkedint",
+		   "FiKbZi")
+DEF_D_LIB_BUILTIN (INTRINSIC_NEGSL, BUILT_IN_NONE, "negs", "core.checkedint",
+		   "FlKbZl")
 
 /* core.math intrinsics.  */
 
@@ -182,11 +189,12 @@  DEF_D_BUILTIN (INTRINSIC_SQRT, BUILT_IN_SQRT, "sqrt", "core.math",
 	       "FNaNbNiNfdZd")
 DEF_D_BUILTIN (INTRINSIC_SQRTL, BUILT_IN_SQRTL, "sqrt", "core.math",
 	       "FNaNbNiNfeZe")
-DEF_D_BUILTIN (INTRINSIC_TOPRECF, BUILT_IN_NONE, "toPrec", "core.math",
-	       "FfZ@1T")
-DEF_D_BUILTIN (INTRINSIC_TOPREC, BUILT_IN_NONE, "toPrec", "core.math", "FdZ@1T")
-DEF_D_BUILTIN (INTRINSIC_TOPRECL, BUILT_IN_NONE, "toPrec", "core.math",
-	       "FeZ@1T")
+DEF_D_LIB_BUILTIN (INTRINSIC_TOPRECF, BUILT_IN_NONE, "toPrec", "core.math",
+		   "FfZ@1T")
+DEF_D_LIB_BUILTIN (INTRINSIC_TOPREC, BUILT_IN_NONE, "toPrec", "core.math",
+		   "FdZ@1T")
+DEF_D_LIB_BUILTIN (INTRINSIC_TOPRECL, BUILT_IN_NONE, "toPrec", "core.math",
+		   "FeZ@1T")
 
 /* std.math intrinsics.  */
 
diff --git a/gcc/testsuite/gdc.dg/builtins_reject.d b/gcc/testsuite/gdc.dg/builtins_reject.d
new file mode 100644
index 00000000000..51d7df236ed
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/builtins_reject.d
@@ -0,0 +1,17 @@ 
+// { dg-do compile }
+
+import gcc.builtins;
+
+auto test_sqrt() { return &__builtin_sqrt; }
+auto test_tan() { return &__builtin_tan; }
+auto test_malloc() { return &__builtin_malloc; }
+auto test_printf() { return &__builtin_printf; }
+
+// { dg-error ".__builtin_inf. must be directly called" "" { target *-*-* } .+1 }
+auto test_inf() { return &__builtin_inf; }
+// { dg-error ".__builtin_lfloor. must be directly called" "" { target *-*-* } .+1 }
+auto test_lfloor() { return &__builtin_lfloor; }
+// { dg-error ".__builtin_setjmp. must be directly called" "" { target *-*-* } .+1 }
+auto test_setjmp() { return &__builtin_setjmp; }
+// { dg-error ".__builtin_unreachable. must be directly called" "" { target *-*-* } .+1 }
+auto test_unreachable() { return &__builtin_unreachable; }
diff --git a/gcc/testsuite/gdc.dg/intrinsics_reject.d b/gcc/testsuite/gdc.dg/intrinsics_reject.d
new file mode 100644
index 00000000000..8c644cc025b
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/intrinsics_reject.d
@@ -0,0 +1,87 @@ 
+// { dg-do compile }
+import core.bitop;
+import core.math;
+import core.volatile;
+import core.stdc.stdarg;
+
+//////////////////////////////////////////////////////
+// core.bitop
+
+int function(uint) test_bsf() { return &bsf; }
+int function(ulong) test_bsfl() { return &bsf; }
+int function(uint) test_bsr() { return &bsr; }
+int function(ulong) test_bsrl() { return &bsr; }
+auto test_bt() { return &bt; }
+// { dg-error "intrinsic function .btc. must be directly called" "" { target *-*-* } .+1 }
+auto test_btc() { return &btc; }
+// { dg-error "intrinsic function .btr. must be directly called" "" { target *-*-* } .+1 }
+auto test_btr() { return &btr; }
+// { dg-error "intrinsic function .bts. must be directly called" "" { target *-*-* } .+1 }
+auto test_bts() { return &bts; }
+// { dg-error "intrinsic function .byteswap. must be directly called" "" { target *-*-* } .+1 }
+ushort function(ushort) test_byteswap() { return &byteswap; }
+// { dg-error "intrinsic function .bswap. must be directly called" "" { target *-*-* } .+1 }
+uint function(uint) test_bswap() { return &bswap; }
+// { dg-error "intrinsic function .bswap. must be directly called" "" { target *-*-* } .+1 }
+ulong function(ulong) test_bswapl() { return &bswap; }
+int function(uint) test_popcnt() { return &popcnt; }
+int function(ulong) test_popcntl() { return &popcnt; }
+auto test_rol() { return &rol!ubyte; }
+auto test_rol(uint a) { return &rol!(1, uint); }
+auto test_ror(ushort a, uint b) { return &ror!ushort; }
+auto test_ror(ulong a) { return &ror!(1, ulong); }
+
+//////////////////////////////////////////////////////
+// core.math
+
+float function(float) test_cosf() { return &cos; }
+double function(double) test_cos() { return &cos; }
+real function(real) test_cosl() { return &cos; }
+float function(float) test_sinf() { return &sin; }
+double function(double) test_sin() { return &sin; }
+real function(real) test_sinl() { return &sin; }
+long function(float) test_rndtolf() { return &rndtol; }
+long function(double) test_rndtol() { return &rndtol; }
+long function(real) test_rndtoll() { return &rndtol; }
+float function(float) test_sqrtf() { return &sqrt; }
+double function(double) test_sqrt() { return &sqrt; }
+real function(real) test_sqrtl() { return &sqrt; }
+float function(float, int) test_ldexpf() { return &ldexp; }
+double function(double, int) test_ldexp() { return &ldexp; }
+real function(real, int) test_ldexpl() { return &ldexp; }
+float function(float) test_fabsf() { return &fabs; }
+double function(double) test_fabs() { return &fabs; }
+real function(real) test_fabsl() { return &fabs; }
+float function(float) test_rintf() { return &rint; }
+double function(double) test_rint() { return &rint; }
+real function(real) test_rintl() { return &rint; }
+
+//////////////////////////////////////////////////////
+// core.volatile
+
+// { dg-error "intrinsic function .volatileLoad. must be directly called" "" { target *-*-* } .+1 }
+ubyte function(ubyte*) test_volatileLoad8() { return &volatileLoad; }
+// { dg-error "intrinsic function .volatileLoad. must be directly called" "" { target *-*-* } .+1 }
+ushort function(ushort*) test_volatileLoad16() { return &volatileLoad; }
+// { dg-error "intrinsic function .volatileLoad. must be directly called" "" { target *-*-* } .+1 }
+uint function(uint*) test_volatileLoad32() { return &volatileLoad; }
+// { dg-error "intrinsic function .volatileLoad. must be directly called" "" { target *-*-* } .+1 }
+ulong function(ulong*) test_volatileLoad64() { return &volatileLoad; }
+// { dg-error "intrinsic function .volatileStore. must be directly called" "" { target *-*-* } .+1 }
+void function(ubyte*, ubyte) test_volatileStore8() { return &volatileStore; }
+// { dg-error "intrinsic function .volatileStore. must be directly called" "" { target *-*-* } .+1 }
+void function(ushort*, ushort) test_volatileStore16() { return &volatileStore; }
+// { dg-error "intrinsic function .volatileStore. must be directly called" "" { target *-*-* } .+1 }
+void function(uint*, uint) test_volatileStore32() { return &volatileStore; }
+// { dg-error "intrinsic function .volatileStore. must be directly called" "" { target *-*-* } .+1 }
+void function(ulong*, ulong) test_volatileStore64() { return &volatileStore; }
+
+//////////////////////////////////////////////////////
+// core.stdc.stdarg
+
+// { dg-error "intrinsic function .va_start. must be directly called" "" { target *-*-* } .+1 }
+auto test_va_start() { return &va_start!int; }
+// { dg-error "built-in function .__builtin_va_end. must be directly called" "" { target *-*-* } .+1 }
+auto test_va_end() { return &va_end; }
+// { dg-error "built-in function .__builtin_va_copy. must be directly called" "" { target *-*-* } .+1 }
+auto test_va_copy() { return &va_copy; }