public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases
@ 2021-09-10 23:24 ldalessandro at gmail dot com
  2021-09-11  0:16 ` [Bug c++/102286] " ldalessandro at gmail dot com
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: ldalessandro at gmail dot com @ 2021-09-10 23:24 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 102286
           Summary: [constexpr] construct_at incorrectly starts union
                    array lifetime in some cases
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ldalessandro at gmail dot com
  Target Milestone: ---

Given the following struct and union,

    struct Foo {
        constexpr explicit Foo(int) {}
    };

    union U {
        Foo data[1];
        constexpr U() {} // no active member
    };

In the function foo() below, assignment to u.data[0] correctly starts the
lifetime of the data array by https://eel.is/c++draft/class.union#general-6.

    constexpr void foo() {
        U u;
        u.data[0] = 0; // okay
    }

However in the function bar() below, &u.data[0] forms a reference before the
start of the lifetime of the data array and thus std::construct_at cannot be
used to start the lifetime of data.

    constexpr void bar() {
        U u;
        std::construct_at(&u.data[0], 0); // forms reference outside lifetime
    }

Currently gcc and msvc accept this invalid code, while clang and icc reject.

See the thread of discussion at
https://lists.isocpp.org/std-proposals/2021/09/3171.php and a live example at
https://godbolt.org/z/Poh6bb5de.

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

* [Bug c++/102286] [constexpr] construct_at incorrectly starts union array lifetime in some cases
  2021-09-10 23:24 [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases ldalessandro at gmail dot com
@ 2021-09-11  0:16 ` ldalessandro at gmail dot com
  2021-09-11  2:49 ` ldalessandro at gmail dot com
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ldalessandro at gmail dot com @ 2021-09-11  0:16 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Luke Dalessandro <ldalessandro at gmail dot com> ---
Oops, slightly reduced testcase, don't think the struct is necessary (just part
of my RL code).

    union U {
        int data[1];
        constexpr U() {} // no active member
    };

    constexpr bool bar() {
        U u;
        std::construct_at(&u.data[0], 0); // (1)
        return true;
    }

Per https://eel.is/c++draft/class.union#general-6, only assignment can start
the data array lifetime at (1). https://godbolt.org/z/6vfY6fT3d

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

* [Bug c++/102286] [constexpr] construct_at incorrectly starts union array lifetime in some cases
  2021-09-10 23:24 [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases ldalessandro at gmail dot com
  2021-09-11  0:16 ` [Bug c++/102286] " ldalessandro at gmail dot com
@ 2021-09-11  2:49 ` ldalessandro at gmail dot com
  2021-11-17 12:06 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ldalessandro at gmail dot com @ 2021-09-11  2:49 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Luke Dalessandro <ldalessandro at gmail dot com> ---
Okay, one last simplification for posterity.

    constexpr void bar() {
        union {
            int data[1];
        } u;
        std::construct_at(u.data, 0);
    }

https://godbolt.org/z/r4M3voh6W

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

* [Bug c++/102286] [constexpr] construct_at incorrectly starts union array lifetime in some cases
  2021-09-10 23:24 [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases ldalessandro at gmail dot com
  2021-09-11  0:16 ` [Bug c++/102286] " ldalessandro at gmail dot com
  2021-09-11  2:49 ` ldalessandro at gmail dot com
@ 2021-11-17 12:06 ` redi at gcc dot gnu.org
  2021-11-17 12:09 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2021-11-17 12:06 UTC (permalink / raw)
  To: gcc-bugs

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=98637
             Blocks|                            |55004
   Last reconfirmed|                            |2021-11-17
     Ever confirmed|0                           |1


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55004
[Bug 55004] [meta-bug] constexpr issues

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

* [Bug c++/102286] [constexpr] construct_at incorrectly starts union array lifetime in some cases
  2021-09-10 23:24 [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases ldalessandro at gmail dot com
                   ` (2 preceding siblings ...)
  2021-11-17 12:06 ` redi at gcc dot gnu.org
@ 2021-11-17 12:09 ` redi at gcc dot gnu.org
  2022-02-18 13:43 ` gcc at ebasoft dot com.pl
  2023-10-20  3:26 ` cvs-commit at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2021-11-17 12:09 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
This code from PR 103295 is kinda related, which GCC, EDG and MSVC all accept,
but Clang doesn't:

struct S
{
  union {
    char buf[8];
    char* ptr;
  };
  unsigned len;

  constexpr S(const char* s, unsigned n)
  {
    char* p;
    if (n > 7)
      p = ptr = new char[n];
    else
      p = buf;
    for (len = 0; len < n; ++len)
      p[len] = s[len];
    p[len] = '\0';
  }

  constexpr ~S()
  {
    if (len > 7)
      delete[] ptr;
  }
};

constexpr bool test()
{
  S s("test", 4);
  return true;
}

static_assert( test() );



In the constructor, buf[len] starts the lifetime of the union member, but
p[len] does not.

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

* [Bug c++/102286] [constexpr] construct_at incorrectly starts union array lifetime in some cases
  2021-09-10 23:24 [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases ldalessandro at gmail dot com
                   ` (3 preceding siblings ...)
  2021-11-17 12:09 ` redi at gcc dot gnu.org
@ 2022-02-18 13:43 ` gcc at ebasoft dot com.pl
  2023-10-20  3:26 ` cvs-commit at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: gcc at ebasoft dot com.pl @ 2022-02-18 13:43 UTC (permalink / raw)
  To: gcc-bugs

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

Artur Bać <gcc at ebasoft dot com.pl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |gcc at ebasoft dot com.pl

--- Comment #4 from Artur Bać <gcc at ebasoft dot com.pl> ---
This is not legal in c++20 but gcc allows accessing not active member of a
union in constexpr

https://godbolt.org/z/KsEhffeEa

clang refuses and it is right

"construction of subobject of member 'object' of union with active member
'init' is not allowed in a constant expression"
With c++20 there is no way to have aligned_storage for not trivial type in
constexpr (storage without initialization, not std::array that requires
construction of non trivial objects upon member activation)

https://godbolt.org/z/9EGrf8fbr

#include <memory>

    struct foo
        {
        int * i;
        constexpr foo() { i = new int; }
        constexpr ~foo() { delete(i); }
        };
    union storage
    {
      constexpr storage() 
          : init{}
      {}
      constexpr ~storage() {}

      foo object[1];
      char init = '\0';
      };

consteval bool test()
    {
    storage u;
    auto p = std::addressof(u.object[0]);
    std::construct_at<foo>(p);
    std::destroy_at(p);
    return true;
    }

int main()
{ 
    static_assert( test() );
    return test();
}

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

* [Bug c++/102286] [constexpr] construct_at incorrectly starts union array lifetime in some cases
  2021-09-10 23:24 [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases ldalessandro at gmail dot com
                   ` (4 preceding siblings ...)
  2022-02-18 13:43 ` gcc at ebasoft dot com.pl
@ 2023-10-20  3:26 ` cvs-commit at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2023-10-20  3:26 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:1d260ab0e39ea63644e3af3ab2e0db946026b5a6

commit r14-4771-g1d260ab0e39ea63644e3af3ab2e0db946026b5a6
Author: Nathaniel Shead <nathanieloshead@gmail.com>
Date:   Thu Oct 12 19:53:55 2023 +1100

    c++: indirect change of active union member in constexpr
[PR101631,PR102286]

    This patch adds checks for attempting to change the active member of a
    union by methods other than a member access expression.

    To be able to properly distinguish `*(&u.a) = ` from `u.a = `, this
    patch redoes the solution for c++/59950 to avoid extranneous *&; it
    seems that the only case that needed the workaround was when copying
    empty classes.

    This patch also ensures that constructors for a union field mark that
    field as the active member before entering the call itself; this ensures
    that modifications of the field within the constructor's body don't
    cause false positives (as these will not appear to be member access
    expressions). This means that we no longer need to start the lifetime of
    empty union members after the constructor body completes.

    As a drive-by fix, this patch also ensures that value-initialised unions
    are considered to have activated their initial member for the purpose of
    checking stores and accesses, which catches some additional mistakes
    pre-C++20.

            PR c++/101631
            PR c++/102286

    gcc/cp/ChangeLog:

            * call.cc (build_over_call): Fold more indirect refs for trivial
            assignment op.
            * class.cc (type_has_non_deleted_trivial_default_ctor): Create.
            * constexpr.cc (cxx_eval_call_expression): Start lifetime of
            union member before entering constructor.
            (cxx_eval_component_reference): Check against first member of
            value-initialised union.
            (cxx_eval_store_expression): Activate member for
            value-initialised union. Check for accessing inactive union
            member indirectly.
            * cp-tree.h (type_has_non_deleted_trivial_default_ctor):
            Forward declare.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp1y/constexpr-89336-3.C: Fix union initialisation.
            * g++.dg/cpp1y/constexpr-union6.C: New test.
            * g++.dg/cpp1y/constexpr-union7.C: New test.
            * g++.dg/cpp2a/constexpr-union2.C: New test.
            * g++.dg/cpp2a/constexpr-union3.C: New test.
            * g++.dg/cpp2a/constexpr-union4.C: New test.
            * g++.dg/cpp2a/constexpr-union5.C: New test.
            * g++.dg/cpp2a/constexpr-union6.C: New test.

    Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
    Reviewed-by: Jason Merrill <jason@redhat.com>

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

end of thread, other threads:[~2023-10-20  3:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-10 23:24 [Bug c++/102286] New: [constexpr] construct_at incorrectly starts union array lifetime in some cases ldalessandro at gmail dot com
2021-09-11  0:16 ` [Bug c++/102286] " ldalessandro at gmail dot com
2021-09-11  2:49 ` ldalessandro at gmail dot com
2021-11-17 12:06 ` redi at gcc dot gnu.org
2021-11-17 12:09 ` redi at gcc dot gnu.org
2022-02-18 13:43 ` gcc at ebasoft dot com.pl
2023-10-20  3:26 ` cvs-commit 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).