diff options
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index dd76891..a333170 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -138,6 +138,7 @@ static bool same_discriminant_p (Entity_Id, Entity_Id); static bool array_type_has_nonaliased_component (tree, Entity_Id); static bool compile_time_known_address_p (Node_Id); static bool cannot_be_superflat_p (Node_Id); +static bool constructor_address_p (tree); static void components_to_record (tree, Node_Id, tree, int, bool, tree *, bool, bool, bool, bool, bool); static Uint annotate_value (tree); @@ -1376,6 +1377,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) DECL_IGNORED_P (gnu_decl) = 1; } + /* If this is a constant, even if we don't need a true variable, we + may need to avoid returning the initializer in every case. That + can happen for the address of a (constant) constructor because, + upon dereferencing it, the constructor will be reinjected in the + tree, which may not be valid in every case; see lvalue_required_p + for more details. */ + if (TREE_CODE (gnu_decl) == CONST_DECL) + DECL_CONST_ADDRESS_P (gnu_decl) = constructor_address_p (gnu_expr); + /* If this is declared in a block that contains a block with an exception handler, we must force this variable in memory to suppress an invalid optimization. */ @@ -2892,10 +2902,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) false, all_rep, is_unchecked_union, debug_info_p, false); - /* If it is a tagged record force the type to BLKmode to insure that - these objects will always be put in memory. Likewise for limited - record types. */ - if (Is_Tagged_Type (gnat_entity) || Is_Limited_Record (gnat_entity)) + /* If it is passed by reference, force BLKmode to ensure that objects ++ of this type will always be put in memory. */ + if (Is_By_Reference_Type (gnat_entity)) SET_TYPE_MODE (gnu_type, BLKmode); /* We used to remove the associations of the discriminants and _Parent @@ -3216,8 +3225,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) finish_record_type (gnu_type, gnu_field_list, 2, false); /* See the E_Record_Type case for the rationale. */ - if (Is_Tagged_Type (gnat_entity) - || Is_Limited_Record (gnat_entity)) + if (Is_By_Reference_Type (gnat_entity)) SET_TYPE_MODE (gnu_type, BLKmode); else compute_record_mode (gnu_type); @@ -4388,8 +4396,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) || Is_Class_Wide_Equivalent_Type (gnat_entity)) TYPE_ALIGN_OK (gnu_type) = 1; - if (AGGREGATE_TYPE_P (gnu_type) && Is_By_Reference_Type (gnat_entity)) - TYPE_BY_REFERENCE_P (gnu_type) = 1; + /* If the type is passed by reference, objects of this type must be + fully addressable and cannot be copied. */ + if (Is_By_Reference_Type (gnat_entity)) + TREE_ADDRESSABLE (gnu_type) = 1; /* ??? Don't set the size for a String_Literal since it is either confirming or we don't handle it properly (if the low bound is @@ -5397,6 +5407,20 @@ cannot_be_superflat_p (Node_Id gnat_range) return (tree_int_cst_lt (gnu_hb, gnu_lb) == 0); } + +/* Return true if GNU_EXPR is (essentially) the address of a CONSTRUCTOR. */ + +static bool +constructor_address_p (tree gnu_expr) +{ + while (TREE_CODE (gnu_expr) == NOP_EXPR + || TREE_CODE (gnu_expr) == CONVERT_EXPR + || TREE_CODE (gnu_expr) == NON_LVALUE_EXPR) + gnu_expr = TREE_OPERAND (gnu_expr, 0); + + return (TREE_CODE (gnu_expr) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (gnu_expr, 0)) == CONSTRUCTOR); +} /* Given GNAT_ENTITY, elaborate all expressions that are required to be elaborated at the point of its definition, but do nothing else. */ @@ -6033,10 +6057,7 @@ make_packable_type (tree type, bool in_record) !DECL_NONADDRESSABLE_P (old_field)); DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field); - SET_DECL_ORIGINAL_FIELD - (new_field, (DECL_ORIGINAL_FIELD (old_field) - ? DECL_ORIGINAL_FIELD (old_field) : old_field)); - + SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, old_field); if (TREE_CODE (new_type) == QUAL_UNION_TYPE) DECL_QUALIFIER (new_field) = DECL_QUALIFIER (old_field); @@ -7253,9 +7274,8 @@ annotate_object (Entity_Id gnat_entity, tree gnu_type, tree size, bool by_ref) UI_From_Int (TYPE_ALIGN (gnu_type) / BITS_PER_UNIT)); } -/* Return first element of field list whose TREE_PURPOSE is ELEM or whose - DECL_ORIGINAL_FIELD of TREE_PURPOSE is ELEM. Return NULL_TREE if there - is no such element in the list. */ +/* Return first element of field list whose TREE_PURPOSE is the same as ELEM. + Return NULL_TREE if there is no such element in the list. */ static tree purpose_member_field (const_tree elem, tree list) @@ -7263,7 +7283,7 @@ purpose_member_field (const_tree elem, tree list) while (list) { tree field = TREE_PURPOSE (list); - if (elem == field || elem == DECL_ORIGINAL_FIELD (field)) + if (SAME_FIELD_P (field, elem)) return list; list = TREE_CHAIN (list); } @@ -8035,8 +8055,7 @@ create_field_decl_from (tree old_field, tree field_type, tree record_type, } DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field); - t = DECL_ORIGINAL_FIELD (old_field); - SET_DECL_ORIGINAL_FIELD (new_field, t ? t : old_field); + SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, old_field); DECL_DISCRIMINANT_NUMBER (new_field) = DECL_DISCRIMINANT_NUMBER (old_field); TREE_THIS_VOLATILE (new_field) = TREE_THIS_VOLATILE (old_field); @@ -8372,9 +8391,7 @@ substitute_in_type (tree t, tree f, tree r) } DECL_CONTEXT (new_field) = nt; - SET_DECL_ORIGINAL_FIELD (new_field, - (DECL_ORIGINAL_FIELD (field) - ? DECL_ORIGINAL_FIELD (field) : field)); + SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, field); TREE_CHAIN (new_field) = TYPE_FIELDS (nt); TYPE_FIELDS (nt) = new_field; |