[gomp] avoid creating incomplete types in Fortran when possible (take 2)
Jakub Jelinek
jakub@redhat.com
Fri Oct 21 12:48:00 GMT 2005
On Thu, Oct 20, 2005 at 05:10:04PM -0400, Jakub Jelinek wrote:
> I'm not sure about gfc_trans_dummy_array_bias, maybe it will need similar
> handling as gfc_trans_array_bounds.
It does, so here is what I have committed.
2005-10-21 Jakub Jelinek <jakub@redhat.com>
* trans-decl.c (gfc_build_qualified_array): For non-assumed-size
arrays without constant size, create also an index var for
GFC_TYPE_ARRAY_SIZE (type). If the type is incomplete, complete
it as 0..size-1.
(gfc_create_string_length): Don't call gfc_defer_symbol_init
if just creating DECL_ARGUMENTS.
(gfc_get_symbol_decl): Call gfc_finish_var_decl and
gfc_defer_symbol_init even if ts.cl->backend_decl is already
set to a VAR_DECL that doesn't have DECL_CONTEXT yet.
(create_function_arglist): Rework, so that hidden length
arguments for CHARACTER parameters are created together with
the parameters. Resolve ts.cl->backend_decl for CHARACTER
parameters. If the argument is a non-constant length array
or CHARACTER, ensure PARM_DECL has different type than
its DECL_ARG_TYPE.
(generate_local_decl): Call gfc_get_symbol_decl even
for non-referenced non-constant length CHARACTER parameters
after optionally issuing warnings.
* trans-array.c (gfc_trans_array_bounds): Set last stride
to GFC_TYPE_ARRAY_SIZE (type) to initialize it as well.
(gfc_trans_dummy_array_bias): Initialize GFC_TYPE_ARRAY_SIZE (type)
variable as well.
--- gcc/fortran/trans-decl.c.jj 2005-10-21 09:37:41.000000000 +0200
+++ gcc/fortran/trans-decl.c 2005-10-21 09:43:39.000000000 +0200
@@ -569,6 +569,30 @@ gfc_build_qualified_array (tree decl, gf
else
gfc_add_decl_to_function (GFC_TYPE_ARRAY_OFFSET (type));
}
+
+ if (GFC_TYPE_ARRAY_SIZE (type) == NULL_TREE
+ && sym->as->type != AS_ASSUMED_SIZE)
+ GFC_TYPE_ARRAY_SIZE (type) = create_index_var ("size", nest);
+
+ if (POINTER_TYPE_P (type))
+ {
+ gcc_assert (GFC_ARRAY_TYPE_P (TREE_TYPE (type)));
+ gcc_assert (TYPE_LANG_SPECIFIC (type)
+ == TYPE_LANG_SPECIFIC (TREE_TYPE (type)));
+ type = TREE_TYPE (type);
+ }
+
+ if (! COMPLETE_TYPE_P (type) && GFC_TYPE_ARRAY_SIZE (type))
+ {
+ tree size, range;
+
+ size = build2 (MINUS_EXPR, gfc_array_index_type,
+ GFC_TYPE_ARRAY_SIZE (type), gfc_index_one_node);
+ range = build_range_type (gfc_array_index_type, gfc_index_zero_node,
+ size);
+ TYPE_DOMAIN (type) = range;
+ layout_type (type);
+ }
}
@@ -717,7 +741,8 @@ gfc_create_string_length (gfc_symbol * s
gfc_charlen_type_node);
DECL_ARTIFICIAL (length) = 1;
TREE_USED (length) = 1;
- gfc_defer_symbol_init (sym);
+ if (sym->ns->proc_name->tlink != NULL)
+ gfc_defer_symbol_init (sym);
sym->ts.cl->backend_decl = length;
}
@@ -763,13 +788,14 @@ gfc_get_symbol_decl (gfc_symbol * sym)
if (sym->ts.type == BT_CHARACTER)
{
if (sym->ts.cl->backend_decl == NULL_TREE)
+ length = gfc_create_string_length (sym);
+ else
+ length = sym->ts.cl->backend_decl;
+ if (TREE_CODE (length) == VAR_DECL
+ && DECL_CONTEXT (length) == NULL_TREE)
{
- length = gfc_create_string_length (sym);
- if (TREE_CODE (length) != INTEGER_CST)
- {
- gfc_finish_var_decl (length, sym);
- gfc_defer_symbol_init (sym);
- }
+ gfc_finish_var_decl (length, sym);
+ gfc_defer_symbol_init (sym);
}
}
@@ -1153,9 +1179,8 @@ create_function_arglist (gfc_symbol * sy
{
tree fndecl;
gfc_formal_arglist *f;
- tree typelist;
- tree arglist;
- tree length;
+ tree typelist, hidden_typelist;
+ tree arglist, hidden_arglist;
tree type;
tree parm;
@@ -1164,6 +1189,7 @@ create_function_arglist (gfc_symbol * sy
/* Build formal argument list. Make sure that their TREE_CONTEXT is
the new FUNCTION_DECL node. */
arglist = NULL_TREE;
+ hidden_arglist = NULL_TREE;
typelist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
if (sym->attr.entry_master)
@@ -1196,6 +1222,7 @@ create_function_arglist (gfc_symbol * sy
if (sym->ts.type == BT_CHARACTER)
{
+ tree length;
gfc_allocate_lang_decl (parm);
/* Length of character result. */
@@ -1221,92 +1248,109 @@ create_function_arglist (gfc_symbol * sy
}
}
+ hidden_typelist = typelist;
for (f = sym->formal; f; f = f->next)
- {
- if (f->sym != NULL) /* ignore alternate returns. */
- {
- length = NULL_TREE;
-
- type = TREE_VALUE (typelist);
+ if (f->sym != NULL) /* Ignore alternate returns. */
+ hidden_typelist = TREE_CHAIN (hidden_typelist);
- /* Build a the argument declaration. */
- parm = build_decl (PARM_DECL,
- gfc_sym_identifier (f->sym), type);
-
- /* Fill in arg stuff. */
- DECL_CONTEXT (parm) = fndecl;
- DECL_ARG_TYPE (parm) = type;
- /* All implementation args are read-only. */
- TREE_READONLY (parm) = 1;
-
- gfc_finish_decl (parm, NULL_TREE);
-
- f->sym->backend_decl = parm;
-
- arglist = chainon (arglist, parm);
- typelist = TREE_CHAIN (typelist);
- }
- }
-
- /* Add the hidden string length parameters. */
- parm = arglist;
for (f = sym->formal; f; f = f->next)
{
char name[GFC_MAX_SYMBOL_LEN + 2];
+
/* Ignore alternate returns. */
if (f->sym == NULL)
continue;
- if (f->sym->ts.type != BT_CHARACTER)
- continue;
-
- parm = f->sym->backend_decl;
type = TREE_VALUE (typelist);
- gcc_assert (type == gfc_charlen_type_node);
- strcpy (&name[1], f->sym->name);
- name[0] = '_';
- length = build_decl (PARM_DECL, get_identifier (name), type);
+ if (f->sym->ts.type == BT_CHARACTER)
+ {
+ tree len_type = TREE_VALUE (hidden_typelist);
+ tree length = NULL_TREE;
+ gcc_assert (len_type == gfc_charlen_type_node);
- arglist = chainon (arglist, length);
- DECL_CONTEXT (length) = fndecl;
- DECL_ARTIFICIAL (length) = 1;
- DECL_ARG_TYPE (length) = type;
- TREE_READONLY (length) = 1;
- gfc_finish_decl (length, NULL_TREE);
-
- /* TODO: Check string lengths when -fbounds-check. */
-
- /* Use the passed value for assumed length variables. */
- if (!f->sym->ts.cl->length)
- {
- TREE_USED (length) = 1;
- if (!f->sym->ts.cl->backend_decl)
- f->sym->ts.cl->backend_decl = length;
- else
+ strcpy (&name[1], f->sym->name);
+ name[0] = '_';
+ length = build_decl (PARM_DECL, get_identifier (name), len_type);
+
+ hidden_arglist = chainon (hidden_arglist, length);
+ DECL_CONTEXT (length) = fndecl;
+ DECL_ARTIFICIAL (length) = 1;
+ DECL_ARG_TYPE (length) = len_type;
+ TREE_READONLY (length) = 1;
+ gfc_finish_decl (length, NULL_TREE);
+
+ /* TODO: Check string lengths when -fbounds-check. */
+
+ /* Use the passed value for assumed length variables. */
+ if (!f->sym->ts.cl->length)
{
- /* there is already another variable using this
- gfc_charlen node, build a new one for this variable
- and chain it into the list of gfc_charlens.
- This happens for e.g. in the case
- CHARACTER(*)::c1,c2
- since CHARACTER declarations on the same line share
- the same gfc_charlen node. */
- gfc_charlen *cl;
+ TREE_USED (length) = 1;
+ if (!f->sym->ts.cl->backend_decl)
+ f->sym->ts.cl->backend_decl = length;
+ else
+ {
+ /* there is already another variable using this
+ gfc_charlen node, build a new one for this variable
+ and chain it into the list of gfc_charlens.
+ This happens for e.g. in the case
+ CHARACTER(*)::c1,c2
+ since CHARACTER declarations on the same line share
+ the same gfc_charlen node. */
+ gfc_charlen *cl;
- cl = gfc_get_charlen ();
- cl->backend_decl = length;
- cl->next = f->sym->ts.cl->next;
- f->sym->ts.cl->next = cl;
- f->sym->ts.cl = cl;
+ cl = gfc_get_charlen ();
+ cl->backend_decl = length;
+ cl->next = f->sym->ts.cl->next;
+ f->sym->ts.cl->next = cl;
+ f->sym->ts.cl = cl;
+ }
+ }
+
+ hidden_typelist = TREE_CHAIN (hidden_typelist);
+
+ if (f->sym->ts.cl->backend_decl == NULL
+ || f->sym->ts.cl->backend_decl == length)
+ {
+ if (f->sym->ts.cl->backend_decl == NULL)
+ gfc_create_string_length (f->sym);
+
+ /* Make sure PARM_DECL type doesn't point to incomplete type. */
+ type = gfc_sym_type (f->sym);
}
}
- parm = TREE_CHAIN (parm);
+ /* For non-constant length array arguments, make sure they use
+ a different type node from TYPE_ARG_TYPES type. */
+ if (f->sym->attr.dimension
+ && type == TREE_VALUE (typelist)
+ && TREE_CODE (type) == POINTER_TYPE
+ && GFC_ARRAY_TYPE_P (type)
+ && f->sym->as->type != AS_ASSUMED_SIZE
+ && ! COMPLETE_TYPE_P (TREE_TYPE (type)))
+ type = gfc_sym_type (f->sym);
+
+ /* Build a the argument declaration. */
+ parm = build_decl (PARM_DECL, gfc_sym_identifier (f->sym), type);
+
+ /* Fill in arg stuff. */
+ DECL_CONTEXT (parm) = fndecl;
+ DECL_ARG_TYPE (parm) = TREE_VALUE (typelist);
+ /* All implementation args are read-only. */
+ TREE_READONLY (parm) = 1;
+
+ gfc_finish_decl (parm, NULL_TREE);
+
+ f->sym->backend_decl = parm;
+
+ arglist = chainon (arglist, parm);
typelist = TREE_CHAIN (typelist);
}
- gcc_assert (TREE_VALUE (typelist) == void_type_node);
+ /* Add the hidden string length parameters. */
+ arglist = chainon (arglist, hidden_arglist);
+
+ gcc_assert (TREE_VALUE (hidden_typelist) == void_type_node);
DECL_ARGUMENTS (fndecl) = arglist;
}
@@ -2342,6 +2386,19 @@ generate_local_decl (gfc_symbol * sym)
else if (warn_unused_variable
&& !(sym->attr.in_common || sym->attr.use_assoc))
warning (0, "unused variable %qs", sym->name);
+ /* For variable length CHARACTER parameters, the PARM_DECL already
+ references the length variable, so force gfc_get_symbol_decl
+ even when not referenced. If optimize > 0, it will be optimized
+ away anyway. But do this only after emitting -Wunused-parameter
+ warning if requested. */
+ if (sym->attr.dummy && ! sym->attr.referenced
+ && sym->ts.type == BT_CHARACTER
+ && sym->ts.cl->backend_decl != NULL
+ && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
+ {
+ sym->attr.referenced = 1;
+ gfc_get_symbol_decl (sym);
+ }
}
}
--- gcc/fortran/trans-array.c.jj 2005-10-21 09:37:41.000000000 +0200
+++ gcc/fortran/trans-array.c 2005-10-21 11:25:38.000000000 +0200
@@ -3162,7 +3162,7 @@ gfc_trans_array_bounds (tree type, gfc_s
if (dim + 1 < as->rank)
stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
else
- stride = NULL_TREE;
+ stride = GFC_TYPE_ARRAY_SIZE (type);
if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
{
@@ -3559,6 +3559,22 @@ gfc_trans_dummy_array_bias (gfc_symbol *
gfc_add_modify_expr (&block, stride, tmp);
}
}
+ else
+ {
+ stride = GFC_TYPE_ARRAY_SIZE (type);
+
+ if (stride && !INTEGER_CST_P (stride))
+ {
+ /* Calculate size = stride * (ubound + 1 - lbound). */
+ tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
+ gfc_index_one_node, lbound);
+ tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
+ ubound, tmp);
+ tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
+ GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
+ gfc_add_modify_expr (&block, stride, tmp);
+ }
+ }
}
/* Set the offset. */
Jakub
More information about the Fortran
mailing list