aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/trans.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2006-02-15 10:31:40 +0100
committerArnaud Charlet <charlet@gcc.gnu.org>2006-02-15 10:31:40 +0100
commit5b47742c2d278f8f8a4b1e02c6e1f786340da38f (patch)
tree1fd44711246a1ea895cf60b81987968b22bb417e /gcc/ada/trans.c
parent0022d9e31d01f2a31808ff38f66dd3e3ac96927a (diff)
downloadgcc-5b47742c2d278f8f8a4b1e02c6e1f786340da38f.zip
gcc-5b47742c2d278f8f8a4b1e02c6e1f786340da38f.tar.gz
gcc-5b47742c2d278f8f8a4b1e02c6e1f786340da38f.tar.bz2
re PR ada/26096 (Ada bootstrap fails in g-alleve.adb)
2006-02-13 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> Olivier Hainque <hainque@adacore.com> Eric Botcazou <ebotcazou@adacore.com> * ada-tree.h: (TYPE_UNCHECKED_UNION_P): Deleted. * gigi.h (value_factor_p): Add prototype and description, now public. * decl.c (gnat_to_gnu_field): Don't attempt BLKmode to integral type promotion for field with rep clause if the associated size was proven to be in error. Expand comments describing attempts to use a packable type. (gnat_to_gnu_entity) <E_Signed_Integer_Subtype, E_Floating_Point_Subtype>: Inherit alias set of what we are making a subtype of to ensure conflicts amongst all subtypes in a hierarchy, necessary since these are not different types and pointers may actually designate any subtype in this hierarchy. (gnat_to_gnu_entity, case E_Record_Type): Always make fields for discriminants but put them into record only if not Unchecked_Union; pass flag to components_to_record showing Unchecked_Union. (make_dummy_type): Use UNION_TYPE only if Unchecked_Union and no components before variants; don't set TYPE_UNCHECKED_UNION_P. (components_to_record): New argument UNCHECKED_UNION. Remove special case code for Unchecked_Union and instead use main code with small changes. PR ada/26096 (gnat_to_gnu_entity) <E_Variable>: Do not initialize the aligning variable with the expression being built, only its inner field. * trans.c (Handled_Sequence_Of_Statements_to_gnu): Remove call to emit_sequence_entry_statements. (emit_sequence_entry_statements, body_with_handlers_p): Delete. (establish_gnat_vms_condition_handler): Move before Subprogram_Body_to_gnu. (Subprogram_Body_to_gnu): On VMS, establish_gnat_vms_condition_handler for a subprogram if it has a foreign convention or is exported. (Identifier_to_gnu): Manually unshare the DECL_INITIAL tree when it is substituted for a CONST_DECL. (tree_transform, case N_Aggregate): Remove code for UNION_TYPE and pass Etype to assoc_to_constructor. (assoc_to_constructor): New argument, GNAT_ENTITY; use it to ignore discriminants of Unchecked_Union. (TARGET_ABI_OPEN_VMS): Define to 0 if not defined, so that later uses don't need cluttering preprocessor directives. (establish_gnat_vms_condition_handler): New function. Establish the GNAT condition handler as current in the compiled function. (body_with_handlers_p): New function. Tell whether a given sequence of statements node is attached to a package or subprogram body and involves exception handlers possibly nested within inner block statements. (emit_sequence_entry_statements): New function, to emit special statements on entry of sequences when necessary. Establish GNAT condition handler in the proper cases for VMS. (Handled_Sequence_Of_Statements_to_gnu): Start block code with emit_sequence_entry_statements. * utils2.c (find_common_type): If both input types are BLKmode and have a constant size, use the smaller one. (build_simple_component_ref): Also match if FIELD and NEW_FIELD are the same. * utils.c (value_factor_p): Make public, to allow uses from other gigi units. (create_type_decl): Do not set the flag DECL_IGNORED_P for dummy types. (convert, case UNION_TYPE): Remove special treatment for unchecked unions. PR ada/18659 (update_pointer_to): Update variants of pointer types to unconstrained arrays by attaching the list of fields of the main variant. From-SVN: r111030
Diffstat (limited to 'gcc/ada/trans.c')
-rw-r--r--gcc/ada/trans.c123
1 files changed, 100 insertions, 23 deletions
diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c
index f8698c5..1a9f3f4 100644
--- a/gcc/ada/trans.c
+++ b/gcc/ada/trans.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2005, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2006, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -57,6 +57,12 @@
#include "ada-tree.h"
#include "gigi.h"
+/* Let code below know whether we are targetting VMS without need of
+ intrusive preprocessor directives. */
+#ifndef TARGET_ABI_OPEN_VMS
+#define TARGET_ABI_OPEN_VMS 0
+#endif
+
int max_gnat_nodes;
int number_names;
struct Node *Nodes_Ptr;
@@ -159,7 +165,7 @@ static tree emit_index_check (tree, tree, tree, tree);
static tree emit_check (tree, tree, int);
static tree convert_with_check (Entity_Id, tree, bool, bool, bool);
static bool addressable_p (tree);
-static tree assoc_to_constructor (Node_Id, tree);
+static tree assoc_to_constructor (Entity_Id, Node_Id, tree);
static tree extract_values (tree, tree);
static tree pos_to_constructor (Node_Id, tree, Entity_Id);
static tree maybe_implicit_deref (tree);
@@ -446,7 +452,18 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
== Attr_Unchecked_Access)
|| (Get_Attribute_Id (Attribute_Name (gnat_temp))
== Attr_Unrestricted_Access)))))
- gnu_result = DECL_INITIAL (gnu_result);
+ {
+ gnu_result = DECL_INITIAL (gnu_result);
+ /* ??? The mark/unmark mechanism implemented in Gigi to prevent tree
+ sharing between global level and subprogram level doesn't apply
+ to elaboration routines. As a result, the DECL_INITIAL tree may
+ be shared between the static initializer of a global object and
+ the elaboration routine, thus wreaking havoc if a local temporary
+ is created in place during gimplification of the latter and the
+ former is emitted afterwards. Manually unshare for now. */
+ if (TREE_VISITED (gnu_result))
+ gnu_result = unshare_expr (gnu_result);
+ }
}
*gnu_result_type_p = gnu_result_type;
@@ -1340,6 +1357,57 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
return gnu_result;
}
+/* Emit statements to establish __gnat_handle_vms_condition as a VMS condition
+ handler for the current function. */
+
+/* This is implemented by issuing a call to the appropriate VMS specific
+ builtin. To avoid having VMS specific sections in the global gigi decls
+ array, we maintain the decls of interest here. We can't declare them
+ inside the function because we must mark them never to be GC'd, which we
+ can only do at the global level. */
+
+static GTY(()) tree vms_builtin_establish_handler_decl = NULL_TREE;
+static GTY(()) tree gnat_vms_condition_handler_decl = NULL_TREE;
+
+static void
+establish_gnat_vms_condition_handler (void)
+{
+ tree establish_stmt;
+
+ /* Elaborate the required decls on the first call. Check on the decl for
+ the gnat condition handler to decide, as this is one we create so we are
+ sure that it will be non null on subsequent calls. The builtin decl is
+ looked up so remains null on targets where it is not implemented yet. */
+ if (gnat_vms_condition_handler_decl == NULL_TREE)
+ {
+ vms_builtin_establish_handler_decl
+ = builtin_decl_for
+ (get_identifier ("__builtin_establish_vms_condition_handler"));
+
+ gnat_vms_condition_handler_decl
+ = create_subprog_decl (get_identifier ("__gnat_handle_vms_condition"),
+ NULL_TREE,
+ build_function_type_list (integer_type_node,
+ ptr_void_type_node,
+ ptr_void_type_node,
+ NULL_TREE),
+ NULL_TREE, 0, 1, 1, 0, Empty);
+ }
+
+ /* Do nothing if the establish builtin is not available, which might happen
+ on targets where the facility is not implemented. */
+ if (vms_builtin_establish_handler_decl == NULL_TREE)
+ return;
+
+ establish_stmt
+ = build_call_1_expr (vms_builtin_establish_handler_decl,
+ build_unary_op
+ (ADDR_EXPR, NULL_TREE,
+ gnat_vms_condition_handler_decl));
+
+ add_stmt (establish_stmt);
+}
+
/* Subroutine of gnat_to_gnu to process gnat_node, an N_Subprogram_Body. We
don't return anything. */
@@ -1433,6 +1501,22 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
gnat_to_gnu_entity (gnat_param, NULL_TREE, 1));
}
+
+ /* On VMS, establish our condition handler to possibly turn a condition into
+ the corresponding exception if the subprogram has a foreign convention or
+ is exported.
+
+ To ensure proper execution of local finalizations on condition instances,
+ we must turn a condition into the corresponding exception even if there
+ is no applicable Ada handler, and need at least one condition handler per
+ possible call chain involving GNAT code. OTOH, establishing the handler
+ has a cost so we want to mimize the number of subprograms into which this
+ happens. The foreign or exported condition is expected to satisfy all
+ the constraints. */
+ if (TARGET_ABI_OPEN_VMS
+ && (Has_Foreign_Convention (gnat_node) || Is_Exported (gnat_node)))
+ establish_gnat_vms_condition_handler ();
+
process_decls (Declarations (gnat_node), Empty, Empty, true, true);
/* Generate the code of the subprogram itself. A return statement will be
@@ -3082,25 +3166,11 @@ gnat_to_gnu (Node_Id gnat_node)
if (Null_Record_Present (gnat_node))
gnu_result = gnat_build_constructor (gnu_aggr_type, NULL_TREE);
- else if (TREE_CODE (gnu_aggr_type) == UNION_TYPE
- && TYPE_UNCHECKED_UNION_P (gnu_aggr_type))
- {
- /* The first element is the discrimant, which we ignore. The
- next is the field we're building. Convert the expression
- to the type of the field and then to the union type. */
- Node_Id gnat_assoc
- = Next (First (Component_Associations (gnat_node)));
- Entity_Id gnat_field = Entity (First (Choices (gnat_assoc)));
- tree gnu_field_type
- = TREE_TYPE (gnat_to_gnu_entity (gnat_field, NULL_TREE, 0));
-
- gnu_result = convert (gnu_field_type,
- gnat_to_gnu (Expression (gnat_assoc)));
- }
else if (TREE_CODE (gnu_aggr_type) == RECORD_TYPE
|| TREE_CODE (gnu_aggr_type) == UNION_TYPE)
gnu_result
- = assoc_to_constructor (First (Component_Associations (gnat_node)),
+ = assoc_to_constructor (Etype (gnat_node),
+ First (Component_Associations (gnat_node)),
gnu_aggr_type);
else if (TREE_CODE (gnu_aggr_type) == ARRAY_TYPE)
gnu_result = pos_to_constructor (First (Expressions (gnat_node)),
@@ -3996,7 +4066,8 @@ gnat_to_gnu (Node_Id gnat_node)
if (Present (Actual_Designated_Subtype (gnat_node)))
{
- gnu_actual_obj_type = gnat_to_gnu_type (Actual_Designated_Subtype (gnat_node));
+ gnu_actual_obj_type
+ = gnat_to_gnu_type (Actual_Designated_Subtype (gnat_node));
if (TYPE_FAT_OR_THIN_POINTER_P (gnu_ptr_type))
gnu_actual_obj_type
@@ -5582,13 +5653,14 @@ process_type (Entity_Id gnat_entity)
}
}
-/* GNAT_ASSOC is the front of the Component_Associations of an N_Aggregate.
- GNU_TYPE is the GCC type of the corresponding record.
+/* GNAT_ENTITY is the type of the resulting constructors,
+ GNAT_ASSOC is the front of the Component_Associations of an N_Aggregate,
+ and GNU_TYPE is the GCC type of the corresponding record.
Return a CONSTRUCTOR to build the record. */
static tree
-assoc_to_constructor (Node_Id gnat_assoc, tree gnu_type)
+assoc_to_constructor (Entity_Id gnat_entity, Node_Id gnat_assoc, tree gnu_type)
{
tree gnu_list, gnu_result;
@@ -5614,6 +5686,11 @@ assoc_to_constructor (Node_Id gnat_assoc, tree gnu_type)
&& Is_Tagged_Type (Scope (Entity (gnat_field))))
continue;
+ /* Also ignore discriminants of Unchecked_Unions. */
+ else if (Is_Unchecked_Union (gnat_entity)
+ && Ekind (Entity (gnat_field)) == E_Discriminant)
+ continue;
+
/* Before assigning a value in an aggregate make sure range checks
are done if required. Then convert to the type of the field. */
if (Do_Range_Check (Expression (gnat_assoc)))