diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-02-28 19:22:36 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-02-28 20:58:43 +0100 |
commit | f7bc17ebc9ef89700672ed7125da719f3558f3b7 (patch) | |
tree | 1882c0683ee843f44e85b256d97bc2d4ceb41997 /gcc/ada/a-synbar.adb | |
parent | 96572464234a88949ebfc07207ae2ae04c63e53b (diff) | |
download | gcc-trunk.zip gcc-trunk.tar.gz gcc-trunk.tar.bz2 |
Floating-point emulation in the D front-end is done via a type named
`struct longdouble`, which in GDC is a small interface around the
real_value type. Because the D code cannot include gcc/real.h directly,
a big enough buffer is used for the data instead.
On x86_64, this buffer is actually bigger than real_value itself, so
when a new longdouble object is created with
longdouble r;
real_from_string3 (&r.rv (), buffer, mode);
return r;
there is uninitialized padding at the end of `r`. This was never a
problem when D was implemented in C++ (until GCC 12) as comparing two
longdouble objects with `==' would be forwarded to the relevant
operator== overload that extracted the underlying real_value.
However when the front-end was translated to D, such conditions were
instead rewritten into identity comparisons
return exp.toReal() is CTFloat.zero
The `is` operator gets lowered as a call to `memcmp() == 0', which is
where the read of uninitialized memory occurs, as seen by valgrind.
==26778== Conditional jump or move depends on uninitialised value(s)
==26778== at 0x911F41: dmd.dstruct._isZeroInit(dmd.expression.Expression) (dstruct.d:635)
==26778== by 0x9123BE: StructDeclaration::finalizeSize() (dstruct.d:373)
==26778== by 0x86747C: dmd.aggregate.AggregateDeclaration.determineSize(ref const(dmd.location.Loc)) (aggregate.d:226)
[...]
To avoid accidentally reading uninitialized data, explicitly initialize
all `longdouble` variables with an empty constructor on C++ side of the
implementation before initializing underlying real_value type it holds.
PR d/116961
gcc/d/ChangeLog:
* d-codegen.cc (build_float_cst): Change new_value type from real_t to
real_value.
* d-ctfloat.cc (CTFloat::fabs): Default initialize the return value.
(CTFloat::ldexp): Likewise.
(CTFloat::parse): Likewise.
* d-longdouble.cc (longdouble::add): Likewise.
(longdouble::sub): Likewise.
(longdouble::mul): Likewise.
(longdouble::div): Likewise.
(longdouble::mod): Likewise.
(longdouble::neg): Likewise.
* d-port.cc (Port::isFloat32LiteralOutOfRange): Likewise.
(Port::isFloat64LiteralOutOfRange): Likewise.
gcc/testsuite/ChangeLog:
* gdc.dg/pr116961.d: New test.
Diffstat (limited to 'gcc/ada/a-synbar.adb')
0 files changed, 0 insertions, 0 deletions