[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