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).