diff options
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index ca4d3e2..a4b8b00 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -5540,6 +5540,68 @@ maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc) return false; } +/* Given an initializer INIT for a TYPE, return true if INIT is zero + so that it can be replaced by value initialization. This function + distinguishes betwen empty strings as initializers for arrays and + for pointers (which make it return false). */ + +bool +type_initializer_zero_p (tree type, tree init) +{ + if (type == error_mark_node || init == error_mark_node) + return false; + + STRIP_NOPS (init); + + if (POINTER_TYPE_P (type)) + return TREE_CODE (init) != STRING_CST && initializer_zerop (init); + + if (TREE_CODE (init) != CONSTRUCTOR) + return initializer_zerop (init); + + if (TREE_CODE (type) == ARRAY_TYPE) + { + tree elt_type = TREE_TYPE (type); + elt_type = TYPE_MAIN_VARIANT (elt_type); + if (elt_type == char_type_node) + return initializer_zerop (init); + + tree elt_init; + unsigned HOST_WIDE_INT i; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init) + if (!type_initializer_zero_p (elt_type, elt_init)) + return false; + return true; + } + + if (TREE_CODE (type) != RECORD_TYPE) + return initializer_zerop (init); + + if (TYPE_NON_AGGREGATE_CLASS (type)) + return false; + + tree fld = TYPE_FIELDS (type); + + tree fld_init; + unsigned HOST_WIDE_INT i; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init) + { + fld = next_initializable_field (fld); + if (!fld) + return true; + + tree fldtype = TREE_TYPE (fld); + if (!type_initializer_zero_p (fldtype, fld_init)) + return false; + + fld = DECL_CHAIN (fld); + if (!fld) + break; + } + + return true; +} + #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) /* Complain that some language-specific thing hanging off a tree node has been accessed improperly. */ |