https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114536
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jakub at gcc dot gnu.org,
| |jason at gcc dot gnu.org,
| |redi at gcc dot gnu.org
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Adjusted testcase:
namespace std {
template<typename T, typename F>
constexpr T
bit_cast (const F& f) noexcept
{
return __builtin_bit_cast (T, f);
}
}
struct A { unsigned char a : 7; };
struct B { unsigned char b; };
constexpr unsigned char c = __builtin_bit_cast (B, A{1}).b;
constexpr unsigned char d = std::bit_cast <B> (A{1}).b;
This shows that we diagnose correctly the c case:
pr114536.C:12:58: error: accessing uninitialized member ‘B::b’
12 | constexpr unsigned char c = __builtin_bit_cast (B, A{1}).b;
| ~~~~~~~~~^
but don't diagnose when the builtin call is wrapped in another call
(std::bit_cast).
The reason for that is:
/* The result of a constexpr function must be completely initialized.
However, in C++20, a constexpr constructor doesn't necessarily have
to initialize all the fields, so we don't clear CONSTRUCTOR_NO_CLEARING
in order to detect reading an unitialized object in constexpr instead
of value-initializing it. (reduced_constant_expression_p is expected to
take care of clearing the flag.) */
if (TREE_CODE (result) == CONSTRUCTOR
&& (cxx_dialect < cxx20
|| !DECL_CONSTRUCTOR_P (fun)))
clear_no_implicit_zero (result);
hunk in cxx_eval_call_expression.
This is done there since PR80829 for the nested CONSTRUCTOR_NO_CLEARING, and on
the outermost since r7-4090-gf64e0c029c452c9fc508adebf18d0ceb3ffdc066.
If it is UB to return not completely initialized aggregate, shouldn't
clear_no_implicit_zero actually diagnose it if CONSTRUCTOR_NO_CLEARING is set
and not all ctor elements are initialized?