diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-10-17 02:06:34 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-10-17 02:20:51 +0200 |
commit | ef8f7e3f973d90fdffaf4b8e720db484ce63df6f (patch) | |
tree | 552b47ec87801a86a9a6a9fb834c55ce1c9ab13f /gcc/testsuite | |
parent | e16ace7c79687c224d08ee8d04fd637589333a99 (diff) | |
download | gcc-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.d | 17 | ||||
-rw-r--r-- | gcc/testsuite/gdc.dg/intrinsics_reject.d | 87 |
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; } |