The -Wmaybe-uninitialized enhancement to warn when the address of an uninitialized object is passed to a function taking a const pointer (or, in C++, a const reference) tries to avoid triggering when the address is that of an empty object. It does that by checking EMPTY_TYPE_P() and default_is_empty_record() for structs. As it turns out, neither of these is reliable for this purpose (both are subject to ABI constraints).
The attached patch replaces these tests by one for is_empty_type(), the workhorse function behind default_is_empty_record(). Besides bootstrapping and regtesting on x86_64-linux I've tested the patch works to suppress the warning with an aarch64-gnu-linux cross (where the bogus warning was reported). Martin
PR middle-end/97840 - Bogus -Wmaybe-uninitialized passing an empty object to a function gcc/ChangeLog: * tree-ssa-uninit.c (maybe_warn_operand): Call is_empty_type. * tree.c (default_is_empty_type): Rename... (is_empty_type): ...to this. * tree.h (is_empty_type): Declare. diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index c94831bfb75..516a7bd2c99 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -404,10 +404,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, tree rhstype = TREE_TYPE (rhs); if (POINTER_TYPE_P (rhstype)) rhstype = TREE_TYPE (rhstype); - if (TYPE_EMPTY_P (rhstype) - || (RECORD_OR_UNION_TYPE_P (rhstype) - && (!first_field (rhstype) - || default_is_empty_record (rhstype)))) + if (is_empty_type (rhstype)) return NULL_TREE; bool warned = false; diff --git a/gcc/tree.c b/gcc/tree.c index 1ad4ad5a5f7..0fe9097bbbc 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -15136,22 +15136,22 @@ get_nonnull_args (const_tree fntype) /* Returns true if TYPE is a type where it and all of its subobjects (recursively) are of structure, union, or array type. */ -static bool -default_is_empty_type (tree type) +bool +is_empty_type (const_tree type) { if (RECORD_OR_UNION_TYPE_P (type)) { for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && !DECL_PADDING_P (field) - && !default_is_empty_type (TREE_TYPE (field))) + && !is_empty_type (TREE_TYPE (field))) return false; return true; } else if (TREE_CODE (type) == ARRAY_TYPE) return (integer_minus_onep (array_type_nelts (type)) || TYPE_DOMAIN (type) == NULL_TREE - || default_is_empty_type (TREE_TYPE (type))); + || is_empty_type (TREE_TYPE (type))); return false; } @@ -15170,7 +15170,7 @@ default_is_empty_record (const_tree type) if (TREE_ADDRESSABLE (type)) return false; - return default_is_empty_type (TYPE_MAIN_VARIANT (type)); + return is_empty_type (TYPE_MAIN_VARIANT (type)); } /* Determine whether TYPE is a structure with a flexible array member, diff --git a/gcc/tree.h b/gcc/tree.h index 9a713cdb0c7..5c0e3cc2e5a 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -6233,6 +6233,7 @@ extern void gt_pch_nx (tree &); extern void gt_pch_nx (tree &, gt_pointer_operator, void *); extern bool nonnull_arg_p (const_tree); +extern bool is_empty_type (const_tree); extern bool default_is_empty_record (const_tree); extern bool flexible_array_type_p (const_tree); extern HOST_WIDE_INT arg_int_size_in_bytes (const_tree);