public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements
@ 2021-09-18 16:25 krax.powah at gmail dot com
  2021-09-18 16:33 ` [Bug c++/102401] " jakub at gcc dot gnu.org
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: krax.powah at gmail dot com @ 2021-09-18 16:25 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 102401
           Summary: std::bit_cast falls over, seemingly due to some
                    invisible alignment requirements
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: krax.powah at gmail dot com
  Target Milestone: ---

GCC Version: The current truck (12.0.0 20210917), but also present on all
versions which support std::bit_cast.

Repro case (https://godbolt.org/z/zWbMnMfvx):

```
    #include <bit>

    struct Item
    {
        float a = 0;
        float b = 0;
        char  c = 0;  // Removing this or changing it to type with a size of 4
    };                // fixes it.

    struct M
    {
        struct Data { char d[sizeof(Item)]; };
        static constexpr Data build(Item item)
        {
            Data d {};
            d = std::bit_cast<Data>(item);
            return d;
        }
    };

    int main(void)
    {
        constexpr auto data = M::build({}); // Only occurs if this is a
constexpr assignment
    }
```

Result:

```
    In file included from <source>:1:
    /opt/compiler-explorer/gcc-trunk-20210917/include/c++/12.0.0/bit: In
function 'int main()':
    <source>:26:35:   in 'constexpr' expansion of 'M::build(Item{(float)0,
(float)0, '\000'})'
    <source>:18:32:   in 'constexpr' expansion of 'std::bit_cast<M::Data,
Item>(item)'
    /opt/compiler-explorer/gcc-trunk-20210917/include/c++/12.0.0/bit:77:33:
error: '__builtin_bit_cast' accessing uninitialized byte at offset 9
       77 |       return __builtin_bit_cast(_To, __from);
          |                                 ^~~
    ASM generation compiler returned: 1
    In file included from <source>:1:
    /opt/compiler-explorer/gcc-trunk-20210917/include/c++/12.0.0/bit: In
function 'int main()':
    <source>:26:35:   in 'constexpr' expansion of 'M::build(Item{(float)0,
(float)0, '\000'})'
    <source>:18:32:   in 'constexpr' expansion of 'std::bit_cast<M::Data,
Item>(item)'
    /opt/compiler-explorer/gcc-trunk-20210917/include/c++/12.0.0/bit:77:33:
error: '__builtin_bit_cast' accessing uninitialized byte at offset 9
       77 |       return __builtin_bit_cast(_To, __from);
          |                                 ^~~
    Execution build compiler returned: 1
```

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102401] std::bit_cast falls over, seemingly due to some invisible alignment requirements
  2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
@ 2021-09-18 16:33 ` jakub at gcc dot gnu.org
  2021-09-18 18:47 ` pinskia at gcc dot gnu.org
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: jakub at gcc dot gnu.org @ 2021-09-18 16:33 UTC (permalink / raw)
  To: gcc-bugs

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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Why do you think GCC is not right?
The Item class has 3 bytes of padding, and the Data class doesn't have any.
So, when evaluated at runtime, it would be a UB, while during constant
evaluation it has to be an error.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102401] std::bit_cast falls over, seemingly due to some invisible alignment requirements
  2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
  2021-09-18 16:33 ` [Bug c++/102401] " jakub at gcc dot gnu.org
@ 2021-09-18 18:47 ` pinskia at gcc dot gnu.org
  2021-09-18 18:55 ` jakub at gcc dot gnu.org
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-09-18 18:47 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Yes this is the way the C++ standard is defined.  Even clang rejects it.  I
would have thought __builtin_clear_padding could be used in constexpr but I was
wrong.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102401] std::bit_cast falls over, seemingly due to some invisible alignment requirements
  2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
  2021-09-18 16:33 ` [Bug c++/102401] " jakub at gcc dot gnu.org
  2021-09-18 18:47 ` pinskia at gcc dot gnu.org
@ 2021-09-18 18:55 ` jakub at gcc dot gnu.org
  2021-09-18 22:23 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: jakub at gcc dot gnu.org @ 2021-09-18 18:55 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
There are things that need to be clarified, in particular value initialization
should clear even the padding bits, so supposedly std::bit_cast of Item() if
the NSDMIs would be dropped might be well defined and ok in constexpr contexts
(we don't implement that currently, and don't implement it even at runtime, we
treat padding bits as always undefined), but the above testcase has a user
defined constructor and therefore no zero initialization happens, and even if
it wouldn't, any copying around (both copy construction and assignments) will
make those bits undefined as well.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102401] std::bit_cast falls over, seemingly due to some invisible alignment requirements
  2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
                   ` (2 preceding siblings ...)
  2021-09-18 18:55 ` jakub at gcc dot gnu.org
@ 2021-09-18 22:23 ` redi at gcc dot gnu.org
  2021-09-20  9:15 ` jakub at gcc dot gnu.org
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2021-09-18 22:23 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #3)
> There are things that need to be clarified, in particular value
> initialization should clear even the padding bits, so supposedly
> std::bit_cast of Item() if the NSDMIs would be dropped might be well defined
> and ok in constexpr contexts (we don't implement that currently, and don't
> implement it even at runtime, we treat padding bits as always undefined),

I think that's a bug.

> but the above testcase has a user defined constructor and therefore no zero

No it doesn't.

It has no constructor that is user-declared, so a default constructor is
implicitly defined as defaulted. That default constructor is non-trivial
(because of the default member-initializers) but it's still implicitly defined.

List-initialization with an empty init list means value-initialization. Since
there is no user-provided default constructor, that means:

"the object is zero-initialized and the semantic constraints for
default-initialization are checked, and if T has a non-trivial default
constructor, the object is default-initialized;"

So it should be zero-initialized (which zeroes all padding) and then it should
be default-initialized (which uses the implicitly-defined default constructor,
which uses the NSDMIs).

So the padding bits should be initialized, no?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102401] std::bit_cast falls over, seemingly due to some invisible alignment requirements
  2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
                   ` (3 preceding siblings ...)
  2021-09-18 22:23 ` redi at gcc dot gnu.org
@ 2021-09-20  9:15 ` jakub at gcc dot gnu.org
  2021-09-20  9:41 ` redi at gcc dot gnu.org
  2022-01-12 20:08 ` jakub at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: jakub at gcc dot gnu.org @ 2021-09-20  9:15 UTC (permalink / raw)
  To: gcc-bugs

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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|INVALID                     |---
   Last reconfirmed|                            |2021-09-20
     Ever confirmed|0                           |1
             Status|RESOLVED                    |REOPENED

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
We need to fix PR78620 first.
I think one thing is adding some CONSTRUCTOR_ZERO_PADDING flag on CONSTRUCTORs
(meaning that padding is zero initialized), propagate it through the FE and
handle in constexpr there and handle that during gimplification, either by
__builtin_clear_padding or pre-zeroing the whole memory (TREE_STATIC vars don't
need that of course).
And then there is a question if we don't need further middle-end changes,
because a mere struct assignment in the GIMPLE IL doesn't guarantee copying of
the padding bits.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102401] std::bit_cast falls over, seemingly due to some invisible alignment requirements
  2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
                   ` (4 preceding siblings ...)
  2021-09-20  9:15 ` jakub at gcc dot gnu.org
@ 2021-09-20  9:41 ` redi at gcc dot gnu.org
  2022-01-12 20:08 ` jakub at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2021-09-20  9:41 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Depends on|                            |78620

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
std::bit_cast says the padding bits have unspecified values, so we don't
necessarily need to copy them. We just can't reject them for being
uninitialized.


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78620
[Bug 78620] C++11, Padding bytes not zero-intialized when POD is initialized
with compiler generated default constructor

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug c++/102401] std::bit_cast falls over, seemingly due to some invisible alignment requirements
  2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
                   ` (5 preceding siblings ...)
  2021-09-20  9:41 ` redi at gcc dot gnu.org
@ 2022-01-12 20:08 ` jakub at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: jakub at gcc dot gnu.org @ 2022-01-12 20:08 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Note, since r12-5789-gc57c910c945ac68ba9a7cda9b0f963173781d58c
GCC implements https://wg21.link/P1272 which clarifies that the #c0 testcase is
invalid.
With unsigned char or std::byte instead of char in Data definition actually
doing std::bit_cast<Data>(item) would be well defined, but not the copying
of those bytes to d.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-01-12 20:08 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-18 16:25 [Bug c++/102401] New: std::bit_cast falls over, seemingly due to some invisible alignment requirements krax.powah at gmail dot com
2021-09-18 16:33 ` [Bug c++/102401] " jakub at gcc dot gnu.org
2021-09-18 18:47 ` pinskia at gcc dot gnu.org
2021-09-18 18:55 ` jakub at gcc dot gnu.org
2021-09-18 22:23 ` redi at gcc dot gnu.org
2021-09-20  9:15 ` jakub at gcc dot gnu.org
2021-09-20  9:41 ` redi at gcc dot gnu.org
2022-01-12 20:08 ` jakub at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).