aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-10-17 02:06:34 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2023-10-17 02:20:51 +0200
commitef8f7e3f973d90fdffaf4b8e720db484ce63df6f (patch)
tree552b47ec87801a86a9a6a9fb834c55ce1c9ab13f /gcc/testsuite
parente16ace7c79687c224d08ee8d04fd637589333a99 (diff)
downloadgcc-ef8f7e3f973d90fdffaf4b8e720db484ce63df6f.zip
gcc-ef8f7e3f973d90fdffaf4b8e720db484ce63df6f.tar.gz
gcc-ef8f7e3f973d90fdffaf4b8e720db484ce63df6f.tar.bz2
d: Forbid taking the address of an intrinsic with no implementation
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. 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.
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/gdc.dg/builtins_reject.d17
-rw-r--r--gcc/testsuite/gdc.dg/intrinsics_reject.d87
2 files changed, 104 insertions, 0 deletions
diff --git a/gcc/testsuite/gdc.dg/builtins_reject.d b/gcc/testsuite/gdc.dg/builtins_reject.d
new file mode 100644
index 0000000..51d7df2
--- /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 0000000..8c644cc
--- /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; }