https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91292

--- Comment #6 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Patrick Palka <ppa...@gcc.gnu.org>:

https://gcc.gnu.org/g:34947d4e97ee72b26491cfe5ff4fa8258fadbe95

commit r12-3882-g34947d4e97ee72b26491cfe5ff4fa8258fadbe95
Author: Patrick Palka <ppa...@redhat.com>
Date:   Fri Sep 24 12:36:26 2021 -0400

    real: fix encoding of negative IEEE double/quad values [PR98216]

    In encode_ieee_double/quad, the assignment

      unsigned long WORD = r->sign << 31;

    is intended to set the 31st bit of WORD whenever the sign bit is set.
    But on LP64 hosts it also unintentionally sets the upper 32 bits of WORD,
    because r->sign gets promoted from unsigned:1 to int and then the result
    of the shift (equal to INT_MIN) gets sign extended from int to long.

    In the C++ frontend, this bug causes incorrect mangling of negative
    floating point values because the output of real_to_target called from
    write_real_cst unexpectedly has the upper 32 bits of this word set,
    which the caller doesn't mask out.

    This patch fixes this by avoiding the unwanted sign extension.  Note
    that r0-53976 fixed the same bug in encode_ieee_single long ago.

            PR c++/98216
            PR c++/91292

    gcc/ChangeLog:

            * real.c (encode_ieee_double): Avoid unwanted sign extension.
            (encode_ieee_quad): Likewise.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp2a/nontype-float2.C: New test.

Reply via email to