[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #19 from Carlos Galvez --- I can confirm that recent versions of trunk fixed the problem described in this thread, thank you so much! > Sounds like another regression? I need to run more tests to confirm. It is a very huge file, it could simply be that we were close to the limits of the machine and now GCC does slightly more work and goes over the threshold. Anyhow, off-topic for this issue, I'll open a separate one if needed!
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #18 from Patrick Palka --- (In reply to Carlos Galvez from comment #17) > (FYI I'm trying to test this but now I get out-of-memory errors when trying > to compile a single .cpp file, will test with a newer patch in case it got > fixed) Sounds like another regression? Please open a new PR if anything :)
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #17 from Carlos Galvez --- (FYI I'm trying to test this but now I get out-of-memory errors when trying to compile a single .cpp file, will test with a newer patch in case it got fixed)
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #16 from GCC Commits --- The trunk branch has been updated by Marek Polacek : https://gcc.gnu.org/g:cb828691fe692f9df002a2e3757a1aec68857e85 commit r15-7127-gcb828691fe692f9df002a2e3757a1aec68857e85 Author: Marek Polacek Date: Tue Jan 21 14:48:46 2025 -0500 c++: further tweak to cxx_eval_outermost_constant_expr [PR118396] This patch adds an error in a !allow_non_constant case when the initializer/object types don't match. PR c++/118396 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_outermost_constant_expr): Add an error call when !allow_non_constant. Reviewed-by: Jason Merrill
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #15 from Carlos Galvez --- Thank you for the quick fix! I'll test it right away :)
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 Marek Polacek changed: What|Removed |Added Resolution|--- |FIXED Status|ASSIGNED|RESOLVED --- Comment #14 from Marek Polacek --- Should be fixed.
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #13 from GCC Commits --- The trunk branch has been updated by Marek Polacek : https://gcc.gnu.org/g:f3f02493dfa8858c3fb2bc0da0d6d7320921408a commit r15-7103-gf3f02493dfa8858c3fb2bc0da0d6d7320921408a Author: Marek Polacek Date: Thu Jan 16 11:22:59 2025 -0500 c++: fix wrong-code with constexpr prvalue opt [PR118396] The recent r15-6369 unfortunately caused a bad wrong-code issue. Here we have TARGET_EXPR and call cp_fold_r -> maybe_constant_init with object=D.2996. In cxx_eval_outermost_constant_expr we now take the type of the object if present. An object can't have type 'void' and so we continue to evaluate the initializer. That evaluates into a VOID_CST, meaning we disregard the whole initializer, and terrible things ensue. For non-simple TARGET_EXPRs, we should return ctx.ctor rather than the result of cxx_eval_constant_expression. PR c++/118396 PR c++/118523 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_outermost_constant_expr): For non-simple TARGET_EXPRs, return ctx.ctor rather than the result of cxx_eval_constant_expression. If TYPE and the type of R don't match, return the original expression. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-prvalue4.C: New test. * g++.dg/cpp1y/constexpr-prvalue3.C: New test. Reviewed-by: Jason Merrill
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396
--- Comment #12 from Marek Polacek ---
So I think I'll test this:
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8871,9 +8871,17 @@ cxx_eval_outermost_constant_expr (tree t, bool
allow_non_constant,
/* Turn off -frounding-math for manifestly constant evaluation. */
warning_sentinel rm (flag_rounding_math,
ctx.manifestly_const_eval == mce_true);
- tree type = (object
- ? cv_unqualified (TREE_TYPE (object))
- : initialized_type (t));
+ tree type;
+ if (object)
+{
+ type = cv_unqualified (TREE_TYPE (object));
+ /* If there is an object to initialize, make sure we don't throw
+away the initializer. */
+ gcc_assert (!VOID_TYPE_P (initialized_type (t)) || constexpr_dtor);
+}
+ else
+type = initialized_type (t);
+
tree r = t;
bool is_consteval = false;
if (VOID_TYPE_P (type))
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index c7074b00cef..283c0fa3e26 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1475,7 +1475,9 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
cp_walk_tree (&init, cp_fold_r, data, NULL);
cp_walk_tree (&TARGET_EXPR_CLEANUP (stmt), cp_fold_r, data, NULL);
*walk_subtrees = 0;
- if (!flag_no_inline)
+ /* Only attempt to evaluate the initializer if we're inlining and
+the TARGET_EXPR is simple. */
+ if (!flag_no_inline && !VOID_TYPE_P (TREE_TYPE (init)))
{
tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt));
if (folded != init && TREE_CONSTANT (folded))
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396
Marek Polacek changed:
What|Removed |Added
CC||jason at gcc dot gnu.org
--- Comment #11 from Marek Polacek ---
One idea would be to only fold simple TARGET_EXPR's initializer:
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1475,7 +1475,7 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
cp_walk_tree (&init, cp_fold_r, data, NULL);
cp_walk_tree (&TARGET_EXPR_CLEANUP (stmt), cp_fold_r, data, NULL);
*walk_subtrees = 0;
- if (!flag_no_inline)
+ if (!flag_no_inline && !VOID_TYPE_P (TREE_TYPE (init)))
{
tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt));
if (folded != init && TREE_CONSTANT (folded))
but maybe we also need an assert in cxx_eval_outermost_constant_expr checking
that if there's an object, we don't fold away all the initializing bits?
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #10 from Marek Polacek --- We have: TARGET_EXPR so object=D.2996 whose type is Data, so we do not go down the VOID_TYPE_P path in cxx_eval_outermost_constant_expr, and evaluate the whole init to VOID_CST. Obviously, that should not happen. I'm not sure why we create TARGET_EXPRs that look like this.
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #9 from Marek Polacek --- This difference seems to be the problem: -vector::vector (&items_, (const struct Data &) &TARGET_EXPR >>>) >; +vector::vector (&items_, (const struct Data &) &TARGET_EXPR ) >;
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #8 from Andrew Pinski --- Created attachment 60165 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60165&action=edit Fixed up removing hard coded size_t, use __SIZE_TYPE__ instead and removed __assert_failure Just some small changes to the testcase in comment #7 fixing up a few x86_64 linux-isms.
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396
--- Comment #7 from Marek Polacek ---
// PR c++/118396
extern "C" void __assert_fail(const char *, const char *);
void *operator new(unsigned long, void *__p) { return __p; }
struct Foo {
virtual ~Foo() = default;
};
struct Data {
int status;
Foo data{};
};
Data *P, *Q;
struct vector {
vector (const Data &__value) {
P = static_cast(__builtin_operator_new(0));
new (P) Data (__value);
Q = P + 1;
}
Data *begin() { return P; }
Data *end() { return Q; }
};
int
main ()
{
vector items_(Data{});
for (auto item : items_)
item.status == 0 ? void() : __assert_fail("oy", "118396.C");
}
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396
--- Comment #6 from Marek Polacek ---
Somewhat reduced but it's still ugly:
```
extern "C" void __assert_fail(const char *, const char *);
struct Data;
void *operator new(unsigned long, void *__p) { return __p; }
template struct __new_allocator {
Data *allocate(long __n) {
return static_cast(__builtin_operator_new(__n));
}
template
void construct(_Up *__p, _Args... __args) {
new (__p) _Up(__args...);
}
};
template struct allocator_traits;
template using rebind_alloc = __new_allocator<_Up>;
template struct allocator_traits<__new_allocator<_Tp>> {
using allocator_type = __new_allocator<_Tp>;
using pointer = _Tp *;
static pointer allocate() {
allocator_type __a;
return __a.allocate(0);
}
template
static void construct(allocator_type __a, _Up __p, _Args... __args) {
__a.construct(__p, __args...);
}
};
struct __alloc_traits : allocator_traits<__new_allocator> {};
template
_ForwardIterator __uninitialized_fill_n_a(_ForwardIterator __first, long __n,
const Data &__x,
__new_allocator __alloc) {
for (; __n; --__n, ++__first) {
Data *__trans_tmp_1(__first);
__alloc_traits::construct(__alloc, __trans_tmp_1, __x);
}
return __first;
}
typedef __alloc_traits::pointer pointer;
pointer P, _M_impl_1;
struct _Vector_base {
_Vector_base(long __n) {
P = __alloc_traits::allocate();
}
};
struct vector : _Vector_base {
vector(long __n, const Data &__value) : _Vector_base(__n) {
long __trans_tmp_4 = __n;
rebind_alloc __trans_tmp_2;
_M_impl_1 = __uninitialized_fill_n_a(P,
__trans_tmp_4, __value,
__trans_tmp_2);
}
pointer begin() { return P; }
pointer end() { return _M_impl_1; }
};
struct Foo {
virtual ~Foo() = default;
};
struct Data {
int status;
Foo data{};
};
int kValue;
struct Vector : vector {
Vector(long size) : vector(size, Data{}) {}
};
int main() {
Vector items_(10);
for (auto item : items_)
item.status == kValue ? void() : __assert_fail("", __builtin_FILE());
}
```
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #5 from Sam James --- *** Bug 118475 has been marked as a duplicate of this bug. ***
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #4 from Sam James --- Testing trunk regularly is more than enough ;)
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 --- Comment #3 from Carlos Galvez --- Thanks for the quick confirmation! Let me know if I can be of help.
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present since r15-6369-gfa99002538bc91
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 Marek Polacek changed: What|Removed |Added Priority|P3 |P1 Assignee|unassigned at gcc dot gnu.org |mpolacek at gcc dot gnu.org Status|NEW |ASSIGNED --- Comment #2 from Marek Polacek --- Oy. Mine then.
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 Patrick Palka changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2025-01-10 CC||mpolacek at gcc dot gnu.org, ||ppalka at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Patrick Palka --- Confirmed, seems to have started with r15-6369-gfa99002538bc91 "c++: ICE in TARGET_EXPR evaluation in cp_fold_r [PR117980]".
[Bug c++/118396] [15 regression] -O1+ leads to reading uninitialized data when virtual destructor is present
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118396 Sam James changed: What|Removed |Added Target Milestone|--- |15.0 Summary|Regression: -O1+ leads to |[15 regression] -O1+ leads |reading uninitialized data |to reading uninitialized |when virtual destructor is |data when virtual |present |destructor is present Keywords||wrong-code
