be a FIELD_DECL. Likewise for discriminants. If the entity is a
non-girder discriminant (in the case of derived untagged record
types), return the stored discriminant it renames. */
- else if (Present (Original_Record_Component (gnat_entity))
- && Original_Record_Component (gnat_entity) != gnat_entity)
+ if (Present (Original_Record_Component (gnat_entity))
+ && Original_Record_Component (gnat_entity) != gnat_entity)
{
gnu_decl
= gnat_to_gnu_entity (Original_Record_Component (gnat_entity),
/* Otherwise, if we are not defining this and we have no GCC type
for the containing record, make one for it. Then we should
have made our own equivalent. */
- else if (!definition && !present_gnu_tree (gnat_record))
+ if (!definition && !present_gnu_tree (gnat_record))
{
/* ??? If this is in a record whose scope is a protected
type and we have an Original_Record_Component, use it.
= gnat_to_gnu_entity (Original_Record_Component
(gnat_entity),
gnu_expr, false);
- saved = true;
- break;
+ }
+ else
+ {
+ gnat_to_gnu_entity (Scope (gnat_entity), NULL_TREE, false);
+ gnu_decl = get_gnu_tree (gnat_entity);
}
- gnat_to_gnu_entity (Scope (gnat_entity), NULL_TREE, false);
- gnu_decl = get_gnu_tree (gnat_entity);
saved = true;
break;
}
- else
- /* Here we have no GCC type and this is a reference rather than a
- definition. This should never happen. Most likely the cause is
- reference before declaration in the GNAT tree for gnat_entity. */
- gcc_unreachable ();
+ /* Here we have no GCC type and this is a reference rather than a
+ definition. This should never happen. Most likely the cause is
+ reference before declaration in the GNAT tree for gnat_entity. */
+ gcc_unreachable ();
}
case E_Constant:
gcc_assert (ralign >= align);
}
+ /* The expression might not be a DECL so save it manually. */
save_gnu_tree (gnat_entity, gnu_decl, true);
saved = true;
annotate_object (gnat_entity, gnu_type, NULL_TREE, false);
NULL_TREE, false);
this_made_decl = true;
gnu_type = TREE_TYPE (gnu_decl);
-
save_gnu_tree (gnat_entity, NULL_TREE, false);
+ save_gnu_tree (gnat_entity, gnu_decl, false);
+ saved = true;
gnu_inner = gnu_type;
while (TREE_CODE (gnu_inner) == RECORD_TYPE
gnu_decl = TYPE_STUB_DECL (gnu_type);
if (Has_Completion_In_Body (gnat_entity))
DECL_TAFT_TYPE_P (gnu_decl) = 1;
- save_gnu_tree (full_view, gnu_decl, 0);
+ save_gnu_tree (full_view, gnu_decl, false);
}
}
break;
handling alignment and possible padding. */
if (is_type && (!gnu_decl || this_made_decl))
{
+ gcc_assert (!TYPE_IS_DUMMY_P (gnu_type));
+
/* Process the attributes, if not already done. Note that the type is
already defined so we cannot pass true for IN_PLACE here. */
process_attributes (&gnu_type, &attr_list, false, gnat_entity);
}
}
- if (!gnu_decl)
- gnu_decl = create_type_decl (gnu_entity_name, gnu_type,
- artificial_p, debug_info_p,
- gnat_entity);
- else
- {
- TREE_TYPE (gnu_decl) = gnu_type;
- TYPE_STUB_DECL (gnu_type) = gnu_decl;
- }
- }
-
- if (is_type && !TYPE_IS_DUMMY_P (TREE_TYPE (gnu_decl)))
- {
- gnu_type = TREE_TYPE (gnu_decl);
-
/* If this is a derived type, relate its alias set to that of its parent
to avoid troubles when a call to an inherited primitive is inlined in
a context where a derived object is accessed. The inlined code works
? ALIAS_SET_COPY : ALIAS_SET_SUPERSET);
}
- /* Back-annotate the Alignment of the type if not already in the
- tree. Likewise for sizes. */
+ if (!gnu_decl)
+ gnu_decl = create_type_decl (gnu_entity_name, gnu_type,
+ artificial_p, debug_info_p,
+ gnat_entity);
+ else
+ {
+ TREE_TYPE (gnu_decl) = gnu_type;
+ TYPE_STUB_DECL (gnu_type) = gnu_decl;
+ }
+ }
+
+ /* If we got a type that is not dummy, back-annotate the alignment of the
+ type if not already in the tree. Likewise for the size, if any. */
+ if (is_type && !TYPE_IS_DUMMY_P (TREE_TYPE (gnu_decl)))
+ {
+ gnu_type = TREE_TYPE (gnu_decl);
+
if (Unknown_Alignment (gnat_entity))
{
unsigned int double_align, align;
Set_Esize (gnat_entity, annotate_value (gnu_size));
}
- if (Unknown_RM_Size (gnat_entity) && rm_size (gnu_type))
+ if (Unknown_RM_Size (gnat_entity) && TYPE_SIZE (gnu_type))
Set_RM_Size (gnat_entity, annotate_value (rm_size (gnu_type)));
}
}
/* Return a GCC tree for a parameter corresponding to GNAT_PARAM, to be placed
- in the parameter list built for GNAT_SUBPROG. FIRST is true if GNAT_PARAM
- is the first parameter in the list. Also set CICO to true if the parameter
- must use the copy-in copy-out implementation mechanism.
+ in the parameter list of GNAT_SUBPROG. GNU_PARAM_TYPE is the GCC tree for
+ the type of the parameter. FIRST is true if this is the first parameter in
+ the list of GNAT_SUBPROG. Also set CICO to true if the parameter must use
+ the copy-in copy-out implementation mechanism.
- The returned tree is a PARM_DECL, except for those cases where no
- parameter needs to be actually passed to the subprogram; the type
- of this "shadow" parameter is then returned instead. */
+ The returned tree is a PARM_DECL, except for the cases where no parameter
+ needs to be actually passed to the subprogram; the type of this "shadow"
+ parameter is then returned instead. */
static tree
-gnat_to_gnu_param (Entity_Id gnat_param, bool first, Entity_Id gnat_subprog,
- bool *cico)
+gnat_to_gnu_param (Entity_Id gnat_param, tree gnu_param_type, bool first,
+ Entity_Id gnat_subprog, bool *cico)
{
Entity_Id gnat_param_type = Etype (gnat_param);
Mechanism_Type mech = Mechanism (gnat_param);
tree gnu_param_name = get_entity_name (gnat_param);
- tree gnu_param_type = gnat_to_gnu_type (gnat_param_type);
bool foreign = Has_Foreign_Convention (gnat_subprog);
bool in_param = (Ekind (gnat_param) == E_In_Parameter);
/* The parameter can be indirectly modified if its address is taken. */
}
/* Associate GNAT_SUBPROG with GNU_TYPE, which must be a dummy type, so that
- GNAT_SUBPROG is updated when TYPE is completed.
+ GNAT_SUBPROG is updated when GNU_TYPE is completed.
Ada 2012 (AI05-019) says that freezing a subprogram does not always freeze
the corresponding profile, which means that, by the time the freeze node
of the subprogram is encountered, types involved in its profile may still
- be not frozen yet. That's why we do not update GNAT_SUBPROG when we see
- its freeze node but only when we see the freeze node of types involved in
- its profile, either types of formal parameters or the return type. */
+ be not yet frozen. That's why we need to update GNAT_SUBPROG when we see
+ the freeze node of types involved in its profile, either types of formal
+ parameters or the return type. */
static void
associate_subprog_with_dummy_type (Entity_Id gnat_subprog, tree gnu_type)
&& ((!in_main_unit
&& !present_gnu_tree (gnat_equiv)
&& Present (gnat_full)
- && (Is_Record_Type (gnat_full) || Is_Array_Type (gnat_full)))
+ && (Is_Record_Type (gnat_full)
+ || Is_Array_Type (gnat_full)
+ || Is_Access_Type (gnat_full)))
|| (in_main_unit && Present (Freeze_Node (gnat_rep)))))
{
gnu_type = make_dummy_type (gnat_equiv);
else
{
gnu_param
- = gnat_to_gnu_param (gnat_param, num == 0, gnat_subprog,
- &cico);
+ = gnat_to_gnu_param (gnat_param, gnu_param_type, num == 0,
+ gnat_subprog, &cico);
/* We are returned either a PARM_DECL or a type if no parameter
needs to be passed; in either case, adjust the type. */
/***************************/
case N_Subprogram_Declaration:
- /* Unless there is a freeze node, declare the subprogram. We consider
- this a "definition" even though we're not generating code for
- the subprogram because we will be making the corresponding GCC
- node here. */
-
+ /* Unless there is a freeze node, declare the entity. We consider
+ this a definition even though we're not generating code for the
+ subprogram because we will be making the corresponding GCC node.
+ When there is a freeze node, it is considered the definition of
+ the subprogram and we do nothing until after it is encountered.
+ That's an efficiency issue: the types involved in the profile
+ are far more likely to be frozen between the declaration and
+ the freeze node than before the declaration, so we save some
+ updates of the GCC node by waiting until the freeze node.
+ The counterpart is that we assume that there is no reference
+ to the subprogram between the declaration and the freeze node
+ in the expanded code; otherwise, it will be interpreted as an
+ external reference and very likely give rise to a link failure. */
if (No (Freeze_Node (Defining_Entity (Specification (gnat_node)))))
gnat_to_gnu_entity (Defining_Entity (Specification (gnat_node)),
NULL_TREE, true);
case N_Itype_Reference:
if (!present_gnu_tree (Itype (gnat_node)))
process_type (Itype (gnat_node));
-
gnu_result = alloc_stmt_list ();
break;
&& kind == E_Subprogram_Type)))
return;
- /* If we have a non-dummy type old tree, we have nothing to do, except
- aborting if this is the public view of a private type whose full view was
- not delayed, as this node was never delayed as it should have been. We
+ /* If we have a non-dummy type old tree, we have nothing to do, except for
+ aborting, since this node was never delayed as it should have been. We
let this happen for concurrent types and their Corresponding_Record_Type,
however, because each might legitimately be elaborated before its own
freeze node, e.g. while processing the other. */
&& !(TREE_CODE (gnu_old) == TYPE_DECL
&& TYPE_IS_DUMMY_P (TREE_TYPE (gnu_old))))
{
- gcc_assert ((IN (kind, Incomplete_Or_Private_Kind)
- && Present (Full_View (gnat_entity))
- && No (Freeze_Node (Full_View (gnat_entity))))
- || Is_Concurrent_Type (gnat_entity)
+ gcc_assert (Is_Concurrent_Type (gnat_entity)
|| (IN (kind, Record_Kind)
&& Is_Concurrent_Record_Type (gnat_entity)));
return;
}
}
\f
-/* Do the processing for the declaration of a GNAT_ENTITY, a type. If
- a separate Freeze node exists, delay the bulk of the processing. Otherwise
- make a GCC type for GNAT_ENTITY and set up the correspondence. */
+/* Do the processing for the declaration of a GNAT_ENTITY, a type or subtype.
+ If a Freeze node exists for the entity, delay the bulk of the processing.
+ Otherwise make a GCC type for GNAT_ENTITY and set up the correspondence. */
void
process_type (Entity_Id gnat_entity)
{
tree gnu_old
- = present_gnu_tree (gnat_entity) ? get_gnu_tree (gnat_entity) : 0;
- tree gnu_new;
-
- /* If we are to delay elaboration of this type, just do any
- elaborations needed for expressions within the declaration and
- make a dummy type entry for this node and its Full_View (if
- any) in case something points to it. Don't do this if it
- has already been done (the only way that can happen is if
- the private completion is also delayed). */
- if (Present (Freeze_Node (gnat_entity))
- || (IN (Ekind (gnat_entity), Incomplete_Or_Private_Kind)
- && Present (Full_View (gnat_entity))
- && Present (Freeze_Node (Full_View (gnat_entity)))
- && !present_gnu_tree (Full_View (gnat_entity))))
+ = present_gnu_tree (gnat_entity) ? get_gnu_tree (gnat_entity) : NULL_TREE;
+
+ /* If we are to delay elaboration of this type, just do any elaboration
+ needed for expressions within the declaration and make a dummy node
+ for it and its Full_View (if any), in case something points to it.
+ Do not do this if it has already been done (the only way that can
+ happen is if the private completion is also delayed). */
+ if (Present (Freeze_Node (gnat_entity)))
{
elaborate_entity (gnat_entity);
return;
}
- /* If we saved away a dummy type for this node it means that this
- made the type that corresponds to the full type of an incomplete
- type. Clear that type for now and then update the type in the
- pointers. */
+ /* If we saved away a dummy type for this node, it means that this made the
+ type that corresponds to the full type of an incomplete type. Clear that
+ type for now and then update the type in the pointers below. */
if (gnu_old)
{
gcc_assert (TREE_CODE (gnu_old) == TYPE_DECL
}
/* Now fully elaborate the type. */
- gnu_new = gnat_to_gnu_entity (gnat_entity, NULL_TREE, true);
+ tree gnu_new = gnat_to_gnu_entity (gnat_entity, NULL_TREE, true);
gcc_assert (TREE_CODE (gnu_new) == TYPE_DECL);
/* If we have an old type and we've made pointers to this type, update those