https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117322
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords| |missed-optimization
Status|UNCONFIRMED |NEW
Ever confirmed|0 |1
Priority|P3 |P2
Last reconfirmed| |2026-02-16
CC| |pinskia at gcc dot gnu.org
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
The diagnostic is emitted because *arr is uninitialized on the
if (nbytes <= 256*1024) {
arr = reinterpret_cast<T*>(alloca(nbytes));
path where
std::uninitialized_copy(data, data + len, arr);
decides to do nothing:
<bb 3> [local count: 59055800]:
arr_14 = __builtin_alloca (nbytes_8);
_32 = len_7(D) * 4;
_30 = data_15(D) + _32;
if (data_15(D) != _30)
goto <bb 30>; [89.00%]
else
goto <bb 8>; [11.00%]
(gdb) p debug_bb_n (8)
<bb 8> [local count: 6496138]:
f (arr_14, len_7(D));
aka, when 'len' (* 4) is zero. Now, we can only know that data + len * 4
does not wrap to zero because of POINTER_PLUS_EXPR making that UB, so
we should be able to fold
A p+ X != A
to X != 0 and len * 4 != 0 to len != 0 because of the guard bounding len
which means we could back-propagate the zero, knowing we allocated zero
bytes and thus there is nothing to initialize. But the code does not
concern itself with the size of the object at all at the moment.
I'll note that we do simplify comparisons liek this, but only through
fold-const.cc (and forwrpop), for the testcase at hand it likely appears
either too late or is somehow single-use restricted. We do not optimize
_Bool foo (int *p, unsigned n)
{
if (n > 10000)
return false;
int *q = p + n;
return (q != p);
}
all the way down to n != 0 though.
diff --git a/gcc/match.pd b/gcc/match.pd
index 8910591a04b..7cc16ac2fc3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2885,7 +2885,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(for op (eq ne)
(simplify
(op (pointer_plus @0 @1) (pointer_plus @0 @2))
- (op @1 @2)))
+ (op @1 @2))
+ (simplify
+ (op:c (pointer_plus @0 @1) @0)
+ (op @1 { build_zero_cst (TREE_TYPE (@1)); })))
(simplify
(pointer_diff (pointer_plus @0 @1) (pointer_plus @0 @2))
(if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
fixes part of it, but there's remains of fold_comparison that still seem
important and incomplete WRT range info.
In the end the diagnostic is a bit misleading,
<source>:29:4: warning: 'arr' may be used uninitialized [-Wmaybe-uninitialized]
should say
<source>:29:4: warning: '*arr' may be used uninitialized
[-Wmaybe-uninitialized]
or "storage at 'arr' may be used uninitialized" (though C++ and references
and/or array decay probably makes this a bit awkward to get correct).
The decision to diagnose uninitialized storage passed to a function
via const qualified reference is questionable, of course, but makes
sense in some context.