OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [fortran/] [trans-types.c] - Diff between revs 285 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 285 Rev 816
/* Backend support for Fortran 95 basic types and derived types.
/* Backend support for Fortran 95 basic types and derived types.
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
   2010
   2010
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Contributed by Paul Brook <paul@nowt.org>
   Contributed by Paul Brook <paul@nowt.org>
   and Steven Bosscher <s.bosscher@student.tudelft.nl>
   and Steven Bosscher <s.bosscher@student.tudelft.nl>
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
/* trans-types.c -- gfortran backend types */
/* trans-types.c -- gfortran backend types */
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tree.h"
#include "tree.h"
#include "langhooks.h"
#include "langhooks.h"
#include "tm.h"
#include "tm.h"
#include "target.h"
#include "target.h"
#include "ggc.h"
#include "ggc.h"
#include "toplev.h"
#include "toplev.h"
#include "gfortran.h"
#include "gfortran.h"
#include "trans.h"
#include "trans.h"
#include "trans-types.h"
#include "trans-types.h"
#include "trans-const.h"
#include "trans-const.h"
#include "real.h"
#include "real.h"
#include "flags.h"
#include "flags.h"
#include "dwarf2out.h"
#include "dwarf2out.h"


 
 
#if (GFC_MAX_DIMENSIONS < 10)
#if (GFC_MAX_DIMENSIONS < 10)
#define GFC_RANK_DIGITS 1
#define GFC_RANK_DIGITS 1
#define GFC_RANK_PRINTF_FORMAT "%01d"
#define GFC_RANK_PRINTF_FORMAT "%01d"
#elif (GFC_MAX_DIMENSIONS < 100)
#elif (GFC_MAX_DIMENSIONS < 100)
#define GFC_RANK_DIGITS 2
#define GFC_RANK_DIGITS 2
#define GFC_RANK_PRINTF_FORMAT "%02d"
#define GFC_RANK_PRINTF_FORMAT "%02d"
#else
#else
#error If you really need >99 dimensions, continue the sequence above...
#error If you really need >99 dimensions, continue the sequence above...
#endif
#endif
 
 
/* array of structs so we don't have to worry about xmalloc or free */
/* array of structs so we don't have to worry about xmalloc or free */
CInteropKind_t c_interop_kinds_table[ISOCBINDING_NUMBER];
CInteropKind_t c_interop_kinds_table[ISOCBINDING_NUMBER];
 
 
tree gfc_array_index_type;
tree gfc_array_index_type;
tree gfc_array_range_type;
tree gfc_array_range_type;
tree gfc_character1_type_node;
tree gfc_character1_type_node;
tree pvoid_type_node;
tree pvoid_type_node;
tree prvoid_type_node;
tree prvoid_type_node;
tree ppvoid_type_node;
tree ppvoid_type_node;
tree pchar_type_node;
tree pchar_type_node;
tree pfunc_type_node;
tree pfunc_type_node;
 
 
tree gfc_charlen_type_node;
tree gfc_charlen_type_node;
 
 
static GTY(()) tree gfc_desc_dim_type;
static GTY(()) tree gfc_desc_dim_type;
static GTY(()) tree gfc_max_array_element_size;
static GTY(()) tree gfc_max_array_element_size;
static GTY(()) tree gfc_array_descriptor_base[2 * GFC_MAX_DIMENSIONS];
static GTY(()) tree gfc_array_descriptor_base[2 * GFC_MAX_DIMENSIONS];
 
 
/* Arrays for all integral and real kinds.  We'll fill this in at runtime
/* Arrays for all integral and real kinds.  We'll fill this in at runtime
   after the target has a chance to process command-line options.  */
   after the target has a chance to process command-line options.  */
 
 
#define MAX_INT_KINDS 5
#define MAX_INT_KINDS 5
gfc_integer_info gfc_integer_kinds[MAX_INT_KINDS + 1];
gfc_integer_info gfc_integer_kinds[MAX_INT_KINDS + 1];
gfc_logical_info gfc_logical_kinds[MAX_INT_KINDS + 1];
gfc_logical_info gfc_logical_kinds[MAX_INT_KINDS + 1];
static GTY(()) tree gfc_integer_types[MAX_INT_KINDS + 1];
static GTY(()) tree gfc_integer_types[MAX_INT_KINDS + 1];
static GTY(()) tree gfc_logical_types[MAX_INT_KINDS + 1];
static GTY(()) tree gfc_logical_types[MAX_INT_KINDS + 1];
 
 
#define MAX_REAL_KINDS 5
#define MAX_REAL_KINDS 5
gfc_real_info gfc_real_kinds[MAX_REAL_KINDS + 1];
gfc_real_info gfc_real_kinds[MAX_REAL_KINDS + 1];
static GTY(()) tree gfc_real_types[MAX_REAL_KINDS + 1];
static GTY(()) tree gfc_real_types[MAX_REAL_KINDS + 1];
static GTY(()) tree gfc_complex_types[MAX_REAL_KINDS + 1];
static GTY(()) tree gfc_complex_types[MAX_REAL_KINDS + 1];
 
 
#define MAX_CHARACTER_KINDS 2
#define MAX_CHARACTER_KINDS 2
gfc_character_info gfc_character_kinds[MAX_CHARACTER_KINDS + 1];
gfc_character_info gfc_character_kinds[MAX_CHARACTER_KINDS + 1];
static GTY(()) tree gfc_character_types[MAX_CHARACTER_KINDS + 1];
static GTY(()) tree gfc_character_types[MAX_CHARACTER_KINDS + 1];
static GTY(()) tree gfc_pcharacter_types[MAX_CHARACTER_KINDS + 1];
static GTY(()) tree gfc_pcharacter_types[MAX_CHARACTER_KINDS + 1];
 
 
 
 
/* The integer kind to use for array indices.  This will be set to the
/* The integer kind to use for array indices.  This will be set to the
   proper value based on target information from the backend.  */
   proper value based on target information from the backend.  */
 
 
int gfc_index_integer_kind;
int gfc_index_integer_kind;
 
 
/* The default kinds of the various types.  */
/* The default kinds of the various types.  */
 
 
int gfc_default_integer_kind;
int gfc_default_integer_kind;
int gfc_max_integer_kind;
int gfc_max_integer_kind;
int gfc_default_real_kind;
int gfc_default_real_kind;
int gfc_default_double_kind;
int gfc_default_double_kind;
int gfc_default_character_kind;
int gfc_default_character_kind;
int gfc_default_logical_kind;
int gfc_default_logical_kind;
int gfc_default_complex_kind;
int gfc_default_complex_kind;
int gfc_c_int_kind;
int gfc_c_int_kind;
 
 
/* The kind size used for record offsets. If the target system supports
/* The kind size used for record offsets. If the target system supports
   kind=8, this will be set to 8, otherwise it is set to 4.  */
   kind=8, this will be set to 8, otherwise it is set to 4.  */
int gfc_intio_kind;
int gfc_intio_kind;
 
 
/* The integer kind used to store character lengths.  */
/* The integer kind used to store character lengths.  */
int gfc_charlen_int_kind;
int gfc_charlen_int_kind;
 
 
/* The size of the numeric storage unit and character storage unit.  */
/* The size of the numeric storage unit and character storage unit.  */
int gfc_numeric_storage_size;
int gfc_numeric_storage_size;
int gfc_character_storage_size;
int gfc_character_storage_size;
 
 
 
 
gfc_try
gfc_try
gfc_check_any_c_kind (gfc_typespec *ts)
gfc_check_any_c_kind (gfc_typespec *ts)
{
{
  int i;
  int i;
 
 
  for (i = 0; i < ISOCBINDING_NUMBER; i++)
  for (i = 0; i < ISOCBINDING_NUMBER; i++)
    {
    {
      /* Check for any C interoperable kind for the given type/kind in ts.
      /* Check for any C interoperable kind for the given type/kind in ts.
         This can be used after verify_c_interop to make sure that the
         This can be used after verify_c_interop to make sure that the
         Fortran kind being used exists in at least some form for C.  */
         Fortran kind being used exists in at least some form for C.  */
      if (c_interop_kinds_table[i].f90_type == ts->type &&
      if (c_interop_kinds_table[i].f90_type == ts->type &&
          c_interop_kinds_table[i].value == ts->kind)
          c_interop_kinds_table[i].value == ts->kind)
        return SUCCESS;
        return SUCCESS;
    }
    }
 
 
  return FAILURE;
  return FAILURE;
}
}
 
 
 
 
static int
static int
get_real_kind_from_node (tree type)
get_real_kind_from_node (tree type)
{
{
  int i;
  int i;
 
 
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
    if (gfc_real_kinds[i].mode_precision == TYPE_PRECISION (type))
    if (gfc_real_kinds[i].mode_precision == TYPE_PRECISION (type))
      return gfc_real_kinds[i].kind;
      return gfc_real_kinds[i].kind;
 
 
  return -4;
  return -4;
}
}
 
 
static int
static int
get_int_kind_from_node (tree type)
get_int_kind_from_node (tree type)
{
{
  int i;
  int i;
 
 
  if (!type)
  if (!type)
    return -2;
    return -2;
 
 
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
    if (gfc_integer_kinds[i].bit_size == TYPE_PRECISION (type))
    if (gfc_integer_kinds[i].bit_size == TYPE_PRECISION (type))
      return gfc_integer_kinds[i].kind;
      return gfc_integer_kinds[i].kind;
 
 
  return -1;
  return -1;
}
}
 
 
/* Return a typenode for the "standard" C type with a given name.  */
/* Return a typenode for the "standard" C type with a given name.  */
static tree
static tree
get_typenode_from_name (const char *name)
get_typenode_from_name (const char *name)
{
{
  if (name == NULL || *name == '\0')
  if (name == NULL || *name == '\0')
    return NULL_TREE;
    return NULL_TREE;
 
 
  if (strcmp (name, "char") == 0)
  if (strcmp (name, "char") == 0)
    return char_type_node;
    return char_type_node;
  if (strcmp (name, "unsigned char") == 0)
  if (strcmp (name, "unsigned char") == 0)
    return unsigned_char_type_node;
    return unsigned_char_type_node;
  if (strcmp (name, "signed char") == 0)
  if (strcmp (name, "signed char") == 0)
    return signed_char_type_node;
    return signed_char_type_node;
 
 
  if (strcmp (name, "short int") == 0)
  if (strcmp (name, "short int") == 0)
    return short_integer_type_node;
    return short_integer_type_node;
  if (strcmp (name, "short unsigned int") == 0)
  if (strcmp (name, "short unsigned int") == 0)
    return short_unsigned_type_node;
    return short_unsigned_type_node;
 
 
  if (strcmp (name, "int") == 0)
  if (strcmp (name, "int") == 0)
    return integer_type_node;
    return integer_type_node;
  if (strcmp (name, "unsigned int") == 0)
  if (strcmp (name, "unsigned int") == 0)
    return unsigned_type_node;
    return unsigned_type_node;
 
 
  if (strcmp (name, "long int") == 0)
  if (strcmp (name, "long int") == 0)
    return long_integer_type_node;
    return long_integer_type_node;
  if (strcmp (name, "long unsigned int") == 0)
  if (strcmp (name, "long unsigned int") == 0)
    return long_unsigned_type_node;
    return long_unsigned_type_node;
 
 
  if (strcmp (name, "long long int") == 0)
  if (strcmp (name, "long long int") == 0)
    return long_long_integer_type_node;
    return long_long_integer_type_node;
  if (strcmp (name, "long long unsigned int") == 0)
  if (strcmp (name, "long long unsigned int") == 0)
    return long_long_unsigned_type_node;
    return long_long_unsigned_type_node;
 
 
  gcc_unreachable ();
  gcc_unreachable ();
}
}
 
 
static int
static int
get_int_kind_from_name (const char *name)
get_int_kind_from_name (const char *name)
{
{
  return get_int_kind_from_node (get_typenode_from_name (name));
  return get_int_kind_from_node (get_typenode_from_name (name));
}
}
 
 
 
 
/* Get the kind number corresponding to an integer of given size,
/* Get the kind number corresponding to an integer of given size,
   following the required return values for ISO_FORTRAN_ENV INT* constants:
   following the required return values for ISO_FORTRAN_ENV INT* constants:
   -2 is returned if we support a kind of larger size, -1 otherwise.  */
   -2 is returned if we support a kind of larger size, -1 otherwise.  */
int
int
gfc_get_int_kind_from_width_isofortranenv (int size)
gfc_get_int_kind_from_width_isofortranenv (int size)
{
{
  int i;
  int i;
 
 
  /* Look for a kind with matching storage size.  */
  /* Look for a kind with matching storage size.  */
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
    if (gfc_integer_kinds[i].bit_size == size)
    if (gfc_integer_kinds[i].bit_size == size)
      return gfc_integer_kinds[i].kind;
      return gfc_integer_kinds[i].kind;
 
 
  /* Look for a kind with larger storage size.  */
  /* Look for a kind with larger storage size.  */
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
    if (gfc_integer_kinds[i].bit_size > size)
    if (gfc_integer_kinds[i].bit_size > size)
      return -2;
      return -2;
 
 
  return -1;
  return -1;
}
}
 
 
/* Get the kind number corresponding to a real of given storage size,
/* Get the kind number corresponding to a real of given storage size,
   following the required return values for ISO_FORTRAN_ENV REAL* constants:
   following the required return values for ISO_FORTRAN_ENV REAL* constants:
   -2 is returned if we support a kind of larger size, -1 otherwise.  */
   -2 is returned if we support a kind of larger size, -1 otherwise.  */
int
int
gfc_get_real_kind_from_width_isofortranenv (int size)
gfc_get_real_kind_from_width_isofortranenv (int size)
{
{
  int i;
  int i;
 
 
  size /= 8;
  size /= 8;
 
 
  /* Look for a kind with matching storage size.  */
  /* Look for a kind with matching storage size.  */
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
    if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) == size)
    if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) == size)
      return gfc_real_kinds[i].kind;
      return gfc_real_kinds[i].kind;
 
 
  /* Look for a kind with larger storage size.  */
  /* Look for a kind with larger storage size.  */
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
    if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) > size)
    if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) > size)
      return -2;
      return -2;
 
 
  return -1;
  return -1;
}
}
 
 
 
 
 
 
static int
static int
get_int_kind_from_width (int size)
get_int_kind_from_width (int size)
{
{
  int i;
  int i;
 
 
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
    if (gfc_integer_kinds[i].bit_size == size)
    if (gfc_integer_kinds[i].bit_size == size)
      return gfc_integer_kinds[i].kind;
      return gfc_integer_kinds[i].kind;
 
 
  return -2;
  return -2;
}
}
 
 
static int
static int
get_int_kind_from_minimal_width (int size)
get_int_kind_from_minimal_width (int size)
{
{
  int i;
  int i;
 
 
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
    if (gfc_integer_kinds[i].bit_size >= size)
    if (gfc_integer_kinds[i].bit_size >= size)
      return gfc_integer_kinds[i].kind;
      return gfc_integer_kinds[i].kind;
 
 
  return -2;
  return -2;
}
}
 
 
 
 
/* Generate the CInteropKind_t objects for the C interoperable
/* Generate the CInteropKind_t objects for the C interoperable
   kinds.  */
   kinds.  */
 
 
static
static
void init_c_interop_kinds (void)
void init_c_interop_kinds (void)
{
{
  int i;
  int i;
 
 
  /* init all pointers in the list to NULL */
  /* init all pointers in the list to NULL */
  for (i = 0; i < ISOCBINDING_NUMBER; i++)
  for (i = 0; i < ISOCBINDING_NUMBER; i++)
    {
    {
      /* Initialize the name and value fields.  */
      /* Initialize the name and value fields.  */
      c_interop_kinds_table[i].name[0] = '\0';
      c_interop_kinds_table[i].name[0] = '\0';
      c_interop_kinds_table[i].value = -100;
      c_interop_kinds_table[i].value = -100;
      c_interop_kinds_table[i].f90_type = BT_UNKNOWN;
      c_interop_kinds_table[i].f90_type = BT_UNKNOWN;
    }
    }
 
 
#define NAMED_INTCST(a,b,c,d) \
#define NAMED_INTCST(a,b,c,d) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_INTEGER; \
  c_interop_kinds_table[a].f90_type = BT_INTEGER; \
  c_interop_kinds_table[a].value = c;
  c_interop_kinds_table[a].value = c;
#define NAMED_REALCST(a,b,c) \
#define NAMED_REALCST(a,b,c) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_REAL; \
  c_interop_kinds_table[a].f90_type = BT_REAL; \
  c_interop_kinds_table[a].value = c;
  c_interop_kinds_table[a].value = c;
#define NAMED_CMPXCST(a,b,c) \
#define NAMED_CMPXCST(a,b,c) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_COMPLEX; \
  c_interop_kinds_table[a].f90_type = BT_COMPLEX; \
  c_interop_kinds_table[a].value = c;
  c_interop_kinds_table[a].value = c;
#define NAMED_LOGCST(a,b,c) \
#define NAMED_LOGCST(a,b,c) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_LOGICAL; \
  c_interop_kinds_table[a].f90_type = BT_LOGICAL; \
  c_interop_kinds_table[a].value = c;
  c_interop_kinds_table[a].value = c;
#define NAMED_CHARKNDCST(a,b,c) \
#define NAMED_CHARKNDCST(a,b,c) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_CHARACTER; \
  c_interop_kinds_table[a].f90_type = BT_CHARACTER; \
  c_interop_kinds_table[a].value = c;
  c_interop_kinds_table[a].value = c;
#define NAMED_CHARCST(a,b,c) \
#define NAMED_CHARCST(a,b,c) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_CHARACTER; \
  c_interop_kinds_table[a].f90_type = BT_CHARACTER; \
  c_interop_kinds_table[a].value = c;
  c_interop_kinds_table[a].value = c;
#define DERIVED_TYPE(a,b,c) \
#define DERIVED_TYPE(a,b,c) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_DERIVED; \
  c_interop_kinds_table[a].f90_type = BT_DERIVED; \
  c_interop_kinds_table[a].value = c;
  c_interop_kinds_table[a].value = c;
#define PROCEDURE(a,b) \
#define PROCEDURE(a,b) \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
  c_interop_kinds_table[a].f90_type = BT_PROCEDURE; \
  c_interop_kinds_table[a].f90_type = BT_PROCEDURE; \
  c_interop_kinds_table[a].value = 0;
  c_interop_kinds_table[a].value = 0;
#include "iso-c-binding.def"
#include "iso-c-binding.def"
}
}
 
 
 
 
/* Query the target to determine which machine modes are available for
/* Query the target to determine which machine modes are available for
   computation.  Choose KIND numbers for them.  */
   computation.  Choose KIND numbers for them.  */
 
 
void
void
gfc_init_kinds (void)
gfc_init_kinds (void)
{
{
  unsigned int mode;
  unsigned int mode;
  int i_index, r_index, kind;
  int i_index, r_index, kind;
  bool saw_i4 = false, saw_i8 = false;
  bool saw_i4 = false, saw_i8 = false;
  bool saw_r4 = false, saw_r8 = false, saw_r16 = false;
  bool saw_r4 = false, saw_r8 = false, saw_r16 = false;
 
 
  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT; mode++)
  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT; mode++)
    {
    {
      int kind, bitsize;
      int kind, bitsize;
 
 
      if (!targetm.scalar_mode_supported_p ((enum machine_mode) mode))
      if (!targetm.scalar_mode_supported_p ((enum machine_mode) mode))
        continue;
        continue;
 
 
      /* The middle end doesn't support constants larger than 2*HWI.
      /* The middle end doesn't support constants larger than 2*HWI.
         Perhaps the target hook shouldn't have accepted these either,
         Perhaps the target hook shouldn't have accepted these either,
         but just to be safe...  */
         but just to be safe...  */
      bitsize = GET_MODE_BITSIZE (mode);
      bitsize = GET_MODE_BITSIZE (mode);
      if (bitsize > 2*HOST_BITS_PER_WIDE_INT)
      if (bitsize > 2*HOST_BITS_PER_WIDE_INT)
        continue;
        continue;
 
 
      gcc_assert (i_index != MAX_INT_KINDS);
      gcc_assert (i_index != MAX_INT_KINDS);
 
 
      /* Let the kind equal the bit size divided by 8.  This insulates the
      /* Let the kind equal the bit size divided by 8.  This insulates the
         programmer from the underlying byte size.  */
         programmer from the underlying byte size.  */
      kind = bitsize / 8;
      kind = bitsize / 8;
 
 
      if (kind == 4)
      if (kind == 4)
        saw_i4 = true;
        saw_i4 = true;
      if (kind == 8)
      if (kind == 8)
        saw_i8 = true;
        saw_i8 = true;
 
 
      gfc_integer_kinds[i_index].kind = kind;
      gfc_integer_kinds[i_index].kind = kind;
      gfc_integer_kinds[i_index].radix = 2;
      gfc_integer_kinds[i_index].radix = 2;
      gfc_integer_kinds[i_index].digits = bitsize - 1;
      gfc_integer_kinds[i_index].digits = bitsize - 1;
      gfc_integer_kinds[i_index].bit_size = bitsize;
      gfc_integer_kinds[i_index].bit_size = bitsize;
 
 
      gfc_logical_kinds[i_index].kind = kind;
      gfc_logical_kinds[i_index].kind = kind;
      gfc_logical_kinds[i_index].bit_size = bitsize;
      gfc_logical_kinds[i_index].bit_size = bitsize;
 
 
      i_index += 1;
      i_index += 1;
    }
    }
 
 
  /* Set the kind used to match GFC_INT_IO in libgfortran.  This is
  /* Set the kind used to match GFC_INT_IO in libgfortran.  This is
     used for large file access.  */
     used for large file access.  */
 
 
  if (saw_i8)
  if (saw_i8)
    gfc_intio_kind = 8;
    gfc_intio_kind = 8;
  else
  else
    gfc_intio_kind = 4;
    gfc_intio_kind = 4;
 
 
  /* If we do not at least have kind = 4, everything is pointless.  */
  /* If we do not at least have kind = 4, everything is pointless.  */
  gcc_assert(saw_i4);
  gcc_assert(saw_i4);
 
 
  /* Set the maximum integer kind.  Used with at least BOZ constants.  */
  /* Set the maximum integer kind.  Used with at least BOZ constants.  */
  gfc_max_integer_kind = gfc_integer_kinds[i_index - 1].kind;
  gfc_max_integer_kind = gfc_integer_kinds[i_index - 1].kind;
 
 
  for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT; mode++)
  for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT; mode++)
    {
    {
      const struct real_format *fmt =
      const struct real_format *fmt =
        REAL_MODE_FORMAT ((enum machine_mode) mode);
        REAL_MODE_FORMAT ((enum machine_mode) mode);
      int kind;
      int kind;
 
 
      if (fmt == NULL)
      if (fmt == NULL)
        continue;
        continue;
      if (!targetm.scalar_mode_supported_p ((enum machine_mode) mode))
      if (!targetm.scalar_mode_supported_p ((enum machine_mode) mode))
        continue;
        continue;
 
 
      /* Only let float/double/long double go through because the fortran
      /* Only let float/double/long double go through because the fortran
         library assumes these are the only floating point types.  */
         library assumes these are the only floating point types.  */
 
 
      if (mode != TYPE_MODE (float_type_node)
      if (mode != TYPE_MODE (float_type_node)
          && (mode != TYPE_MODE (double_type_node))
          && (mode != TYPE_MODE (double_type_node))
          && (mode != TYPE_MODE (long_double_type_node)))
          && (mode != TYPE_MODE (long_double_type_node)))
        continue;
        continue;
 
 
      /* Let the kind equal the precision divided by 8, rounding up.  Again,
      /* Let the kind equal the precision divided by 8, rounding up.  Again,
         this insulates the programmer from the underlying byte size.
         this insulates the programmer from the underlying byte size.
 
 
         Also, it effectively deals with IEEE extended formats.  There, the
         Also, it effectively deals with IEEE extended formats.  There, the
         total size of the type may equal 16, but it's got 6 bytes of padding
         total size of the type may equal 16, but it's got 6 bytes of padding
         and the increased size can get in the way of a real IEEE quad format
         and the increased size can get in the way of a real IEEE quad format
         which may also be supported by the target.
         which may also be supported by the target.
 
 
         We round up so as to handle IA-64 __floatreg (RFmode), which is an
         We round up so as to handle IA-64 __floatreg (RFmode), which is an
         82 bit type.  Not to be confused with __float80 (XFmode), which is
         82 bit type.  Not to be confused with __float80 (XFmode), which is
         an 80 bit type also supported by IA-64.  So XFmode should come out
         an 80 bit type also supported by IA-64.  So XFmode should come out
         to be kind=10, and RFmode should come out to be kind=11.  Egads.  */
         to be kind=10, and RFmode should come out to be kind=11.  Egads.  */
 
 
      kind = (GET_MODE_PRECISION (mode) + 7) / 8;
      kind = (GET_MODE_PRECISION (mode) + 7) / 8;
 
 
      if (kind == 4)
      if (kind == 4)
        saw_r4 = true;
        saw_r4 = true;
      if (kind == 8)
      if (kind == 8)
        saw_r8 = true;
        saw_r8 = true;
      if (kind == 16)
      if (kind == 16)
        saw_r16 = true;
        saw_r16 = true;
 
 
      /* Careful we don't stumble a weird internal mode.  */
      /* Careful we don't stumble a weird internal mode.  */
      gcc_assert (r_index <= 0 || gfc_real_kinds[r_index-1].kind != kind);
      gcc_assert (r_index <= 0 || gfc_real_kinds[r_index-1].kind != kind);
      /* Or have too many modes for the allocated space.  */
      /* Or have too many modes for the allocated space.  */
      gcc_assert (r_index != MAX_REAL_KINDS);
      gcc_assert (r_index != MAX_REAL_KINDS);
 
 
      gfc_real_kinds[r_index].kind = kind;
      gfc_real_kinds[r_index].kind = kind;
      gfc_real_kinds[r_index].radix = fmt->b;
      gfc_real_kinds[r_index].radix = fmt->b;
      gfc_real_kinds[r_index].digits = fmt->p;
      gfc_real_kinds[r_index].digits = fmt->p;
      gfc_real_kinds[r_index].min_exponent = fmt->emin;
      gfc_real_kinds[r_index].min_exponent = fmt->emin;
      gfc_real_kinds[r_index].max_exponent = fmt->emax;
      gfc_real_kinds[r_index].max_exponent = fmt->emax;
      if (fmt->pnan < fmt->p)
      if (fmt->pnan < fmt->p)
        /* This is an IBM extended double format (or the MIPS variant)
        /* This is an IBM extended double format (or the MIPS variant)
           made up of two IEEE doubles.  The value of the long double is
           made up of two IEEE doubles.  The value of the long double is
           the sum of the values of the two parts.  The most significant
           the sum of the values of the two parts.  The most significant
           part is required to be the value of the long double rounded
           part is required to be the value of the long double rounded
           to the nearest double.  If we use emax of 1024 then we can't
           to the nearest double.  If we use emax of 1024 then we can't
           represent huge(x) = (1 - b**(-p)) * b**(emax-1) * b, because
           represent huge(x) = (1 - b**(-p)) * b**(emax-1) * b, because
           rounding will make the most significant part overflow.  */
           rounding will make the most significant part overflow.  */
        gfc_real_kinds[r_index].max_exponent = fmt->emax - 1;
        gfc_real_kinds[r_index].max_exponent = fmt->emax - 1;
      gfc_real_kinds[r_index].mode_precision = GET_MODE_PRECISION (mode);
      gfc_real_kinds[r_index].mode_precision = GET_MODE_PRECISION (mode);
      r_index += 1;
      r_index += 1;
    }
    }
 
 
  /* Choose the default integer kind.  We choose 4 unless the user
  /* Choose the default integer kind.  We choose 4 unless the user
     directs us otherwise.  */
     directs us otherwise.  */
  if (gfc_option.flag_default_integer)
  if (gfc_option.flag_default_integer)
    {
    {
      if (!saw_i8)
      if (!saw_i8)
        fatal_error ("integer kind=8 not available for -fdefault-integer-8 option");
        fatal_error ("integer kind=8 not available for -fdefault-integer-8 option");
      gfc_default_integer_kind = 8;
      gfc_default_integer_kind = 8;
 
 
      /* Even if the user specified that the default integer kind be 8,
      /* Even if the user specified that the default integer kind be 8,
         the numeric storage size isn't 64.  In this case, a warning will
         the numeric storage size isn't 64.  In this case, a warning will
         be issued when NUMERIC_STORAGE_SIZE is used.  */
         be issued when NUMERIC_STORAGE_SIZE is used.  */
      gfc_numeric_storage_size = 4 * 8;
      gfc_numeric_storage_size = 4 * 8;
    }
    }
  else if (saw_i4)
  else if (saw_i4)
    {
    {
      gfc_default_integer_kind = 4;
      gfc_default_integer_kind = 4;
      gfc_numeric_storage_size = 4 * 8;
      gfc_numeric_storage_size = 4 * 8;
    }
    }
  else
  else
    {
    {
      gfc_default_integer_kind = gfc_integer_kinds[i_index - 1].kind;
      gfc_default_integer_kind = gfc_integer_kinds[i_index - 1].kind;
      gfc_numeric_storage_size = gfc_integer_kinds[i_index - 1].bit_size;
      gfc_numeric_storage_size = gfc_integer_kinds[i_index - 1].bit_size;
    }
    }
 
 
  /* Choose the default real kind.  Again, we choose 4 when possible.  */
  /* Choose the default real kind.  Again, we choose 4 when possible.  */
  if (gfc_option.flag_default_real)
  if (gfc_option.flag_default_real)
    {
    {
      if (!saw_r8)
      if (!saw_r8)
        fatal_error ("real kind=8 not available for -fdefault-real-8 option");
        fatal_error ("real kind=8 not available for -fdefault-real-8 option");
      gfc_default_real_kind = 8;
      gfc_default_real_kind = 8;
    }
    }
  else if (saw_r4)
  else if (saw_r4)
    gfc_default_real_kind = 4;
    gfc_default_real_kind = 4;
  else
  else
    gfc_default_real_kind = gfc_real_kinds[0].kind;
    gfc_default_real_kind = gfc_real_kinds[0].kind;
 
 
  /* Choose the default double kind.  If -fdefault-real and -fdefault-double
  /* Choose the default double kind.  If -fdefault-real and -fdefault-double
     are specified, we use kind=8, if it's available.  If -fdefault-real is
     are specified, we use kind=8, if it's available.  If -fdefault-real is
     specified without -fdefault-double, we use kind=16, if it's available.
     specified without -fdefault-double, we use kind=16, if it's available.
     Otherwise we do not change anything.  */
     Otherwise we do not change anything.  */
  if (gfc_option.flag_default_double && !gfc_option.flag_default_real)
  if (gfc_option.flag_default_double && !gfc_option.flag_default_real)
    fatal_error ("Use of -fdefault-double-8 requires -fdefault-real-8");
    fatal_error ("Use of -fdefault-double-8 requires -fdefault-real-8");
 
 
  if (gfc_option.flag_default_real && gfc_option.flag_default_double && saw_r8)
  if (gfc_option.flag_default_real && gfc_option.flag_default_double && saw_r8)
    gfc_default_double_kind = 8;
    gfc_default_double_kind = 8;
  else if (gfc_option.flag_default_real && saw_r16)
  else if (gfc_option.flag_default_real && saw_r16)
    gfc_default_double_kind = 16;
    gfc_default_double_kind = 16;
  else if (saw_r4 && saw_r8)
  else if (saw_r4 && saw_r8)
    gfc_default_double_kind = 8;
    gfc_default_double_kind = 8;
  else
  else
    {
    {
      /* F95 14.6.3.1: A nonpointer scalar object of type double precision
      /* F95 14.6.3.1: A nonpointer scalar object of type double precision
         real ... occupies two contiguous numeric storage units.
         real ... occupies two contiguous numeric storage units.
 
 
         Therefore we must be supplied a kind twice as large as we chose
         Therefore we must be supplied a kind twice as large as we chose
         for single precision.  There are loopholes, in that double
         for single precision.  There are loopholes, in that double
         precision must *occupy* two storage units, though it doesn't have
         precision must *occupy* two storage units, though it doesn't have
         to *use* two storage units.  Which means that you can make this
         to *use* two storage units.  Which means that you can make this
         kind artificially wide by padding it.  But at present there are
         kind artificially wide by padding it.  But at present there are
         no GCC targets for which a two-word type does not exist, so we
         no GCC targets for which a two-word type does not exist, so we
         just let gfc_validate_kind abort and tell us if something breaks.  */
         just let gfc_validate_kind abort and tell us if something breaks.  */
 
 
      gfc_default_double_kind
      gfc_default_double_kind
        = gfc_validate_kind (BT_REAL, gfc_default_real_kind * 2, false);
        = gfc_validate_kind (BT_REAL, gfc_default_real_kind * 2, false);
    }
    }
 
 
  /* The default logical kind is constrained to be the same as the
  /* The default logical kind is constrained to be the same as the
     default integer kind.  Similarly with complex and real.  */
     default integer kind.  Similarly with complex and real.  */
  gfc_default_logical_kind = gfc_default_integer_kind;
  gfc_default_logical_kind = gfc_default_integer_kind;
  gfc_default_complex_kind = gfc_default_real_kind;
  gfc_default_complex_kind = gfc_default_real_kind;
 
 
  /* We only have two character kinds: ASCII and UCS-4.
  /* We only have two character kinds: ASCII and UCS-4.
     ASCII corresponds to a 8-bit integer type, if one is available.
     ASCII corresponds to a 8-bit integer type, if one is available.
     UCS-4 corresponds to a 32-bit integer type, if one is available. */
     UCS-4 corresponds to a 32-bit integer type, if one is available. */
  i_index = 0;
  i_index = 0;
  if ((kind = get_int_kind_from_width (8)) > 0)
  if ((kind = get_int_kind_from_width (8)) > 0)
    {
    {
      gfc_character_kinds[i_index].kind = kind;
      gfc_character_kinds[i_index].kind = kind;
      gfc_character_kinds[i_index].bit_size = 8;
      gfc_character_kinds[i_index].bit_size = 8;
      gfc_character_kinds[i_index].name = "ascii";
      gfc_character_kinds[i_index].name = "ascii";
      i_index++;
      i_index++;
    }
    }
  if ((kind = get_int_kind_from_width (32)) > 0)
  if ((kind = get_int_kind_from_width (32)) > 0)
    {
    {
      gfc_character_kinds[i_index].kind = kind;
      gfc_character_kinds[i_index].kind = kind;
      gfc_character_kinds[i_index].bit_size = 32;
      gfc_character_kinds[i_index].bit_size = 32;
      gfc_character_kinds[i_index].name = "iso_10646";
      gfc_character_kinds[i_index].name = "iso_10646";
      i_index++;
      i_index++;
    }
    }
 
 
  /* Choose the smallest integer kind for our default character.  */
  /* Choose the smallest integer kind for our default character.  */
  gfc_default_character_kind = gfc_character_kinds[0].kind;
  gfc_default_character_kind = gfc_character_kinds[0].kind;
  gfc_character_storage_size = gfc_default_character_kind * 8;
  gfc_character_storage_size = gfc_default_character_kind * 8;
 
 
  /* Choose the integer kind the same size as "void*" for our index kind.  */
  /* Choose the integer kind the same size as "void*" for our index kind.  */
  gfc_index_integer_kind = POINTER_SIZE / 8;
  gfc_index_integer_kind = POINTER_SIZE / 8;
  /* Pick a kind the same size as the C "int" type.  */
  /* Pick a kind the same size as the C "int" type.  */
  gfc_c_int_kind = INT_TYPE_SIZE / 8;
  gfc_c_int_kind = INT_TYPE_SIZE / 8;
 
 
  /* initialize the C interoperable kinds  */
  /* initialize the C interoperable kinds  */
  init_c_interop_kinds();
  init_c_interop_kinds();
}
}
 
 
/* Make sure that a valid kind is present.  Returns an index into the
/* Make sure that a valid kind is present.  Returns an index into the
   associated kinds array, -1 if the kind is not present.  */
   associated kinds array, -1 if the kind is not present.  */
 
 
static int
static int
validate_integer (int kind)
validate_integer (int kind)
{
{
  int i;
  int i;
 
 
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
  for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
    if (gfc_integer_kinds[i].kind == kind)
    if (gfc_integer_kinds[i].kind == kind)
      return i;
      return i;
 
 
  return -1;
  return -1;
}
}
 
 
static int
static int
validate_real (int kind)
validate_real (int kind)
{
{
  int i;
  int i;
 
 
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
  for (i = 0; gfc_real_kinds[i].kind != 0; i++)
    if (gfc_real_kinds[i].kind == kind)
    if (gfc_real_kinds[i].kind == kind)
      return i;
      return i;
 
 
  return -1;
  return -1;
}
}
 
 
static int
static int
validate_logical (int kind)
validate_logical (int kind)
{
{
  int i;
  int i;
 
 
  for (i = 0; gfc_logical_kinds[i].kind; i++)
  for (i = 0; gfc_logical_kinds[i].kind; i++)
    if (gfc_logical_kinds[i].kind == kind)
    if (gfc_logical_kinds[i].kind == kind)
      return i;
      return i;
 
 
  return -1;
  return -1;
}
}
 
 
static int
static int
validate_character (int kind)
validate_character (int kind)
{
{
  int i;
  int i;
 
 
  for (i = 0; gfc_character_kinds[i].kind; i++)
  for (i = 0; gfc_character_kinds[i].kind; i++)
    if (gfc_character_kinds[i].kind == kind)
    if (gfc_character_kinds[i].kind == kind)
      return i;
      return i;
 
 
  return -1;
  return -1;
}
}
 
 
/* Validate a kind given a basic type.  The return value is the same
/* Validate a kind given a basic type.  The return value is the same
   for the child functions, with -1 indicating nonexistence of the
   for the child functions, with -1 indicating nonexistence of the
   type.  If MAY_FAIL is false, then -1 is never returned, and we ICE.  */
   type.  If MAY_FAIL is false, then -1 is never returned, and we ICE.  */
 
 
int
int
gfc_validate_kind (bt type, int kind, bool may_fail)
gfc_validate_kind (bt type, int kind, bool may_fail)
{
{
  int rc;
  int rc;
 
 
  switch (type)
  switch (type)
    {
    {
    case BT_REAL:               /* Fall through */
    case BT_REAL:               /* Fall through */
    case BT_COMPLEX:
    case BT_COMPLEX:
      rc = validate_real (kind);
      rc = validate_real (kind);
      break;
      break;
    case BT_INTEGER:
    case BT_INTEGER:
      rc = validate_integer (kind);
      rc = validate_integer (kind);
      break;
      break;
    case BT_LOGICAL:
    case BT_LOGICAL:
      rc = validate_logical (kind);
      rc = validate_logical (kind);
      break;
      break;
    case BT_CHARACTER:
    case BT_CHARACTER:
      rc = validate_character (kind);
      rc = validate_character (kind);
      break;
      break;
 
 
    default:
    default:
      gfc_internal_error ("gfc_validate_kind(): Got bad type");
      gfc_internal_error ("gfc_validate_kind(): Got bad type");
    }
    }
 
 
  if (rc < 0 && !may_fail)
  if (rc < 0 && !may_fail)
    gfc_internal_error ("gfc_validate_kind(): Got bad kind");
    gfc_internal_error ("gfc_validate_kind(): Got bad kind");
 
 
  return rc;
  return rc;
}
}
 
 
 
 
/* Four subroutines of gfc_init_types.  Create type nodes for the given kind.
/* Four subroutines of gfc_init_types.  Create type nodes for the given kind.
   Reuse common type nodes where possible.  Recognize if the kind matches up
   Reuse common type nodes where possible.  Recognize if the kind matches up
   with a C type.  This will be used later in determining which routines may
   with a C type.  This will be used later in determining which routines may
   be scarfed from libm.  */
   be scarfed from libm.  */
 
 
static tree
static tree
gfc_build_int_type (gfc_integer_info *info)
gfc_build_int_type (gfc_integer_info *info)
{
{
  int mode_precision = info->bit_size;
  int mode_precision = info->bit_size;
 
 
  if (mode_precision == CHAR_TYPE_SIZE)
  if (mode_precision == CHAR_TYPE_SIZE)
    info->c_char = 1;
    info->c_char = 1;
  if (mode_precision == SHORT_TYPE_SIZE)
  if (mode_precision == SHORT_TYPE_SIZE)
    info->c_short = 1;
    info->c_short = 1;
  if (mode_precision == INT_TYPE_SIZE)
  if (mode_precision == INT_TYPE_SIZE)
    info->c_int = 1;
    info->c_int = 1;
  if (mode_precision == LONG_TYPE_SIZE)
  if (mode_precision == LONG_TYPE_SIZE)
    info->c_long = 1;
    info->c_long = 1;
  if (mode_precision == LONG_LONG_TYPE_SIZE)
  if (mode_precision == LONG_LONG_TYPE_SIZE)
    info->c_long_long = 1;
    info->c_long_long = 1;
 
 
  if (TYPE_PRECISION (intQI_type_node) == mode_precision)
  if (TYPE_PRECISION (intQI_type_node) == mode_precision)
    return intQI_type_node;
    return intQI_type_node;
  if (TYPE_PRECISION (intHI_type_node) == mode_precision)
  if (TYPE_PRECISION (intHI_type_node) == mode_precision)
    return intHI_type_node;
    return intHI_type_node;
  if (TYPE_PRECISION (intSI_type_node) == mode_precision)
  if (TYPE_PRECISION (intSI_type_node) == mode_precision)
    return intSI_type_node;
    return intSI_type_node;
  if (TYPE_PRECISION (intDI_type_node) == mode_precision)
  if (TYPE_PRECISION (intDI_type_node) == mode_precision)
    return intDI_type_node;
    return intDI_type_node;
  if (TYPE_PRECISION (intTI_type_node) == mode_precision)
  if (TYPE_PRECISION (intTI_type_node) == mode_precision)
    return intTI_type_node;
    return intTI_type_node;
 
 
  return make_signed_type (mode_precision);
  return make_signed_type (mode_precision);
}
}
 
 
tree
tree
gfc_build_uint_type (int size)
gfc_build_uint_type (int size)
{
{
  if (size == CHAR_TYPE_SIZE)
  if (size == CHAR_TYPE_SIZE)
    return unsigned_char_type_node;
    return unsigned_char_type_node;
  if (size == SHORT_TYPE_SIZE)
  if (size == SHORT_TYPE_SIZE)
    return short_unsigned_type_node;
    return short_unsigned_type_node;
  if (size == INT_TYPE_SIZE)
  if (size == INT_TYPE_SIZE)
    return unsigned_type_node;
    return unsigned_type_node;
  if (size == LONG_TYPE_SIZE)
  if (size == LONG_TYPE_SIZE)
    return long_unsigned_type_node;
    return long_unsigned_type_node;
  if (size == LONG_LONG_TYPE_SIZE)
  if (size == LONG_LONG_TYPE_SIZE)
    return long_long_unsigned_type_node;
    return long_long_unsigned_type_node;
 
 
  return make_unsigned_type (size);
  return make_unsigned_type (size);
}
}
 
 
 
 
static tree
static tree
gfc_build_real_type (gfc_real_info *info)
gfc_build_real_type (gfc_real_info *info)
{
{
  int mode_precision = info->mode_precision;
  int mode_precision = info->mode_precision;
  tree new_type;
  tree new_type;
 
 
  if (mode_precision == FLOAT_TYPE_SIZE)
  if (mode_precision == FLOAT_TYPE_SIZE)
    info->c_float = 1;
    info->c_float = 1;
  if (mode_precision == DOUBLE_TYPE_SIZE)
  if (mode_precision == DOUBLE_TYPE_SIZE)
    info->c_double = 1;
    info->c_double = 1;
  if (mode_precision == LONG_DOUBLE_TYPE_SIZE)
  if (mode_precision == LONG_DOUBLE_TYPE_SIZE)
    info->c_long_double = 1;
    info->c_long_double = 1;
 
 
  if (TYPE_PRECISION (float_type_node) == mode_precision)
  if (TYPE_PRECISION (float_type_node) == mode_precision)
    return float_type_node;
    return float_type_node;
  if (TYPE_PRECISION (double_type_node) == mode_precision)
  if (TYPE_PRECISION (double_type_node) == mode_precision)
    return double_type_node;
    return double_type_node;
  if (TYPE_PRECISION (long_double_type_node) == mode_precision)
  if (TYPE_PRECISION (long_double_type_node) == mode_precision)
    return long_double_type_node;
    return long_double_type_node;
 
 
  new_type = make_node (REAL_TYPE);
  new_type = make_node (REAL_TYPE);
  TYPE_PRECISION (new_type) = mode_precision;
  TYPE_PRECISION (new_type) = mode_precision;
  layout_type (new_type);
  layout_type (new_type);
  return new_type;
  return new_type;
}
}
 
 
static tree
static tree
gfc_build_complex_type (tree scalar_type)
gfc_build_complex_type (tree scalar_type)
{
{
  tree new_type;
  tree new_type;
 
 
  if (scalar_type == NULL)
  if (scalar_type == NULL)
    return NULL;
    return NULL;
  if (scalar_type == float_type_node)
  if (scalar_type == float_type_node)
    return complex_float_type_node;
    return complex_float_type_node;
  if (scalar_type == double_type_node)
  if (scalar_type == double_type_node)
    return complex_double_type_node;
    return complex_double_type_node;
  if (scalar_type == long_double_type_node)
  if (scalar_type == long_double_type_node)
    return complex_long_double_type_node;
    return complex_long_double_type_node;
 
 
  new_type = make_node (COMPLEX_TYPE);
  new_type = make_node (COMPLEX_TYPE);
  TREE_TYPE (new_type) = scalar_type;
  TREE_TYPE (new_type) = scalar_type;
  layout_type (new_type);
  layout_type (new_type);
  return new_type;
  return new_type;
}
}
 
 
static tree
static tree
gfc_build_logical_type (gfc_logical_info *info)
gfc_build_logical_type (gfc_logical_info *info)
{
{
  int bit_size = info->bit_size;
  int bit_size = info->bit_size;
  tree new_type;
  tree new_type;
 
 
  if (bit_size == BOOL_TYPE_SIZE)
  if (bit_size == BOOL_TYPE_SIZE)
    {
    {
      info->c_bool = 1;
      info->c_bool = 1;
      return boolean_type_node;
      return boolean_type_node;
    }
    }
 
 
  new_type = make_unsigned_type (bit_size);
  new_type = make_unsigned_type (bit_size);
  TREE_SET_CODE (new_type, BOOLEAN_TYPE);
  TREE_SET_CODE (new_type, BOOLEAN_TYPE);
  TYPE_MAX_VALUE (new_type) = build_int_cst (new_type, 1);
  TYPE_MAX_VALUE (new_type) = build_int_cst (new_type, 1);
  TYPE_PRECISION (new_type) = 1;
  TYPE_PRECISION (new_type) = 1;
 
 
  return new_type;
  return new_type;
}
}
 
 
 
 
#if 0
#if 0
/* Return the bit size of the C "size_t".  */
/* Return the bit size of the C "size_t".  */
 
 
static unsigned int
static unsigned int
c_size_t_size (void)
c_size_t_size (void)
{
{
#ifdef SIZE_TYPE  
#ifdef SIZE_TYPE  
  if (strcmp (SIZE_TYPE, "unsigned int") == 0)
  if (strcmp (SIZE_TYPE, "unsigned int") == 0)
    return INT_TYPE_SIZE;
    return INT_TYPE_SIZE;
  if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
  if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
    return LONG_TYPE_SIZE;
    return LONG_TYPE_SIZE;
  if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
  if (strcmp (SIZE_TYPE, "short unsigned int") == 0)
    return SHORT_TYPE_SIZE;
    return SHORT_TYPE_SIZE;
  gcc_unreachable ();
  gcc_unreachable ();
#else
#else
  return LONG_TYPE_SIZE;
  return LONG_TYPE_SIZE;
#endif
#endif
}
}
#endif
#endif
 
 
/* Create the backend type nodes. We map them to their
/* Create the backend type nodes. We map them to their
   equivalent C type, at least for now.  We also give
   equivalent C type, at least for now.  We also give
   names to the types here, and we push them in the
   names to the types here, and we push them in the
   global binding level context.*/
   global binding level context.*/
 
 
void
void
gfc_init_types (void)
gfc_init_types (void)
{
{
  char name_buf[18];
  char name_buf[18];
  int index;
  int index;
  tree type;
  tree type;
  unsigned n;
  unsigned n;
  unsigned HOST_WIDE_INT hi;
  unsigned HOST_WIDE_INT hi;
  unsigned HOST_WIDE_INT lo;
  unsigned HOST_WIDE_INT lo;
 
 
  /* Create and name the types.  */
  /* Create and name the types.  */
#define PUSH_TYPE(name, node) \
#define PUSH_TYPE(name, node) \
  pushdecl (build_decl (input_location, \
  pushdecl (build_decl (input_location, \
                        TYPE_DECL, get_identifier (name), node))
                        TYPE_DECL, get_identifier (name), node))
 
 
  for (index = 0; gfc_integer_kinds[index].kind != 0; ++index)
  for (index = 0; gfc_integer_kinds[index].kind != 0; ++index)
    {
    {
      type = gfc_build_int_type (&gfc_integer_kinds[index]);
      type = gfc_build_int_type (&gfc_integer_kinds[index]);
      /* Ensure integer(kind=1) doesn't have TYPE_STRING_FLAG set.  */
      /* Ensure integer(kind=1) doesn't have TYPE_STRING_FLAG set.  */
      if (TYPE_STRING_FLAG (type))
      if (TYPE_STRING_FLAG (type))
        type = make_signed_type (gfc_integer_kinds[index].bit_size);
        type = make_signed_type (gfc_integer_kinds[index].bit_size);
      gfc_integer_types[index] = type;
      gfc_integer_types[index] = type;
      snprintf (name_buf, sizeof(name_buf), "integer(kind=%d)",
      snprintf (name_buf, sizeof(name_buf), "integer(kind=%d)",
                gfc_integer_kinds[index].kind);
                gfc_integer_kinds[index].kind);
      PUSH_TYPE (name_buf, type);
      PUSH_TYPE (name_buf, type);
    }
    }
 
 
  for (index = 0; gfc_logical_kinds[index].kind != 0; ++index)
  for (index = 0; gfc_logical_kinds[index].kind != 0; ++index)
    {
    {
      type = gfc_build_logical_type (&gfc_logical_kinds[index]);
      type = gfc_build_logical_type (&gfc_logical_kinds[index]);
      gfc_logical_types[index] = type;
      gfc_logical_types[index] = type;
      snprintf (name_buf, sizeof(name_buf), "logical(kind=%d)",
      snprintf (name_buf, sizeof(name_buf), "logical(kind=%d)",
                gfc_logical_kinds[index].kind);
                gfc_logical_kinds[index].kind);
      PUSH_TYPE (name_buf, type);
      PUSH_TYPE (name_buf, type);
    }
    }
 
 
  for (index = 0; gfc_real_kinds[index].kind != 0; index++)
  for (index = 0; gfc_real_kinds[index].kind != 0; index++)
    {
    {
      type = gfc_build_real_type (&gfc_real_kinds[index]);
      type = gfc_build_real_type (&gfc_real_kinds[index]);
      gfc_real_types[index] = type;
      gfc_real_types[index] = type;
      snprintf (name_buf, sizeof(name_buf), "real(kind=%d)",
      snprintf (name_buf, sizeof(name_buf), "real(kind=%d)",
                gfc_real_kinds[index].kind);
                gfc_real_kinds[index].kind);
      PUSH_TYPE (name_buf, type);
      PUSH_TYPE (name_buf, type);
 
 
      type = gfc_build_complex_type (type);
      type = gfc_build_complex_type (type);
      gfc_complex_types[index] = type;
      gfc_complex_types[index] = type;
      snprintf (name_buf, sizeof(name_buf), "complex(kind=%d)",
      snprintf (name_buf, sizeof(name_buf), "complex(kind=%d)",
                gfc_real_kinds[index].kind);
                gfc_real_kinds[index].kind);
      PUSH_TYPE (name_buf, type);
      PUSH_TYPE (name_buf, type);
    }
    }
 
 
  for (index = 0; gfc_character_kinds[index].kind != 0; ++index)
  for (index = 0; gfc_character_kinds[index].kind != 0; ++index)
    {
    {
      type = gfc_build_uint_type (gfc_character_kinds[index].bit_size);
      type = gfc_build_uint_type (gfc_character_kinds[index].bit_size);
      type = build_qualified_type (type, TYPE_UNQUALIFIED);
      type = build_qualified_type (type, TYPE_UNQUALIFIED);
      snprintf (name_buf, sizeof(name_buf), "character(kind=%d)",
      snprintf (name_buf, sizeof(name_buf), "character(kind=%d)",
                gfc_character_kinds[index].kind);
                gfc_character_kinds[index].kind);
      PUSH_TYPE (name_buf, type);
      PUSH_TYPE (name_buf, type);
      gfc_character_types[index] = type;
      gfc_character_types[index] = type;
      gfc_pcharacter_types[index] = build_pointer_type (type);
      gfc_pcharacter_types[index] = build_pointer_type (type);
    }
    }
  gfc_character1_type_node = gfc_character_types[0];
  gfc_character1_type_node = gfc_character_types[0];
 
 
  PUSH_TYPE ("byte", unsigned_char_type_node);
  PUSH_TYPE ("byte", unsigned_char_type_node);
  PUSH_TYPE ("void", void_type_node);
  PUSH_TYPE ("void", void_type_node);
 
 
  /* DBX debugging output gets upset if these aren't set.  */
  /* DBX debugging output gets upset if these aren't set.  */
  if (!TYPE_NAME (integer_type_node))
  if (!TYPE_NAME (integer_type_node))
    PUSH_TYPE ("c_integer", integer_type_node);
    PUSH_TYPE ("c_integer", integer_type_node);
  if (!TYPE_NAME (char_type_node))
  if (!TYPE_NAME (char_type_node))
    PUSH_TYPE ("c_char", char_type_node);
    PUSH_TYPE ("c_char", char_type_node);
 
 
#undef PUSH_TYPE
#undef PUSH_TYPE
 
 
  pvoid_type_node = build_pointer_type (void_type_node);
  pvoid_type_node = build_pointer_type (void_type_node);
  prvoid_type_node = build_qualified_type (pvoid_type_node, TYPE_QUAL_RESTRICT);
  prvoid_type_node = build_qualified_type (pvoid_type_node, TYPE_QUAL_RESTRICT);
  ppvoid_type_node = build_pointer_type (pvoid_type_node);
  ppvoid_type_node = build_pointer_type (pvoid_type_node);
  pchar_type_node = build_pointer_type (gfc_character1_type_node);
  pchar_type_node = build_pointer_type (gfc_character1_type_node);
  pfunc_type_node
  pfunc_type_node
    = build_pointer_type (build_function_type (void_type_node, NULL_TREE));
    = build_pointer_type (build_function_type (void_type_node, NULL_TREE));
 
 
  gfc_array_index_type = gfc_get_int_type (gfc_index_integer_kind);
  gfc_array_index_type = gfc_get_int_type (gfc_index_integer_kind);
  /* We cannot use gfc_index_zero_node in definition of gfc_array_range_type,
  /* We cannot use gfc_index_zero_node in definition of gfc_array_range_type,
     since this function is called before gfc_init_constants.  */
     since this function is called before gfc_init_constants.  */
  gfc_array_range_type
  gfc_array_range_type
          = build_range_type (gfc_array_index_type,
          = build_range_type (gfc_array_index_type,
                              build_int_cst (gfc_array_index_type, 0),
                              build_int_cst (gfc_array_index_type, 0),
                              NULL_TREE);
                              NULL_TREE);
 
 
  /* The maximum array element size that can be handled is determined
  /* The maximum array element size that can be handled is determined
     by the number of bits available to store this field in the array
     by the number of bits available to store this field in the array
     descriptor.  */
     descriptor.  */
 
 
  n = TYPE_PRECISION (gfc_array_index_type) - GFC_DTYPE_SIZE_SHIFT;
  n = TYPE_PRECISION (gfc_array_index_type) - GFC_DTYPE_SIZE_SHIFT;
  lo = ~ (unsigned HOST_WIDE_INT) 0;
  lo = ~ (unsigned HOST_WIDE_INT) 0;
  if (n > HOST_BITS_PER_WIDE_INT)
  if (n > HOST_BITS_PER_WIDE_INT)
    hi = lo >> (2*HOST_BITS_PER_WIDE_INT - n);
    hi = lo >> (2*HOST_BITS_PER_WIDE_INT - n);
  else
  else
    hi = 0, lo >>= HOST_BITS_PER_WIDE_INT - n;
    hi = 0, lo >>= HOST_BITS_PER_WIDE_INT - n;
  gfc_max_array_element_size
  gfc_max_array_element_size
    = build_int_cst_wide (long_unsigned_type_node, lo, hi);
    = build_int_cst_wide (long_unsigned_type_node, lo, hi);
 
 
  size_type_node = gfc_array_index_type;
  size_type_node = gfc_array_index_type;
 
 
  boolean_type_node = gfc_get_logical_type (gfc_default_logical_kind);
  boolean_type_node = gfc_get_logical_type (gfc_default_logical_kind);
  boolean_true_node = build_int_cst (boolean_type_node, 1);
  boolean_true_node = build_int_cst (boolean_type_node, 1);
  boolean_false_node = build_int_cst (boolean_type_node, 0);
  boolean_false_node = build_int_cst (boolean_type_node, 0);
 
 
  /* ??? Shouldn't this be based on gfc_index_integer_kind or so?  */
  /* ??? Shouldn't this be based on gfc_index_integer_kind or so?  */
  gfc_charlen_int_kind = 4;
  gfc_charlen_int_kind = 4;
  gfc_charlen_type_node = gfc_get_int_type (gfc_charlen_int_kind);
  gfc_charlen_type_node = gfc_get_int_type (gfc_charlen_int_kind);
}
}
 
 
/* Get the type node for the given type and kind.  */
/* Get the type node for the given type and kind.  */
 
 
tree
tree
gfc_get_int_type (int kind)
gfc_get_int_type (int kind)
{
{
  int index = gfc_validate_kind (BT_INTEGER, kind, true);
  int index = gfc_validate_kind (BT_INTEGER, kind, true);
  return index < 0 ? 0 : gfc_integer_types[index];
  return index < 0 ? 0 : gfc_integer_types[index];
}
}
 
 
tree
tree
gfc_get_real_type (int kind)
gfc_get_real_type (int kind)
{
{
  int index = gfc_validate_kind (BT_REAL, kind, true);
  int index = gfc_validate_kind (BT_REAL, kind, true);
  return index < 0 ? 0 : gfc_real_types[index];
  return index < 0 ? 0 : gfc_real_types[index];
}
}
 
 
tree
tree
gfc_get_complex_type (int kind)
gfc_get_complex_type (int kind)
{
{
  int index = gfc_validate_kind (BT_COMPLEX, kind, true);
  int index = gfc_validate_kind (BT_COMPLEX, kind, true);
  return index < 0 ? 0 : gfc_complex_types[index];
  return index < 0 ? 0 : gfc_complex_types[index];
}
}
 
 
tree
tree
gfc_get_logical_type (int kind)
gfc_get_logical_type (int kind)
{
{
  int index = gfc_validate_kind (BT_LOGICAL, kind, true);
  int index = gfc_validate_kind (BT_LOGICAL, kind, true);
  return index < 0 ? 0 : gfc_logical_types[index];
  return index < 0 ? 0 : gfc_logical_types[index];
}
}
 
 
tree
tree
gfc_get_char_type (int kind)
gfc_get_char_type (int kind)
{
{
  int index = gfc_validate_kind (BT_CHARACTER, kind, true);
  int index = gfc_validate_kind (BT_CHARACTER, kind, true);
  return index < 0 ? 0 : gfc_character_types[index];
  return index < 0 ? 0 : gfc_character_types[index];
}
}
 
 
tree
tree
gfc_get_pchar_type (int kind)
gfc_get_pchar_type (int kind)
{
{
  int index = gfc_validate_kind (BT_CHARACTER, kind, true);
  int index = gfc_validate_kind (BT_CHARACTER, kind, true);
  return index < 0 ? 0 : gfc_pcharacter_types[index];
  return index < 0 ? 0 : gfc_pcharacter_types[index];
}
}
 
 


/* Create a character type with the given kind and length.  */
/* Create a character type with the given kind and length.  */
 
 
tree
tree
gfc_get_character_type_len_for_eltype (tree eltype, tree len)
gfc_get_character_type_len_for_eltype (tree eltype, tree len)
{
{
  tree bounds, type;
  tree bounds, type;
 
 
  bounds = build_range_type (gfc_charlen_type_node, gfc_index_one_node, len);
  bounds = build_range_type (gfc_charlen_type_node, gfc_index_one_node, len);
  type = build_array_type (eltype, bounds);
  type = build_array_type (eltype, bounds);
  TYPE_STRING_FLAG (type) = 1;
  TYPE_STRING_FLAG (type) = 1;
 
 
  return type;
  return type;
}
}
 
 
tree
tree
gfc_get_character_type_len (int kind, tree len)
gfc_get_character_type_len (int kind, tree len)
{
{
  gfc_validate_kind (BT_CHARACTER, kind, false);
  gfc_validate_kind (BT_CHARACTER, kind, false);
  return gfc_get_character_type_len_for_eltype (gfc_get_char_type (kind), len);
  return gfc_get_character_type_len_for_eltype (gfc_get_char_type (kind), len);
}
}
 
 
 
 
/* Get a type node for a character kind.  */
/* Get a type node for a character kind.  */
 
 
tree
tree
gfc_get_character_type (int kind, gfc_charlen * cl)
gfc_get_character_type (int kind, gfc_charlen * cl)
{
{
  tree len;
  tree len;
 
 
  len = (cl == NULL) ? NULL_TREE : cl->backend_decl;
  len = (cl == NULL) ? NULL_TREE : cl->backend_decl;
 
 
  return gfc_get_character_type_len (kind, len);
  return gfc_get_character_type_len (kind, len);
}
}


/* Covert a basic type.  This will be an array for character types.  */
/* Covert a basic type.  This will be an array for character types.  */
 
 
tree
tree
gfc_typenode_for_spec (gfc_typespec * spec)
gfc_typenode_for_spec (gfc_typespec * spec)
{
{
  tree basetype;
  tree basetype;
 
 
  switch (spec->type)
  switch (spec->type)
    {
    {
    case BT_UNKNOWN:
    case BT_UNKNOWN:
      gcc_unreachable ();
      gcc_unreachable ();
 
 
    case BT_INTEGER:
    case BT_INTEGER:
      /* We use INTEGER(c_intptr_t) for C_PTR and C_FUNPTR once the symbol
      /* We use INTEGER(c_intptr_t) for C_PTR and C_FUNPTR once the symbol
         has been resolved.  This is done so we can convert C_PTR and
         has been resolved.  This is done so we can convert C_PTR and
         C_FUNPTR to simple variables that get translated to (void *).  */
         C_FUNPTR to simple variables that get translated to (void *).  */
      if (spec->f90_type == BT_VOID)
      if (spec->f90_type == BT_VOID)
        {
        {
          if (spec->u.derived
          if (spec->u.derived
              && spec->u.derived->intmod_sym_id == ISOCBINDING_PTR)
              && spec->u.derived->intmod_sym_id == ISOCBINDING_PTR)
            basetype = ptr_type_node;
            basetype = ptr_type_node;
          else
          else
            basetype = pfunc_type_node;
            basetype = pfunc_type_node;
        }
        }
      else
      else
        basetype = gfc_get_int_type (spec->kind);
        basetype = gfc_get_int_type (spec->kind);
      break;
      break;
 
 
    case BT_REAL:
    case BT_REAL:
      basetype = gfc_get_real_type (spec->kind);
      basetype = gfc_get_real_type (spec->kind);
      break;
      break;
 
 
    case BT_COMPLEX:
    case BT_COMPLEX:
      basetype = gfc_get_complex_type (spec->kind);
      basetype = gfc_get_complex_type (spec->kind);
      break;
      break;
 
 
    case BT_LOGICAL:
    case BT_LOGICAL:
      basetype = gfc_get_logical_type (spec->kind);
      basetype = gfc_get_logical_type (spec->kind);
      break;
      break;
 
 
    case BT_CHARACTER:
    case BT_CHARACTER:
      basetype = gfc_get_character_type (spec->kind, spec->u.cl);
      basetype = gfc_get_character_type (spec->kind, spec->u.cl);
      break;
      break;
 
 
    case BT_DERIVED:
    case BT_DERIVED:
    case BT_CLASS:
    case BT_CLASS:
      basetype = gfc_get_derived_type (spec->u.derived);
      basetype = gfc_get_derived_type (spec->u.derived);
 
 
      /* If we're dealing with either C_PTR or C_FUNPTR, we modified the
      /* If we're dealing with either C_PTR or C_FUNPTR, we modified the
         type and kind to fit a (void *) and the basetype returned was a
         type and kind to fit a (void *) and the basetype returned was a
         ptr_type_node.  We need to pass up this new information to the
         ptr_type_node.  We need to pass up this new information to the
         symbol that was declared of type C_PTR or C_FUNPTR.  */
         symbol that was declared of type C_PTR or C_FUNPTR.  */
      if (spec->u.derived->attr.is_iso_c)
      if (spec->u.derived->attr.is_iso_c)
        {
        {
          spec->type = spec->u.derived->ts.type;
          spec->type = spec->u.derived->ts.type;
          spec->kind = spec->u.derived->ts.kind;
          spec->kind = spec->u.derived->ts.kind;
          spec->f90_type = spec->u.derived->ts.f90_type;
          spec->f90_type = spec->u.derived->ts.f90_type;
        }
        }
      break;
      break;
    case BT_VOID:
    case BT_VOID:
      /* This is for the second arg to c_f_pointer and c_f_procpointer
      /* This is for the second arg to c_f_pointer and c_f_procpointer
         of the iso_c_binding module, to accept any ptr type.  */
         of the iso_c_binding module, to accept any ptr type.  */
      basetype = ptr_type_node;
      basetype = ptr_type_node;
      if (spec->f90_type == BT_VOID)
      if (spec->f90_type == BT_VOID)
        {
        {
          if (spec->u.derived
          if (spec->u.derived
              && spec->u.derived->intmod_sym_id == ISOCBINDING_PTR)
              && spec->u.derived->intmod_sym_id == ISOCBINDING_PTR)
            basetype = ptr_type_node;
            basetype = ptr_type_node;
          else
          else
            basetype = pfunc_type_node;
            basetype = pfunc_type_node;
        }
        }
       break;
       break;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
  return basetype;
  return basetype;
}
}


/* Build an INT_CST for constant expressions, otherwise return NULL_TREE.  */
/* Build an INT_CST for constant expressions, otherwise return NULL_TREE.  */
 
 
static tree
static tree
gfc_conv_array_bound (gfc_expr * expr)
gfc_conv_array_bound (gfc_expr * expr)
{
{
  /* If expr is an integer constant, return that.  */
  /* If expr is an integer constant, return that.  */
  if (expr != NULL && expr->expr_type == EXPR_CONSTANT)
  if (expr != NULL && expr->expr_type == EXPR_CONSTANT)
    return gfc_conv_mpz_to_tree (expr->value.integer, gfc_index_integer_kind);
    return gfc_conv_mpz_to_tree (expr->value.integer, gfc_index_integer_kind);
 
 
  /* Otherwise return NULL.  */
  /* Otherwise return NULL.  */
  return NULL_TREE;
  return NULL_TREE;
}
}


tree
tree
gfc_get_element_type (tree type)
gfc_get_element_type (tree type)
{
{
  tree element;
  tree element;
 
 
  if (GFC_ARRAY_TYPE_P (type))
  if (GFC_ARRAY_TYPE_P (type))
    {
    {
      if (TREE_CODE (type) == POINTER_TYPE)
      if (TREE_CODE (type) == POINTER_TYPE)
        type = TREE_TYPE (type);
        type = TREE_TYPE (type);
      gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
      gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
      element = TREE_TYPE (type);
      element = TREE_TYPE (type);
    }
    }
  else
  else
    {
    {
      gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
      gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
      element = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
      element = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
 
 
      gcc_assert (TREE_CODE (element) == POINTER_TYPE);
      gcc_assert (TREE_CODE (element) == POINTER_TYPE);
      element = TREE_TYPE (element);
      element = TREE_TYPE (element);
 
 
      gcc_assert (TREE_CODE (element) == ARRAY_TYPE);
      gcc_assert (TREE_CODE (element) == ARRAY_TYPE);
      element = TREE_TYPE (element);
      element = TREE_TYPE (element);
    }
    }
 
 
  return element;
  return element;
}
}


/* Build an array.  This function is called from gfc_sym_type().
/* Build an array.  This function is called from gfc_sym_type().
   Actually returns array descriptor type.
   Actually returns array descriptor type.
 
 
   Format of array descriptors is as follows:
   Format of array descriptors is as follows:
 
 
    struct gfc_array_descriptor
    struct gfc_array_descriptor
    {
    {
      array *data
      array *data
      index offset;
      index offset;
      index dtype;
      index dtype;
      struct descriptor_dimension dimension[N_DIM];
      struct descriptor_dimension dimension[N_DIM];
    }
    }
 
 
    struct descriptor_dimension
    struct descriptor_dimension
    {
    {
      index stride;
      index stride;
      index lbound;
      index lbound;
      index ubound;
      index ubound;
    }
    }
 
 
   Translation code should use gfc_conv_descriptor_* rather than
   Translation code should use gfc_conv_descriptor_* rather than
   accessing the descriptor directly.  Any changes to the array
   accessing the descriptor directly.  Any changes to the array
   descriptor type will require changes in gfc_conv_descriptor_* and
   descriptor type will require changes in gfc_conv_descriptor_* and
   gfc_build_array_initializer.
   gfc_build_array_initializer.
 
 
   This is represented internally as a RECORD_TYPE. The index nodes
   This is represented internally as a RECORD_TYPE. The index nodes
   are gfc_array_index_type and the data node is a pointer to the
   are gfc_array_index_type and the data node is a pointer to the
   data.  See below for the handling of character types.
   data.  See below for the handling of character types.
 
 
   The dtype member is formatted as follows:
   The dtype member is formatted as follows:
    rank = dtype & GFC_DTYPE_RANK_MASK // 3 bits
    rank = dtype & GFC_DTYPE_RANK_MASK // 3 bits
    type = (dtype & GFC_DTYPE_TYPE_MASK) >> GFC_DTYPE_TYPE_SHIFT // 3 bits
    type = (dtype & GFC_DTYPE_TYPE_MASK) >> GFC_DTYPE_TYPE_SHIFT // 3 bits
    size = dtype >> GFC_DTYPE_SIZE_SHIFT
    size = dtype >> GFC_DTYPE_SIZE_SHIFT
 
 
   I originally used nested ARRAY_TYPE nodes to represent arrays, but
   I originally used nested ARRAY_TYPE nodes to represent arrays, but
   this generated poor code for assumed/deferred size arrays.  These
   this generated poor code for assumed/deferred size arrays.  These
   require use of PLACEHOLDER_EXPR/WITH_RECORD_EXPR, which isn't part
   require use of PLACEHOLDER_EXPR/WITH_RECORD_EXPR, which isn't part
   of the GENERIC grammar.  Also, there is no way to explicitly set
   of the GENERIC grammar.  Also, there is no way to explicitly set
   the array stride, so all data must be packed(1).  I've tried to
   the array stride, so all data must be packed(1).  I've tried to
   mark all the functions which would require modification with a GCC
   mark all the functions which would require modification with a GCC
   ARRAYS comment.
   ARRAYS comment.
 
 
   The data component points to the first element in the array.  The
   The data component points to the first element in the array.  The
   offset field is the position of the origin of the array (i.e. element
   offset field is the position of the origin of the array (i.e. element
   (0, 0 ...)).  This may be outside the bounds of the array.
   (0, 0 ...)).  This may be outside the bounds of the array.
 
 
   An element is accessed by
   An element is accessed by
    data[offset + index0*stride0 + index1*stride1 + index2*stride2]
    data[offset + index0*stride0 + index1*stride1 + index2*stride2]
   This gives good performance as the computation does not involve the
   This gives good performance as the computation does not involve the
   bounds of the array.  For packed arrays, this is optimized further
   bounds of the array.  For packed arrays, this is optimized further
   by substituting the known strides.
   by substituting the known strides.
 
 
   This system has one problem: all array bounds must be within 2^31
   This system has one problem: all array bounds must be within 2^31
   elements of the origin (2^63 on 64-bit machines).  For example
   elements of the origin (2^63 on 64-bit machines).  For example
    integer, dimension (80000:90000, 80000:90000, 2) :: array
    integer, dimension (80000:90000, 80000:90000, 2) :: array
   may not work properly on 32-bit machines because 80000*80000 >
   may not work properly on 32-bit machines because 80000*80000 >
   2^31, so the calculation for stride2 would overflow.  This may
   2^31, so the calculation for stride2 would overflow.  This may
   still work, but I haven't checked, and it relies on the overflow
   still work, but I haven't checked, and it relies on the overflow
   doing the right thing.
   doing the right thing.
 
 
   The way to fix this problem is to access elements as follows:
   The way to fix this problem is to access elements as follows:
    data[(index0-lbound0)*stride0 + (index1-lbound1)*stride1]
    data[(index0-lbound0)*stride0 + (index1-lbound1)*stride1]
   Obviously this is much slower.  I will make this a compile time
   Obviously this is much slower.  I will make this a compile time
   option, something like -fsmall-array-offsets.  Mixing code compiled
   option, something like -fsmall-array-offsets.  Mixing code compiled
   with and without this switch will work.
   with and without this switch will work.
 
 
   (1) This can be worked around by modifying the upper bound of the
   (1) This can be worked around by modifying the upper bound of the
   previous dimension.  This requires extra fields in the descriptor
   previous dimension.  This requires extra fields in the descriptor
   (both real_ubound and fake_ubound).  */
   (both real_ubound and fake_ubound).  */
 
 
 
 
/* Returns true if the array sym does not require a descriptor.  */
/* Returns true if the array sym does not require a descriptor.  */
 
 
int
int
gfc_is_nodesc_array (gfc_symbol * sym)
gfc_is_nodesc_array (gfc_symbol * sym)
{
{
  gcc_assert (sym->attr.dimension);
  gcc_assert (sym->attr.dimension);
 
 
  /* We only want local arrays.  */
  /* We only want local arrays.  */
  if (sym->attr.pointer || sym->attr.allocatable)
  if (sym->attr.pointer || sym->attr.allocatable)
    return 0;
    return 0;
 
 
  if (sym->attr.dummy)
  if (sym->attr.dummy)
    {
    {
      if (sym->as->type != AS_ASSUMED_SHAPE)
      if (sym->as->type != AS_ASSUMED_SHAPE)
        return 1;
        return 1;
      else
      else
        return 0;
        return 0;
    }
    }
 
 
  if (sym->attr.result || sym->attr.function)
  if (sym->attr.result || sym->attr.function)
    return 0;
    return 0;
 
 
  gcc_assert (sym->as->type == AS_EXPLICIT || sym->as->cp_was_assumed);
  gcc_assert (sym->as->type == AS_EXPLICIT || sym->as->cp_was_assumed);
 
 
  return 1;
  return 1;
}
}
 
 
 
 
/* Create an array descriptor type.  */
/* Create an array descriptor type.  */
 
 
static tree
static tree
gfc_build_array_type (tree type, gfc_array_spec * as,
gfc_build_array_type (tree type, gfc_array_spec * as,
                      enum gfc_array_kind akind, bool restricted)
                      enum gfc_array_kind akind, bool restricted)
{
{
  tree lbound[GFC_MAX_DIMENSIONS];
  tree lbound[GFC_MAX_DIMENSIONS];
  tree ubound[GFC_MAX_DIMENSIONS];
  tree ubound[GFC_MAX_DIMENSIONS];
  int n;
  int n;
 
 
  for (n = 0; n < as->rank; n++)
  for (n = 0; n < as->rank; n++)
    {
    {
      /* Create expressions for the known bounds of the array.  */
      /* Create expressions for the known bounds of the array.  */
      if (as->type == AS_ASSUMED_SHAPE && as->lower[n] == NULL)
      if (as->type == AS_ASSUMED_SHAPE && as->lower[n] == NULL)
        lbound[n] = gfc_index_one_node;
        lbound[n] = gfc_index_one_node;
      else
      else
        lbound[n] = gfc_conv_array_bound (as->lower[n]);
        lbound[n] = gfc_conv_array_bound (as->lower[n]);
      ubound[n] = gfc_conv_array_bound (as->upper[n]);
      ubound[n] = gfc_conv_array_bound (as->upper[n]);
    }
    }
 
 
  if (as->type == AS_ASSUMED_SHAPE)
  if (as->type == AS_ASSUMED_SHAPE)
    akind = GFC_ARRAY_ASSUMED_SHAPE;
    akind = GFC_ARRAY_ASSUMED_SHAPE;
  return gfc_get_array_type_bounds (type, as->rank, lbound, ubound, 0, akind,
  return gfc_get_array_type_bounds (type, as->rank, lbound, ubound, 0, akind,
                                    restricted);
                                    restricted);
}
}


/* Returns the struct descriptor_dimension type.  */
/* Returns the struct descriptor_dimension type.  */
 
 
static tree
static tree
gfc_get_desc_dim_type (void)
gfc_get_desc_dim_type (void)
{
{
  tree type;
  tree type;
  tree decl;
  tree decl;
  tree fieldlist;
  tree fieldlist;
 
 
  if (gfc_desc_dim_type)
  if (gfc_desc_dim_type)
    return gfc_desc_dim_type;
    return gfc_desc_dim_type;
 
 
  /* Build the type node.  */
  /* Build the type node.  */
  type = make_node (RECORD_TYPE);
  type = make_node (RECORD_TYPE);
 
 
  TYPE_NAME (type) = get_identifier ("descriptor_dimension");
  TYPE_NAME (type) = get_identifier ("descriptor_dimension");
  TYPE_PACKED (type) = 1;
  TYPE_PACKED (type) = 1;
 
 
  /* Consists of the stride, lbound and ubound members.  */
  /* Consists of the stride, lbound and ubound members.  */
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL,
                     FIELD_DECL,
                     get_identifier ("stride"), gfc_array_index_type);
                     get_identifier ("stride"), gfc_array_index_type);
  DECL_CONTEXT (decl) = type;
  DECL_CONTEXT (decl) = type;
  TREE_NO_WARNING (decl) = 1;
  TREE_NO_WARNING (decl) = 1;
  fieldlist = decl;
  fieldlist = decl;
 
 
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL,
                     FIELD_DECL,
                     get_identifier ("lbound"), gfc_array_index_type);
                     get_identifier ("lbound"), gfc_array_index_type);
  DECL_CONTEXT (decl) = type;
  DECL_CONTEXT (decl) = type;
  TREE_NO_WARNING (decl) = 1;
  TREE_NO_WARNING (decl) = 1;
  fieldlist = chainon (fieldlist, decl);
  fieldlist = chainon (fieldlist, decl);
 
 
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL,
                     FIELD_DECL,
                     get_identifier ("ubound"), gfc_array_index_type);
                     get_identifier ("ubound"), gfc_array_index_type);
  DECL_CONTEXT (decl) = type;
  DECL_CONTEXT (decl) = type;
  TREE_NO_WARNING (decl) = 1;
  TREE_NO_WARNING (decl) = 1;
  fieldlist = chainon (fieldlist, decl);
  fieldlist = chainon (fieldlist, decl);
 
 
  /* Finish off the type.  */
  /* Finish off the type.  */
  TYPE_FIELDS (type) = fieldlist;
  TYPE_FIELDS (type) = fieldlist;
 
 
  gfc_finish_type (type);
  gfc_finish_type (type);
  TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
  TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
 
 
  gfc_desc_dim_type = type;
  gfc_desc_dim_type = type;
  return type;
  return type;
}
}
 
 
 
 
/* Return the DTYPE for an array.  This describes the type and type parameters
/* Return the DTYPE for an array.  This describes the type and type parameters
   of the array.  */
   of the array.  */
/* TODO: Only call this when the value is actually used, and make all the
/* TODO: Only call this when the value is actually used, and make all the
   unknown cases abort.  */
   unknown cases abort.  */
 
 
tree
tree
gfc_get_dtype (tree type)
gfc_get_dtype (tree type)
{
{
  tree size;
  tree size;
  int n;
  int n;
  HOST_WIDE_INT i;
  HOST_WIDE_INT i;
  tree tmp;
  tree tmp;
  tree dtype;
  tree dtype;
  tree etype;
  tree etype;
  int rank;
  int rank;
 
 
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type));
  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type));
 
 
  if (GFC_TYPE_ARRAY_DTYPE (type))
  if (GFC_TYPE_ARRAY_DTYPE (type))
    return GFC_TYPE_ARRAY_DTYPE (type);
    return GFC_TYPE_ARRAY_DTYPE (type);
 
 
  rank = GFC_TYPE_ARRAY_RANK (type);
  rank = GFC_TYPE_ARRAY_RANK (type);
  etype = gfc_get_element_type (type);
  etype = gfc_get_element_type (type);
 
 
  switch (TREE_CODE (etype))
  switch (TREE_CODE (etype))
    {
    {
    case INTEGER_TYPE:
    case INTEGER_TYPE:
      n = GFC_DTYPE_INTEGER;
      n = GFC_DTYPE_INTEGER;
      break;
      break;
 
 
    case BOOLEAN_TYPE:
    case BOOLEAN_TYPE:
      n = GFC_DTYPE_LOGICAL;
      n = GFC_DTYPE_LOGICAL;
      break;
      break;
 
 
    case REAL_TYPE:
    case REAL_TYPE:
      n = GFC_DTYPE_REAL;
      n = GFC_DTYPE_REAL;
      break;
      break;
 
 
    case COMPLEX_TYPE:
    case COMPLEX_TYPE:
      n = GFC_DTYPE_COMPLEX;
      n = GFC_DTYPE_COMPLEX;
      break;
      break;
 
 
    /* We will never have arrays of arrays.  */
    /* We will never have arrays of arrays.  */
    case RECORD_TYPE:
    case RECORD_TYPE:
      n = GFC_DTYPE_DERIVED;
      n = GFC_DTYPE_DERIVED;
      break;
      break;
 
 
    case ARRAY_TYPE:
    case ARRAY_TYPE:
      n = GFC_DTYPE_CHARACTER;
      n = GFC_DTYPE_CHARACTER;
      break;
      break;
 
 
    default:
    default:
      /* TODO: Don't do dtype for temporary descriptorless arrays.  */
      /* TODO: Don't do dtype for temporary descriptorless arrays.  */
      /* We can strange array types for temporary arrays.  */
      /* We can strange array types for temporary arrays.  */
      return gfc_index_zero_node;
      return gfc_index_zero_node;
    }
    }
 
 
  gcc_assert (rank <= GFC_DTYPE_RANK_MASK);
  gcc_assert (rank <= GFC_DTYPE_RANK_MASK);
  size = TYPE_SIZE_UNIT (etype);
  size = TYPE_SIZE_UNIT (etype);
 
 
  i = rank | (n << GFC_DTYPE_TYPE_SHIFT);
  i = rank | (n << GFC_DTYPE_TYPE_SHIFT);
  if (size && INTEGER_CST_P (size))
  if (size && INTEGER_CST_P (size))
    {
    {
      if (tree_int_cst_lt (gfc_max_array_element_size, size))
      if (tree_int_cst_lt (gfc_max_array_element_size, size))
        internal_error ("Array element size too big");
        internal_error ("Array element size too big");
 
 
      i += TREE_INT_CST_LOW (size) << GFC_DTYPE_SIZE_SHIFT;
      i += TREE_INT_CST_LOW (size) << GFC_DTYPE_SIZE_SHIFT;
    }
    }
  dtype = build_int_cst (gfc_array_index_type, i);
  dtype = build_int_cst (gfc_array_index_type, i);
 
 
  if (size && !INTEGER_CST_P (size))
  if (size && !INTEGER_CST_P (size))
    {
    {
      tmp = build_int_cst (gfc_array_index_type, GFC_DTYPE_SIZE_SHIFT);
      tmp = build_int_cst (gfc_array_index_type, GFC_DTYPE_SIZE_SHIFT);
      tmp  = fold_build2 (LSHIFT_EXPR, gfc_array_index_type,
      tmp  = fold_build2 (LSHIFT_EXPR, gfc_array_index_type,
                          fold_convert (gfc_array_index_type, size), tmp);
                          fold_convert (gfc_array_index_type, size), tmp);
      dtype = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, dtype);
      dtype = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, dtype);
    }
    }
  /* If we don't know the size we leave it as zero.  This should never happen
  /* If we don't know the size we leave it as zero.  This should never happen
     for anything that is actually used.  */
     for anything that is actually used.  */
  /* TODO: Check this is actually true, particularly when repacking
  /* TODO: Check this is actually true, particularly when repacking
     assumed size parameters.  */
     assumed size parameters.  */
 
 
  GFC_TYPE_ARRAY_DTYPE (type) = dtype;
  GFC_TYPE_ARRAY_DTYPE (type) = dtype;
  return dtype;
  return dtype;
}
}
 
 
 
 
/* Build an array type for use without a descriptor, packed according
/* Build an array type for use without a descriptor, packed according
   to the value of PACKED.  */
   to the value of PACKED.  */
 
 
tree
tree
gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
                           bool restricted)
                           bool restricted)
{
{
  tree range;
  tree range;
  tree type;
  tree type;
  tree tmp;
  tree tmp;
  int n;
  int n;
  int known_stride;
  int known_stride;
  int known_offset;
  int known_offset;
  mpz_t offset;
  mpz_t offset;
  mpz_t stride;
  mpz_t stride;
  mpz_t delta;
  mpz_t delta;
  gfc_expr *expr;
  gfc_expr *expr;
 
 
  mpz_init_set_ui (offset, 0);
  mpz_init_set_ui (offset, 0);
  mpz_init_set_ui (stride, 1);
  mpz_init_set_ui (stride, 1);
  mpz_init (delta);
  mpz_init (delta);
 
 
  /* We don't use build_array_type because this does not include include
  /* We don't use build_array_type because this does not include include
     lang-specific information (i.e. the bounds of the array) when checking
     lang-specific information (i.e. the bounds of the array) when checking
     for duplicates.  */
     for duplicates.  */
  type = make_node (ARRAY_TYPE);
  type = make_node (ARRAY_TYPE);
 
 
  GFC_ARRAY_TYPE_P (type) = 1;
  GFC_ARRAY_TYPE_P (type) = 1;
  TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
  TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
    ggc_alloc_cleared (sizeof (struct lang_type));
    ggc_alloc_cleared (sizeof (struct lang_type));
 
 
  known_stride = (packed != PACKED_NO);
  known_stride = (packed != PACKED_NO);
  known_offset = 1;
  known_offset = 1;
  for (n = 0; n < as->rank; n++)
  for (n = 0; n < as->rank; n++)
    {
    {
      /* Fill in the stride and bound components of the type.  */
      /* Fill in the stride and bound components of the type.  */
      if (known_stride)
      if (known_stride)
        tmp = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
        tmp = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
      else
      else
        tmp = NULL_TREE;
        tmp = NULL_TREE;
      GFC_TYPE_ARRAY_STRIDE (type, n) = tmp;
      GFC_TYPE_ARRAY_STRIDE (type, n) = tmp;
 
 
      expr = as->lower[n];
      expr = as->lower[n];
      if (expr->expr_type == EXPR_CONSTANT)
      if (expr->expr_type == EXPR_CONSTANT)
        {
        {
          tmp = gfc_conv_mpz_to_tree (expr->value.integer,
          tmp = gfc_conv_mpz_to_tree (expr->value.integer,
                                      gfc_index_integer_kind);
                                      gfc_index_integer_kind);
        }
        }
      else
      else
        {
        {
          known_stride = 0;
          known_stride = 0;
          tmp = NULL_TREE;
          tmp = NULL_TREE;
        }
        }
      GFC_TYPE_ARRAY_LBOUND (type, n) = tmp;
      GFC_TYPE_ARRAY_LBOUND (type, n) = tmp;
 
 
      if (known_stride)
      if (known_stride)
        {
        {
          /* Calculate the offset.  */
          /* Calculate the offset.  */
          mpz_mul (delta, stride, as->lower[n]->value.integer);
          mpz_mul (delta, stride, as->lower[n]->value.integer);
          mpz_sub (offset, offset, delta);
          mpz_sub (offset, offset, delta);
        }
        }
      else
      else
        known_offset = 0;
        known_offset = 0;
 
 
      expr = as->upper[n];
      expr = as->upper[n];
      if (expr && expr->expr_type == EXPR_CONSTANT)
      if (expr && expr->expr_type == EXPR_CONSTANT)
        {
        {
          tmp = gfc_conv_mpz_to_tree (expr->value.integer,
          tmp = gfc_conv_mpz_to_tree (expr->value.integer,
                                  gfc_index_integer_kind);
                                  gfc_index_integer_kind);
        }
        }
      else
      else
        {
        {
          tmp = NULL_TREE;
          tmp = NULL_TREE;
          known_stride = 0;
          known_stride = 0;
        }
        }
      GFC_TYPE_ARRAY_UBOUND (type, n) = tmp;
      GFC_TYPE_ARRAY_UBOUND (type, n) = tmp;
 
 
      if (known_stride)
      if (known_stride)
        {
        {
          /* Calculate the stride.  */
          /* Calculate the stride.  */
          mpz_sub (delta, as->upper[n]->value.integer,
          mpz_sub (delta, as->upper[n]->value.integer,
                   as->lower[n]->value.integer);
                   as->lower[n]->value.integer);
          mpz_add_ui (delta, delta, 1);
          mpz_add_ui (delta, delta, 1);
          mpz_mul (stride, stride, delta);
          mpz_mul (stride, stride, delta);
        }
        }
 
 
      /* Only the first stride is known for partial packed arrays.  */
      /* Only the first stride is known for partial packed arrays.  */
      if (packed == PACKED_NO || packed == PACKED_PARTIAL)
      if (packed == PACKED_NO || packed == PACKED_PARTIAL)
        known_stride = 0;
        known_stride = 0;
    }
    }
 
 
  if (known_offset)
  if (known_offset)
    {
    {
      GFC_TYPE_ARRAY_OFFSET (type) =
      GFC_TYPE_ARRAY_OFFSET (type) =
        gfc_conv_mpz_to_tree (offset, gfc_index_integer_kind);
        gfc_conv_mpz_to_tree (offset, gfc_index_integer_kind);
    }
    }
  else
  else
    GFC_TYPE_ARRAY_OFFSET (type) = NULL_TREE;
    GFC_TYPE_ARRAY_OFFSET (type) = NULL_TREE;
 
 
  if (known_stride)
  if (known_stride)
    {
    {
      GFC_TYPE_ARRAY_SIZE (type) =
      GFC_TYPE_ARRAY_SIZE (type) =
        gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
        gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
    }
    }
  else
  else
    GFC_TYPE_ARRAY_SIZE (type) = NULL_TREE;
    GFC_TYPE_ARRAY_SIZE (type) = NULL_TREE;
 
 
  GFC_TYPE_ARRAY_RANK (type) = as->rank;
  GFC_TYPE_ARRAY_RANK (type) = as->rank;
  GFC_TYPE_ARRAY_DTYPE (type) = NULL_TREE;
  GFC_TYPE_ARRAY_DTYPE (type) = NULL_TREE;
  range = build_range_type (gfc_array_index_type, gfc_index_zero_node,
  range = build_range_type (gfc_array_index_type, gfc_index_zero_node,
                            NULL_TREE);
                            NULL_TREE);
  /* TODO: use main type if it is unbounded.  */
  /* TODO: use main type if it is unbounded.  */
  GFC_TYPE_ARRAY_DATAPTR_TYPE (type) =
  GFC_TYPE_ARRAY_DATAPTR_TYPE (type) =
    build_pointer_type (build_array_type (etype, range));
    build_pointer_type (build_array_type (etype, range));
  if (restricted)
  if (restricted)
    GFC_TYPE_ARRAY_DATAPTR_TYPE (type) =
    GFC_TYPE_ARRAY_DATAPTR_TYPE (type) =
      build_qualified_type (GFC_TYPE_ARRAY_DATAPTR_TYPE (type),
      build_qualified_type (GFC_TYPE_ARRAY_DATAPTR_TYPE (type),
                            TYPE_QUAL_RESTRICT);
                            TYPE_QUAL_RESTRICT);
 
 
  if (known_stride)
  if (known_stride)
    {
    {
      mpz_sub_ui (stride, stride, 1);
      mpz_sub_ui (stride, stride, 1);
      range = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
      range = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
    }
    }
  else
  else
    range = NULL_TREE;
    range = NULL_TREE;
 
 
  range = build_range_type (gfc_array_index_type, gfc_index_zero_node, range);
  range = build_range_type (gfc_array_index_type, gfc_index_zero_node, range);
  TYPE_DOMAIN (type) = range;
  TYPE_DOMAIN (type) = range;
 
 
  build_pointer_type (etype);
  build_pointer_type (etype);
  TREE_TYPE (type) = etype;
  TREE_TYPE (type) = etype;
 
 
  layout_type (type);
  layout_type (type);
 
 
  mpz_clear (offset);
  mpz_clear (offset);
  mpz_clear (stride);
  mpz_clear (stride);
  mpz_clear (delta);
  mpz_clear (delta);
 
 
  /* Represent packed arrays as multi-dimensional if they have rank >
  /* Represent packed arrays as multi-dimensional if they have rank >
     1 and with proper bounds, instead of flat arrays.  This makes for
     1 and with proper bounds, instead of flat arrays.  This makes for
     better debug info.  */
     better debug info.  */
  if (known_offset)
  if (known_offset)
    {
    {
      tree gtype = etype, rtype, type_decl;
      tree gtype = etype, rtype, type_decl;
 
 
      for (n = as->rank - 1; n >= 0; n--)
      for (n = as->rank - 1; n >= 0; n--)
        {
        {
          rtype = build_range_type (gfc_array_index_type,
          rtype = build_range_type (gfc_array_index_type,
                                    GFC_TYPE_ARRAY_LBOUND (type, n),
                                    GFC_TYPE_ARRAY_LBOUND (type, n),
                                    GFC_TYPE_ARRAY_UBOUND (type, n));
                                    GFC_TYPE_ARRAY_UBOUND (type, n));
          gtype = build_array_type (gtype, rtype);
          gtype = build_array_type (gtype, rtype);
        }
        }
      TYPE_NAME (type) = type_decl = build_decl (input_location,
      TYPE_NAME (type) = type_decl = build_decl (input_location,
                                                 TYPE_DECL, NULL, gtype);
                                                 TYPE_DECL, NULL, gtype);
      DECL_ORIGINAL_TYPE (type_decl) = gtype;
      DECL_ORIGINAL_TYPE (type_decl) = gtype;
    }
    }
 
 
  if (packed != PACKED_STATIC || !known_stride)
  if (packed != PACKED_STATIC || !known_stride)
    {
    {
      /* For dummy arrays and automatic (heap allocated) arrays we
      /* For dummy arrays and automatic (heap allocated) arrays we
         want a pointer to the array.  */
         want a pointer to the array.  */
      type = build_pointer_type (type);
      type = build_pointer_type (type);
      if (restricted)
      if (restricted)
        type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
        type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
      GFC_ARRAY_TYPE_P (type) = 1;
      GFC_ARRAY_TYPE_P (type) = 1;
      TYPE_LANG_SPECIFIC (type) = TYPE_LANG_SPECIFIC (TREE_TYPE (type));
      TYPE_LANG_SPECIFIC (type) = TYPE_LANG_SPECIFIC (TREE_TYPE (type));
    }
    }
  return type;
  return type;
}
}
 
 
/* Return or create the base type for an array descriptor.  */
/* Return or create the base type for an array descriptor.  */
 
 
static tree
static tree
gfc_get_array_descriptor_base (int dimen, bool restricted)
gfc_get_array_descriptor_base (int dimen, bool restricted)
{
{
  tree fat_type, fieldlist, decl, arraytype;
  tree fat_type, fieldlist, decl, arraytype;
  char name[16 + GFC_RANK_DIGITS + 1];
  char name[16 + GFC_RANK_DIGITS + 1];
  int idx = 2 * (dimen - 1) + restricted;
  int idx = 2 * (dimen - 1) + restricted;
 
 
  gcc_assert (dimen >= 1 && dimen <= GFC_MAX_DIMENSIONS);
  gcc_assert (dimen >= 1 && dimen <= GFC_MAX_DIMENSIONS);
  if (gfc_array_descriptor_base[idx])
  if (gfc_array_descriptor_base[idx])
    return gfc_array_descriptor_base[idx];
    return gfc_array_descriptor_base[idx];
 
 
  /* Build the type node.  */
  /* Build the type node.  */
  fat_type = make_node (RECORD_TYPE);
  fat_type = make_node (RECORD_TYPE);
 
 
  sprintf (name, "array_descriptor" GFC_RANK_PRINTF_FORMAT, dimen);
  sprintf (name, "array_descriptor" GFC_RANK_PRINTF_FORMAT, dimen);
  TYPE_NAME (fat_type) = get_identifier (name);
  TYPE_NAME (fat_type) = get_identifier (name);
 
 
  /* Add the data member as the first element of the descriptor.  */
  /* Add the data member as the first element of the descriptor.  */
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL, get_identifier ("data"),
                     FIELD_DECL, get_identifier ("data"),
                     restricted ? prvoid_type_node : ptr_type_node);
                     restricted ? prvoid_type_node : ptr_type_node);
 
 
  DECL_CONTEXT (decl) = fat_type;
  DECL_CONTEXT (decl) = fat_type;
  fieldlist = decl;
  fieldlist = decl;
 
 
  /* Add the base component.  */
  /* Add the base component.  */
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL, get_identifier ("offset"),
                     FIELD_DECL, get_identifier ("offset"),
                     gfc_array_index_type);
                     gfc_array_index_type);
  DECL_CONTEXT (decl) = fat_type;
  DECL_CONTEXT (decl) = fat_type;
  TREE_NO_WARNING (decl) = 1;
  TREE_NO_WARNING (decl) = 1;
  fieldlist = chainon (fieldlist, decl);
  fieldlist = chainon (fieldlist, decl);
 
 
  /* Add the dtype component.  */
  /* Add the dtype component.  */
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL, get_identifier ("dtype"),
                     FIELD_DECL, get_identifier ("dtype"),
                     gfc_array_index_type);
                     gfc_array_index_type);
  DECL_CONTEXT (decl) = fat_type;
  DECL_CONTEXT (decl) = fat_type;
  TREE_NO_WARNING (decl) = 1;
  TREE_NO_WARNING (decl) = 1;
  fieldlist = chainon (fieldlist, decl);
  fieldlist = chainon (fieldlist, decl);
 
 
  /* Build the array type for the stride and bound components.  */
  /* Build the array type for the stride and bound components.  */
  arraytype =
  arraytype =
    build_array_type (gfc_get_desc_dim_type (),
    build_array_type (gfc_get_desc_dim_type (),
                      build_range_type (gfc_array_index_type,
                      build_range_type (gfc_array_index_type,
                                        gfc_index_zero_node,
                                        gfc_index_zero_node,
                                        gfc_rank_cst[dimen - 1]));
                                        gfc_rank_cst[dimen - 1]));
 
 
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL, get_identifier ("dim"), arraytype);
                     FIELD_DECL, get_identifier ("dim"), arraytype);
  DECL_CONTEXT (decl) = fat_type;
  DECL_CONTEXT (decl) = fat_type;
  TREE_NO_WARNING (decl) = 1;
  TREE_NO_WARNING (decl) = 1;
  fieldlist = chainon (fieldlist, decl);
  fieldlist = chainon (fieldlist, decl);
 
 
  /* Finish off the type.  */
  /* Finish off the type.  */
  TYPE_FIELDS (fat_type) = fieldlist;
  TYPE_FIELDS (fat_type) = fieldlist;
 
 
  gfc_finish_type (fat_type);
  gfc_finish_type (fat_type);
  TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (fat_type)) = 1;
  TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (fat_type)) = 1;
 
 
  gfc_array_descriptor_base[idx] = fat_type;
  gfc_array_descriptor_base[idx] = fat_type;
  return fat_type;
  return fat_type;
}
}
 
 
/* Build an array (descriptor) type with given bounds.  */
/* Build an array (descriptor) type with given bounds.  */
 
 
tree
tree
gfc_get_array_type_bounds (tree etype, int dimen, tree * lbound,
gfc_get_array_type_bounds (tree etype, int dimen, tree * lbound,
                           tree * ubound, int packed,
                           tree * ubound, int packed,
                           enum gfc_array_kind akind, bool restricted)
                           enum gfc_array_kind akind, bool restricted)
{
{
  char name[8 + GFC_RANK_DIGITS + GFC_MAX_SYMBOL_LEN];
  char name[8 + GFC_RANK_DIGITS + GFC_MAX_SYMBOL_LEN];
  tree fat_type, base_type, arraytype, lower, upper, stride, tmp, rtype;
  tree fat_type, base_type, arraytype, lower, upper, stride, tmp, rtype;
  const char *type_name;
  const char *type_name;
  int n;
  int n;
 
 
  base_type = gfc_get_array_descriptor_base (dimen, restricted);
  base_type = gfc_get_array_descriptor_base (dimen, restricted);
  fat_type = build_distinct_type_copy (base_type);
  fat_type = build_distinct_type_copy (base_type);
  /* Make sure that nontarget and target array type have the same canonical
  /* Make sure that nontarget and target array type have the same canonical
     type (and same stub decl for debug info).  */
     type (and same stub decl for debug info).  */
  base_type = gfc_get_array_descriptor_base (dimen, false);
  base_type = gfc_get_array_descriptor_base (dimen, false);
  TYPE_CANONICAL (fat_type) = base_type;
  TYPE_CANONICAL (fat_type) = base_type;
  TYPE_STUB_DECL (fat_type) = TYPE_STUB_DECL (base_type);
  TYPE_STUB_DECL (fat_type) = TYPE_STUB_DECL (base_type);
 
 
  tmp = TYPE_NAME (etype);
  tmp = TYPE_NAME (etype);
  if (tmp && TREE_CODE (tmp) == TYPE_DECL)
  if (tmp && TREE_CODE (tmp) == TYPE_DECL)
    tmp = DECL_NAME (tmp);
    tmp = DECL_NAME (tmp);
  if (tmp)
  if (tmp)
    type_name = IDENTIFIER_POINTER (tmp);
    type_name = IDENTIFIER_POINTER (tmp);
  else
  else
    type_name = "unknown";
    type_name = "unknown";
  sprintf (name, "array" GFC_RANK_PRINTF_FORMAT "_%.*s", dimen,
  sprintf (name, "array" GFC_RANK_PRINTF_FORMAT "_%.*s", dimen,
           GFC_MAX_SYMBOL_LEN, type_name);
           GFC_MAX_SYMBOL_LEN, type_name);
  TYPE_NAME (fat_type) = get_identifier (name);
  TYPE_NAME (fat_type) = get_identifier (name);
 
 
  GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
  GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
  TYPE_LANG_SPECIFIC (fat_type) = (struct lang_type *)
  TYPE_LANG_SPECIFIC (fat_type) = (struct lang_type *)
    ggc_alloc_cleared (sizeof (struct lang_type));
    ggc_alloc_cleared (sizeof (struct lang_type));
 
 
  GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
  GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
  GFC_TYPE_ARRAY_DTYPE (fat_type) = NULL_TREE;
  GFC_TYPE_ARRAY_DTYPE (fat_type) = NULL_TREE;
  GFC_TYPE_ARRAY_AKIND (fat_type) = akind;
  GFC_TYPE_ARRAY_AKIND (fat_type) = akind;
 
 
  /* Build an array descriptor record type.  */
  /* Build an array descriptor record type.  */
  if (packed != 0)
  if (packed != 0)
    stride = gfc_index_one_node;
    stride = gfc_index_one_node;
  else
  else
    stride = NULL_TREE;
    stride = NULL_TREE;
  for (n = 0; n < dimen; n++)
  for (n = 0; n < dimen; n++)
    {
    {
      GFC_TYPE_ARRAY_STRIDE (fat_type, n) = stride;
      GFC_TYPE_ARRAY_STRIDE (fat_type, n) = stride;
 
 
      if (lbound)
      if (lbound)
        lower = lbound[n];
        lower = lbound[n];
      else
      else
        lower = NULL_TREE;
        lower = NULL_TREE;
 
 
      if (lower != NULL_TREE)
      if (lower != NULL_TREE)
        {
        {
          if (INTEGER_CST_P (lower))
          if (INTEGER_CST_P (lower))
            GFC_TYPE_ARRAY_LBOUND (fat_type, n) = lower;
            GFC_TYPE_ARRAY_LBOUND (fat_type, n) = lower;
          else
          else
            lower = NULL_TREE;
            lower = NULL_TREE;
        }
        }
 
 
      upper = ubound[n];
      upper = ubound[n];
      if (upper != NULL_TREE)
      if (upper != NULL_TREE)
        {
        {
          if (INTEGER_CST_P (upper))
          if (INTEGER_CST_P (upper))
            GFC_TYPE_ARRAY_UBOUND (fat_type, n) = upper;
            GFC_TYPE_ARRAY_UBOUND (fat_type, n) = upper;
          else
          else
            upper = NULL_TREE;
            upper = NULL_TREE;
        }
        }
 
 
      if (upper != NULL_TREE && lower != NULL_TREE && stride != NULL_TREE)
      if (upper != NULL_TREE && lower != NULL_TREE && stride != NULL_TREE)
        {
        {
          tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
          tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp,
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp,
                             gfc_index_one_node);
                             gfc_index_one_node);
          stride =
          stride =
            fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, stride);
            fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, stride);
          /* Check the folding worked.  */
          /* Check the folding worked.  */
          gcc_assert (INTEGER_CST_P (stride));
          gcc_assert (INTEGER_CST_P (stride));
        }
        }
      else
      else
        stride = NULL_TREE;
        stride = NULL_TREE;
    }
    }
  GFC_TYPE_ARRAY_SIZE (fat_type) = stride;
  GFC_TYPE_ARRAY_SIZE (fat_type) = stride;
 
 
  /* TODO: known offsets for descriptors.  */
  /* TODO: known offsets for descriptors.  */
  GFC_TYPE_ARRAY_OFFSET (fat_type) = NULL_TREE;
  GFC_TYPE_ARRAY_OFFSET (fat_type) = NULL_TREE;
 
 
  /* We define data as an array with the correct size if possible.
  /* We define data as an array with the correct size if possible.
     Much better than doing pointer arithmetic.  */
     Much better than doing pointer arithmetic.  */
  if (stride)
  if (stride)
    rtype = build_range_type (gfc_array_index_type, gfc_index_zero_node,
    rtype = build_range_type (gfc_array_index_type, gfc_index_zero_node,
                              int_const_binop (MINUS_EXPR, stride,
                              int_const_binop (MINUS_EXPR, stride,
                                               integer_one_node, 0));
                                               integer_one_node, 0));
  else
  else
    rtype = gfc_array_range_type;
    rtype = gfc_array_range_type;
  arraytype = build_array_type (etype, rtype);
  arraytype = build_array_type (etype, rtype);
  arraytype = build_pointer_type (arraytype);
  arraytype = build_pointer_type (arraytype);
  if (restricted)
  if (restricted)
    arraytype = build_qualified_type (arraytype, TYPE_QUAL_RESTRICT);
    arraytype = build_qualified_type (arraytype, TYPE_QUAL_RESTRICT);
  GFC_TYPE_ARRAY_DATAPTR_TYPE (fat_type) = arraytype;
  GFC_TYPE_ARRAY_DATAPTR_TYPE (fat_type) = arraytype;
 
 
  /* This will generate the base declarations we need to emit debug
  /* This will generate the base declarations we need to emit debug
     information for this type.  FIXME: there must be a better way to
     information for this type.  FIXME: there must be a better way to
     avoid divergence between compilations with and without debug
     avoid divergence between compilations with and without debug
     information.  */
     information.  */
  {
  {
    struct array_descr_info info;
    struct array_descr_info info;
    gfc_get_array_descr_info (fat_type, &info);
    gfc_get_array_descr_info (fat_type, &info);
    gfc_get_array_descr_info (build_pointer_type (fat_type), &info);
    gfc_get_array_descr_info (build_pointer_type (fat_type), &info);
  }
  }
 
 
  return fat_type;
  return fat_type;
}
}


/* Build a pointer type. This function is called from gfc_sym_type().  */
/* Build a pointer type. This function is called from gfc_sym_type().  */
 
 
static tree
static tree
gfc_build_pointer_type (gfc_symbol * sym, tree type)
gfc_build_pointer_type (gfc_symbol * sym, tree type)
{
{
  /* Array pointer types aren't actually pointers.  */
  /* Array pointer types aren't actually pointers.  */
  if (sym->attr.dimension)
  if (sym->attr.dimension)
    return type;
    return type;
  else
  else
    return build_pointer_type (type);
    return build_pointer_type (type);
}
}


/* Return the type for a symbol.  Special handling is required for character
/* Return the type for a symbol.  Special handling is required for character
   types to get the correct level of indirection.
   types to get the correct level of indirection.
   For functions return the return type.
   For functions return the return type.
   For subroutines return void_type_node.
   For subroutines return void_type_node.
   Calling this multiple times for the same symbol should be avoided,
   Calling this multiple times for the same symbol should be avoided,
   especially for character and array types.  */
   especially for character and array types.  */
 
 
tree
tree
gfc_sym_type (gfc_symbol * sym)
gfc_sym_type (gfc_symbol * sym)
{
{
  tree type;
  tree type;
  int byref;
  int byref;
  bool restricted;
  bool restricted;
 
 
  /* Procedure Pointers inside COMMON blocks.  */
  /* Procedure Pointers inside COMMON blocks.  */
  if (sym->attr.proc_pointer && sym->attr.in_common)
  if (sym->attr.proc_pointer && sym->attr.in_common)
    {
    {
      /* Unset proc_pointer as gfc_get_function_type calls gfc_sym_type.  */
      /* Unset proc_pointer as gfc_get_function_type calls gfc_sym_type.  */
      sym->attr.proc_pointer = 0;
      sym->attr.proc_pointer = 0;
      type = build_pointer_type (gfc_get_function_type (sym));
      type = build_pointer_type (gfc_get_function_type (sym));
      sym->attr.proc_pointer = 1;
      sym->attr.proc_pointer = 1;
      return type;
      return type;
    }
    }
 
 
  if (sym->attr.flavor == FL_PROCEDURE && !sym->attr.function)
  if (sym->attr.flavor == FL_PROCEDURE && !sym->attr.function)
    return void_type_node;
    return void_type_node;
 
 
  /* In the case of a function the fake result variable may have a
  /* In the case of a function the fake result variable may have a
     type different from the function type, so don't return early in
     type different from the function type, so don't return early in
     that case.  */
     that case.  */
  if (sym->backend_decl && !sym->attr.function)
  if (sym->backend_decl && !sym->attr.function)
    return TREE_TYPE (sym->backend_decl);
    return TREE_TYPE (sym->backend_decl);
 
 
  if (sym->ts.type == BT_CHARACTER
  if (sym->ts.type == BT_CHARACTER
      && ((sym->attr.function && sym->attr.is_bind_c)
      && ((sym->attr.function && sym->attr.is_bind_c)
          || (sym->attr.result
          || (sym->attr.result
              && sym->ns->proc_name
              && sym->ns->proc_name
              && sym->ns->proc_name->attr.is_bind_c)))
              && sym->ns->proc_name->attr.is_bind_c)))
    type = gfc_character1_type_node;
    type = gfc_character1_type_node;
  else
  else
    type = gfc_typenode_for_spec (&sym->ts);
    type = gfc_typenode_for_spec (&sym->ts);
 
 
  if (sym->attr.dummy && !sym->attr.function && !sym->attr.value)
  if (sym->attr.dummy && !sym->attr.function && !sym->attr.value)
    byref = 1;
    byref = 1;
  else
  else
    byref = 0;
    byref = 0;
 
 
  restricted = !sym->attr.target && !sym->attr.pointer
  restricted = !sym->attr.target && !sym->attr.pointer
               && !sym->attr.proc_pointer && !sym->attr.cray_pointee;
               && !sym->attr.proc_pointer && !sym->attr.cray_pointee;
  if (sym->attr.dimension)
  if (sym->attr.dimension)
    {
    {
      if (gfc_is_nodesc_array (sym))
      if (gfc_is_nodesc_array (sym))
        {
        {
          /* If this is a character argument of unknown length, just use the
          /* If this is a character argument of unknown length, just use the
             base type.  */
             base type.  */
          if (sym->ts.type != BT_CHARACTER
          if (sym->ts.type != BT_CHARACTER
              || !(sym->attr.dummy || sym->attr.function)
              || !(sym->attr.dummy || sym->attr.function)
              || sym->ts.u.cl->backend_decl)
              || sym->ts.u.cl->backend_decl)
            {
            {
              type = gfc_get_nodesc_array_type (type, sym->as,
              type = gfc_get_nodesc_array_type (type, sym->as,
                                                byref ? PACKED_FULL
                                                byref ? PACKED_FULL
                                                      : PACKED_STATIC,
                                                      : PACKED_STATIC,
                                                restricted);
                                                restricted);
              byref = 0;
              byref = 0;
            }
            }
 
 
          if (sym->attr.cray_pointee)
          if (sym->attr.cray_pointee)
            GFC_POINTER_TYPE_P (type) = 1;
            GFC_POINTER_TYPE_P (type) = 1;
        }
        }
      else
      else
        {
        {
          enum gfc_array_kind akind = GFC_ARRAY_UNKNOWN;
          enum gfc_array_kind akind = GFC_ARRAY_UNKNOWN;
          if (sym->attr.pointer)
          if (sym->attr.pointer)
            akind = GFC_ARRAY_POINTER;
            akind = GFC_ARRAY_POINTER;
          else if (sym->attr.allocatable)
          else if (sym->attr.allocatable)
            akind = GFC_ARRAY_ALLOCATABLE;
            akind = GFC_ARRAY_ALLOCATABLE;
          type = gfc_build_array_type (type, sym->as, akind, restricted);
          type = gfc_build_array_type (type, sym->as, akind, restricted);
        }
        }
    }
    }
  else
  else
    {
    {
      if (sym->attr.allocatable || sym->attr.pointer)
      if (sym->attr.allocatable || sym->attr.pointer)
        type = gfc_build_pointer_type (sym, type);
        type = gfc_build_pointer_type (sym, type);
      if (sym->attr.pointer || sym->attr.cray_pointee)
      if (sym->attr.pointer || sym->attr.cray_pointee)
        GFC_POINTER_TYPE_P (type) = 1;
        GFC_POINTER_TYPE_P (type) = 1;
    }
    }
 
 
  /* We currently pass all parameters by reference.
  /* We currently pass all parameters by reference.
     See f95_get_function_decl.  For dummy function parameters return the
     See f95_get_function_decl.  For dummy function parameters return the
     function type.  */
     function type.  */
  if (byref)
  if (byref)
    {
    {
      /* We must use pointer types for potentially absent variables.  The
      /* We must use pointer types for potentially absent variables.  The
         optimizers assume a reference type argument is never NULL.  */
         optimizers assume a reference type argument is never NULL.  */
      if (sym->attr.optional || sym->ns->proc_name->attr.entry_master)
      if (sym->attr.optional || sym->ns->proc_name->attr.entry_master)
        type = build_pointer_type (type);
        type = build_pointer_type (type);
      else
      else
        {
        {
          type = build_reference_type (type);
          type = build_reference_type (type);
          if (restricted)
          if (restricted)
            type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
            type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
        }
        }
    }
    }
 
 
  return (type);
  return (type);
}
}


/* Layout and output debug info for a record type.  */
/* Layout and output debug info for a record type.  */
 
 
void
void
gfc_finish_type (tree type)
gfc_finish_type (tree type)
{
{
  tree decl;
  tree decl;
 
 
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     TYPE_DECL, NULL_TREE, type);
                     TYPE_DECL, NULL_TREE, type);
  TYPE_STUB_DECL (type) = decl;
  TYPE_STUB_DECL (type) = decl;
  layout_type (type);
  layout_type (type);
  rest_of_type_compilation (type, 1);
  rest_of_type_compilation (type, 1);
  rest_of_decl_compilation (decl, 1, 0);
  rest_of_decl_compilation (decl, 1, 0);
}
}


/* Add a field of given NAME and TYPE to the context of a UNION_TYPE
/* Add a field of given NAME and TYPE to the context of a UNION_TYPE
   or RECORD_TYPE pointed to by STYPE.  The new field is chained
   or RECORD_TYPE pointed to by STYPE.  The new field is chained
   to the fieldlist pointed to by FIELDLIST.
   to the fieldlist pointed to by FIELDLIST.
 
 
   Returns a pointer to the new field.  */
   Returns a pointer to the new field.  */
 
 
tree
tree
gfc_add_field_to_struct (tree *fieldlist, tree context,
gfc_add_field_to_struct (tree *fieldlist, tree context,
                         tree name, tree type)
                         tree name, tree type)
{
{
  tree decl;
  tree decl;
 
 
  decl = build_decl (input_location,
  decl = build_decl (input_location,
                     FIELD_DECL, name, type);
                     FIELD_DECL, name, type);
 
 
  DECL_CONTEXT (decl) = context;
  DECL_CONTEXT (decl) = context;
  DECL_INITIAL (decl) = 0;
  DECL_INITIAL (decl) = 0;
  DECL_ALIGN (decl) = 0;
  DECL_ALIGN (decl) = 0;
  DECL_USER_ALIGN (decl) = 0;
  DECL_USER_ALIGN (decl) = 0;
  TREE_CHAIN (decl) = NULL_TREE;
  TREE_CHAIN (decl) = NULL_TREE;
  *fieldlist = chainon (*fieldlist, decl);
  *fieldlist = chainon (*fieldlist, decl);
 
 
  return decl;
  return decl;
}
}
 
 
 
 
/* Copy the backend_decl and component backend_decls if
/* Copy the backend_decl and component backend_decls if
   the two derived type symbols are "equal", as described
   the two derived type symbols are "equal", as described
   in 4.4.2 and resolved by gfc_compare_derived_types.  */
   in 4.4.2 and resolved by gfc_compare_derived_types.  */
 
 
static int
static int
copy_dt_decls_ifequal (gfc_symbol *from, gfc_symbol *to,
copy_dt_decls_ifequal (gfc_symbol *from, gfc_symbol *to,
                       bool from_gsym)
                       bool from_gsym)
{
{
  gfc_component *to_cm;
  gfc_component *to_cm;
  gfc_component *from_cm;
  gfc_component *from_cm;
 
 
  if (from->backend_decl == NULL
  if (from->backend_decl == NULL
        || !gfc_compare_derived_types (from, to))
        || !gfc_compare_derived_types (from, to))
    return 0;
    return 0;
 
 
  to->backend_decl = from->backend_decl;
  to->backend_decl = from->backend_decl;
 
 
  to_cm = to->components;
  to_cm = to->components;
  from_cm = from->components;
  from_cm = from->components;
 
 
  /* Copy the component declarations.  If a component is itself
  /* Copy the component declarations.  If a component is itself
     a derived type, we need a copy of its component declarations.
     a derived type, we need a copy of its component declarations.
     This is done by recursing into gfc_get_derived_type and
     This is done by recursing into gfc_get_derived_type and
     ensures that the component's component declarations have
     ensures that the component's component declarations have
     been built.  If it is a character, we need the character
     been built.  If it is a character, we need the character
     length, as well.  */
     length, as well.  */
  for (; to_cm; to_cm = to_cm->next, from_cm = from_cm->next)
  for (; to_cm; to_cm = to_cm->next, from_cm = from_cm->next)
    {
    {
      to_cm->backend_decl = from_cm->backend_decl;
      to_cm->backend_decl = from_cm->backend_decl;
      if ((!from_cm->attr.pointer || from_gsym)
      if ((!from_cm->attr.pointer || from_gsym)
              && from_cm->ts.type == BT_DERIVED)
              && from_cm->ts.type == BT_DERIVED)
        gfc_get_derived_type (to_cm->ts.u.derived);
        gfc_get_derived_type (to_cm->ts.u.derived);
 
 
      else if (from_cm->ts.type == BT_CHARACTER)
      else if (from_cm->ts.type == BT_CHARACTER)
        to_cm->ts.u.cl->backend_decl = from_cm->ts.u.cl->backend_decl;
        to_cm->ts.u.cl->backend_decl = from_cm->ts.u.cl->backend_decl;
    }
    }
 
 
  return 1;
  return 1;
}
}
 
 
 
 
/* Build a tree node for a procedure pointer component.  */
/* Build a tree node for a procedure pointer component.  */
 
 
tree
tree
gfc_get_ppc_type (gfc_component* c)
gfc_get_ppc_type (gfc_component* c)
{
{
  tree t;
  tree t;
 
 
  /* Explicit interface.  */
  /* Explicit interface.  */
  if (c->attr.if_source != IFSRC_UNKNOWN && c->ts.interface)
  if (c->attr.if_source != IFSRC_UNKNOWN && c->ts.interface)
    return build_pointer_type (gfc_get_function_type (c->ts.interface));
    return build_pointer_type (gfc_get_function_type (c->ts.interface));
 
 
  /* Implicit interface (only return value may be known).  */
  /* Implicit interface (only return value may be known).  */
  if (c->attr.function && !c->attr.dimension && c->ts.type != BT_CHARACTER)
  if (c->attr.function && !c->attr.dimension && c->ts.type != BT_CHARACTER)
    t = gfc_typenode_for_spec (&c->ts);
    t = gfc_typenode_for_spec (&c->ts);
  else
  else
    t = void_type_node;
    t = void_type_node;
 
 
  return build_pointer_type (build_function_type (t, NULL_TREE));
  return build_pointer_type (build_function_type (t, NULL_TREE));
}
}
 
 
 
 
/* Build a tree node for a derived type.  If there are equal
/* Build a tree node for a derived type.  If there are equal
   derived types, with different local names, these are built
   derived types, with different local names, these are built
   at the same time.  If an equal derived type has been built
   at the same time.  If an equal derived type has been built
   in a parent namespace, this is used.  */
   in a parent namespace, this is used.  */
 
 
tree
tree
gfc_get_derived_type (gfc_symbol * derived)
gfc_get_derived_type (gfc_symbol * derived)
{
{
  tree typenode = NULL, field = NULL, field_type = NULL, fieldlist = NULL;
  tree typenode = NULL, field = NULL, field_type = NULL, fieldlist = NULL;
  tree canonical = NULL_TREE;
  tree canonical = NULL_TREE;
  bool got_canonical = false;
  bool got_canonical = false;
  gfc_component *c;
  gfc_component *c;
  gfc_dt_list *dt;
  gfc_dt_list *dt;
  gfc_namespace *ns;
  gfc_namespace *ns;
  gfc_gsymbol *gsym;
  gfc_gsymbol *gsym;
 
 
  gcc_assert (derived && derived->attr.flavor == FL_DERIVED);
  gcc_assert (derived && derived->attr.flavor == FL_DERIVED);
 
 
  /* See if it's one of the iso_c_binding derived types.  */
  /* See if it's one of the iso_c_binding derived types.  */
  if (derived->attr.is_iso_c == 1)
  if (derived->attr.is_iso_c == 1)
    {
    {
      if (derived->backend_decl)
      if (derived->backend_decl)
        return derived->backend_decl;
        return derived->backend_decl;
 
 
      if (derived->intmod_sym_id == ISOCBINDING_PTR)
      if (derived->intmod_sym_id == ISOCBINDING_PTR)
        derived->backend_decl = ptr_type_node;
        derived->backend_decl = ptr_type_node;
      else
      else
        derived->backend_decl = pfunc_type_node;
        derived->backend_decl = pfunc_type_node;
 
 
      /* Create a backend_decl for the __c_ptr_c_address field.  */
      /* Create a backend_decl for the __c_ptr_c_address field.  */
      derived->components->backend_decl =
      derived->components->backend_decl =
        gfc_add_field_to_struct (&(derived->backend_decl->type.values),
        gfc_add_field_to_struct (&(derived->backend_decl->type.values),
                                 derived->backend_decl,
                                 derived->backend_decl,
                                 get_identifier (derived->components->name),
                                 get_identifier (derived->components->name),
                                 gfc_typenode_for_spec (
                                 gfc_typenode_for_spec (
                                   &(derived->components->ts)));
                                   &(derived->components->ts)));
 
 
      derived->ts.kind = gfc_index_integer_kind;
      derived->ts.kind = gfc_index_integer_kind;
      derived->ts.type = BT_INTEGER;
      derived->ts.type = BT_INTEGER;
      /* Set the f90_type to BT_VOID as a way to recognize something of type
      /* Set the f90_type to BT_VOID as a way to recognize something of type
         BT_INTEGER that needs to fit a void * for the purpose of the
         BT_INTEGER that needs to fit a void * for the purpose of the
         iso_c_binding derived types.  */
         iso_c_binding derived types.  */
      derived->ts.f90_type = BT_VOID;
      derived->ts.f90_type = BT_VOID;
 
 
      return derived->backend_decl;
      return derived->backend_decl;
    }
    }
 
 
/* If use associated, use the module type for this one.  */
/* If use associated, use the module type for this one.  */
  if (gfc_option.flag_whole_file
  if (gfc_option.flag_whole_file
        && derived->backend_decl == NULL
        && derived->backend_decl == NULL
        && derived->attr.use_assoc
        && derived->attr.use_assoc
        && derived->module)
        && derived->module)
    {
    {
      gsym =  gfc_find_gsymbol (gfc_gsym_root, derived->module);
      gsym =  gfc_find_gsymbol (gfc_gsym_root, derived->module);
      if (gsym && gsym->ns && gsym->type == GSYM_MODULE)
      if (gsym && gsym->ns && gsym->type == GSYM_MODULE)
        {
        {
          gfc_symbol *s;
          gfc_symbol *s;
          s = NULL;
          s = NULL;
          gfc_find_symbol (derived->name, gsym->ns, 0, &s);
          gfc_find_symbol (derived->name, gsym->ns, 0, &s);
          if (s && s->backend_decl)
          if (s && s->backend_decl)
            {
            {
              copy_dt_decls_ifequal (s, derived, true);
              copy_dt_decls_ifequal (s, derived, true);
              goto copy_derived_types;
              goto copy_derived_types;
            }
            }
        }
        }
    }
    }
 
 
  /* If a whole file compilation, the derived types from an earlier
  /* If a whole file compilation, the derived types from an earlier
     namespace can be used as the the canonical type.  */
     namespace can be used as the the canonical type.  */
  if (gfc_option.flag_whole_file
  if (gfc_option.flag_whole_file
        && derived->backend_decl == NULL
        && derived->backend_decl == NULL
        && !derived->attr.use_assoc
        && !derived->attr.use_assoc
        && gfc_global_ns_list)
        && gfc_global_ns_list)
    {
    {
      for (ns = gfc_global_ns_list;
      for (ns = gfc_global_ns_list;
           ns->translated && !got_canonical;
           ns->translated && !got_canonical;
           ns = ns->sibling)
           ns = ns->sibling)
        {
        {
          dt = ns->derived_types;
          dt = ns->derived_types;
          for (; dt && !canonical; dt = dt->next)
          for (; dt && !canonical; dt = dt->next)
            {
            {
              copy_dt_decls_ifequal (dt->derived, derived, true);
              copy_dt_decls_ifequal (dt->derived, derived, true);
              if (derived->backend_decl)
              if (derived->backend_decl)
                got_canonical = true;
                got_canonical = true;
            }
            }
        }
        }
    }
    }
 
 
  /* Store up the canonical type to be added to this one.  */
  /* Store up the canonical type to be added to this one.  */
  if (got_canonical)
  if (got_canonical)
    {
    {
      if (TYPE_CANONICAL (derived->backend_decl))
      if (TYPE_CANONICAL (derived->backend_decl))
        canonical = TYPE_CANONICAL (derived->backend_decl);
        canonical = TYPE_CANONICAL (derived->backend_decl);
      else
      else
        canonical = derived->backend_decl;
        canonical = derived->backend_decl;
 
 
      derived->backend_decl = NULL_TREE;
      derived->backend_decl = NULL_TREE;
    }
    }
 
 
  /* derived->backend_decl != 0 means we saw it before, but its
  /* derived->backend_decl != 0 means we saw it before, but its
     components' backend_decl may have not been built.  */
     components' backend_decl may have not been built.  */
  if (derived->backend_decl)
  if (derived->backend_decl)
    {
    {
      /* Its components' backend_decl have been built or we are
      /* Its components' backend_decl have been built or we are
         seeing recursion through the formal arglist of a procedure
         seeing recursion through the formal arglist of a procedure
         pointer component.  */
         pointer component.  */
      if (TYPE_FIELDS (derived->backend_decl)
      if (TYPE_FIELDS (derived->backend_decl)
            || derived->attr.proc_pointer_comp)
            || derived->attr.proc_pointer_comp)
        return derived->backend_decl;
        return derived->backend_decl;
      else
      else
        typenode = derived->backend_decl;
        typenode = derived->backend_decl;
    }
    }
  else
  else
    {
    {
      /* We see this derived type first time, so build the type node.  */
      /* We see this derived type first time, so build the type node.  */
      typenode = make_node (RECORD_TYPE);
      typenode = make_node (RECORD_TYPE);
      TYPE_NAME (typenode) = get_identifier (derived->name);
      TYPE_NAME (typenode) = get_identifier (derived->name);
      TYPE_PACKED (typenode) = gfc_option.flag_pack_derived;
      TYPE_PACKED (typenode) = gfc_option.flag_pack_derived;
      derived->backend_decl = typenode;
      derived->backend_decl = typenode;
    }
    }
 
 
  /* Go through the derived type components, building them as
  /* Go through the derived type components, building them as
     necessary. The reason for doing this now is that it is
     necessary. The reason for doing this now is that it is
     possible to recurse back to this derived type through a
     possible to recurse back to this derived type through a
     pointer component (PR24092). If this happens, the fields
     pointer component (PR24092). If this happens, the fields
     will be built and so we can return the type.  */
     will be built and so we can return the type.  */
  for (c = derived->components; c; c = c->next)
  for (c = derived->components; c; c = c->next)
    {
    {
      if (c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS)
      if (c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS)
        continue;
        continue;
 
 
      if ((!c->attr.pointer && !c->attr.proc_pointer)
      if ((!c->attr.pointer && !c->attr.proc_pointer)
          || c->ts.u.derived->backend_decl == NULL)
          || c->ts.u.derived->backend_decl == NULL)
        c->ts.u.derived->backend_decl = gfc_get_derived_type (c->ts.u.derived);
        c->ts.u.derived->backend_decl = gfc_get_derived_type (c->ts.u.derived);
 
 
      if (c->ts.u.derived && c->ts.u.derived->attr.is_iso_c)
      if (c->ts.u.derived && c->ts.u.derived->attr.is_iso_c)
        {
        {
          /* Need to copy the modified ts from the derived type.  The
          /* Need to copy the modified ts from the derived type.  The
             typespec was modified because C_PTR/C_FUNPTR are translated
             typespec was modified because C_PTR/C_FUNPTR are translated
             into (void *) from derived types.  */
             into (void *) from derived types.  */
          c->ts.type = c->ts.u.derived->ts.type;
          c->ts.type = c->ts.u.derived->ts.type;
          c->ts.kind = c->ts.u.derived->ts.kind;
          c->ts.kind = c->ts.u.derived->ts.kind;
          c->ts.f90_type = c->ts.u.derived->ts.f90_type;
          c->ts.f90_type = c->ts.u.derived->ts.f90_type;
          if (c->initializer)
          if (c->initializer)
            {
            {
              c->initializer->ts.type = c->ts.type;
              c->initializer->ts.type = c->ts.type;
              c->initializer->ts.kind = c->ts.kind;
              c->initializer->ts.kind = c->ts.kind;
              c->initializer->ts.f90_type = c->ts.f90_type;
              c->initializer->ts.f90_type = c->ts.f90_type;
              c->initializer->expr_type = EXPR_NULL;
              c->initializer->expr_type = EXPR_NULL;
            }
            }
        }
        }
    }
    }
 
 
  if (TYPE_FIELDS (derived->backend_decl))
  if (TYPE_FIELDS (derived->backend_decl))
    return derived->backend_decl;
    return derived->backend_decl;
 
 
  /* Build the type member list. Install the newly created RECORD_TYPE
  /* Build the type member list. Install the newly created RECORD_TYPE
     node as DECL_CONTEXT of each FIELD_DECL.  */
     node as DECL_CONTEXT of each FIELD_DECL.  */
  fieldlist = NULL_TREE;
  fieldlist = NULL_TREE;
  for (c = derived->components; c; c = c->next)
  for (c = derived->components; c; c = c->next)
    {
    {
      if (c->attr.proc_pointer)
      if (c->attr.proc_pointer)
        field_type = gfc_get_ppc_type (c);
        field_type = gfc_get_ppc_type (c);
      else if (c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
      else if (c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
        field_type = c->ts.u.derived->backend_decl;
        field_type = c->ts.u.derived->backend_decl;
      else
      else
        {
        {
          if (c->ts.type == BT_CHARACTER)
          if (c->ts.type == BT_CHARACTER)
            {
            {
              /* Evaluate the string length.  */
              /* Evaluate the string length.  */
              gfc_conv_const_charlen (c->ts.u.cl);
              gfc_conv_const_charlen (c->ts.u.cl);
              gcc_assert (c->ts.u.cl->backend_decl);
              gcc_assert (c->ts.u.cl->backend_decl);
            }
            }
 
 
          field_type = gfc_typenode_for_spec (&c->ts);
          field_type = gfc_typenode_for_spec (&c->ts);
        }
        }
 
 
      /* This returns an array descriptor type.  Initialization may be
      /* This returns an array descriptor type.  Initialization may be
         required.  */
         required.  */
      if (c->attr.dimension && !c->attr.proc_pointer)
      if (c->attr.dimension && !c->attr.proc_pointer)
        {
        {
          if (c->attr.pointer || c->attr.allocatable)
          if (c->attr.pointer || c->attr.allocatable)
            {
            {
              enum gfc_array_kind akind;
              enum gfc_array_kind akind;
              if (c->attr.pointer)
              if (c->attr.pointer)
                akind = GFC_ARRAY_POINTER;
                akind = GFC_ARRAY_POINTER;
              else
              else
                akind = GFC_ARRAY_ALLOCATABLE;
                akind = GFC_ARRAY_ALLOCATABLE;
              /* Pointers to arrays aren't actually pointer types.  The
              /* Pointers to arrays aren't actually pointer types.  The
                 descriptors are separate, but the data is common.  */
                 descriptors are separate, but the data is common.  */
              field_type = gfc_build_array_type (field_type, c->as, akind,
              field_type = gfc_build_array_type (field_type, c->as, akind,
                                                 !c->attr.target
                                                 !c->attr.target
                                                 && !c->attr.pointer);
                                                 && !c->attr.pointer);
            }
            }
          else
          else
            field_type = gfc_get_nodesc_array_type (field_type, c->as,
            field_type = gfc_get_nodesc_array_type (field_type, c->as,
                                                    PACKED_STATIC,
                                                    PACKED_STATIC,
                                                    !c->attr.target);
                                                    !c->attr.target);
        }
        }
      else if ((c->attr.pointer || c->attr.allocatable)
      else if ((c->attr.pointer || c->attr.allocatable)
               && !c->attr.proc_pointer)
               && !c->attr.proc_pointer)
        field_type = build_pointer_type (field_type);
        field_type = build_pointer_type (field_type);
 
 
      field = gfc_add_field_to_struct (&fieldlist, typenode,
      field = gfc_add_field_to_struct (&fieldlist, typenode,
                                       get_identifier (c->name), field_type);
                                       get_identifier (c->name), field_type);
      if (c->loc.lb)
      if (c->loc.lb)
        gfc_set_decl_location (field, &c->loc);
        gfc_set_decl_location (field, &c->loc);
      else if (derived->declared_at.lb)
      else if (derived->declared_at.lb)
        gfc_set_decl_location (field, &derived->declared_at);
        gfc_set_decl_location (field, &derived->declared_at);
 
 
      DECL_PACKED (field) |= TYPE_PACKED (typenode);
      DECL_PACKED (field) |= TYPE_PACKED (typenode);
 
 
      gcc_assert (field);
      gcc_assert (field);
      if (!c->backend_decl)
      if (!c->backend_decl)
        c->backend_decl = field;
        c->backend_decl = field;
    }
    }
 
 
  /* Now we have the final fieldlist.  Record it, then lay out the
  /* Now we have the final fieldlist.  Record it, then lay out the
     derived type, including the fields.  */
     derived type, including the fields.  */
  TYPE_FIELDS (typenode) = fieldlist;
  TYPE_FIELDS (typenode) = fieldlist;
  if (canonical)
  if (canonical)
    TYPE_CANONICAL (typenode) = canonical;
    TYPE_CANONICAL (typenode) = canonical;
 
 
  gfc_finish_type (typenode);
  gfc_finish_type (typenode);
  gfc_set_decl_location (TYPE_STUB_DECL (typenode), &derived->declared_at);
  gfc_set_decl_location (TYPE_STUB_DECL (typenode), &derived->declared_at);
  if (derived->module && derived->ns->proc_name
  if (derived->module && derived->ns->proc_name
      && derived->ns->proc_name->attr.flavor == FL_MODULE)
      && derived->ns->proc_name->attr.flavor == FL_MODULE)
    {
    {
      if (derived->ns->proc_name->backend_decl
      if (derived->ns->proc_name->backend_decl
          && TREE_CODE (derived->ns->proc_name->backend_decl)
          && TREE_CODE (derived->ns->proc_name->backend_decl)
             == NAMESPACE_DECL)
             == NAMESPACE_DECL)
        {
        {
          TYPE_CONTEXT (typenode) = derived->ns->proc_name->backend_decl;
          TYPE_CONTEXT (typenode) = derived->ns->proc_name->backend_decl;
          DECL_CONTEXT (TYPE_STUB_DECL (typenode))
          DECL_CONTEXT (TYPE_STUB_DECL (typenode))
            = derived->ns->proc_name->backend_decl;
            = derived->ns->proc_name->backend_decl;
        }
        }
    }
    }
 
 
  derived->backend_decl = typenode;
  derived->backend_decl = typenode;
 
 
copy_derived_types:
copy_derived_types:
 
 
  for (dt = gfc_derived_types; dt; dt = dt->next)
  for (dt = gfc_derived_types; dt; dt = dt->next)
    copy_dt_decls_ifequal (derived, dt->derived, false);
    copy_dt_decls_ifequal (derived, dt->derived, false);
 
 
  return derived->backend_decl;
  return derived->backend_decl;
}
}
 
 
 
 
int
int
gfc_return_by_reference (gfc_symbol * sym)
gfc_return_by_reference (gfc_symbol * sym)
{
{
  if (!sym->attr.function)
  if (!sym->attr.function)
    return 0;
    return 0;
 
 
  if (sym->attr.dimension)
  if (sym->attr.dimension)
    return 1;
    return 1;
 
 
  if (sym->ts.type == BT_CHARACTER
  if (sym->ts.type == BT_CHARACTER
      && !sym->attr.is_bind_c
      && !sym->attr.is_bind_c
      && (!sym->attr.result
      && (!sym->attr.result
          || !sym->ns->proc_name
          || !sym->ns->proc_name
          || !sym->ns->proc_name->attr.is_bind_c))
          || !sym->ns->proc_name->attr.is_bind_c))
    return 1;
    return 1;
 
 
  /* Possibly return complex numbers by reference for g77 compatibility.
  /* Possibly return complex numbers by reference for g77 compatibility.
     We don't do this for calls to intrinsics (as the library uses the
     We don't do this for calls to intrinsics (as the library uses the
     -fno-f2c calling convention), nor for calls to functions which always
     -fno-f2c calling convention), nor for calls to functions which always
     require an explicit interface, as no compatibility problems can
     require an explicit interface, as no compatibility problems can
     arise there.  */
     arise there.  */
  if (gfc_option.flag_f2c
  if (gfc_option.flag_f2c
      && sym->ts.type == BT_COMPLEX
      && sym->ts.type == BT_COMPLEX
      && !sym->attr.intrinsic && !sym->attr.always_explicit)
      && !sym->attr.intrinsic && !sym->attr.always_explicit)
    return 1;
    return 1;
 
 
  return 0;
  return 0;
}
}


static tree
static tree
gfc_get_mixed_entry_union (gfc_namespace *ns)
gfc_get_mixed_entry_union (gfc_namespace *ns)
{
{
  tree type;
  tree type;
  tree decl;
  tree decl;
  tree fieldlist;
  tree fieldlist;
  char name[GFC_MAX_SYMBOL_LEN + 1];
  char name[GFC_MAX_SYMBOL_LEN + 1];
  gfc_entry_list *el, *el2;
  gfc_entry_list *el, *el2;
 
 
  gcc_assert (ns->proc_name->attr.mixed_entry_master);
  gcc_assert (ns->proc_name->attr.mixed_entry_master);
  gcc_assert (memcmp (ns->proc_name->name, "master.", 7) == 0);
  gcc_assert (memcmp (ns->proc_name->name, "master.", 7) == 0);
 
 
  snprintf (name, GFC_MAX_SYMBOL_LEN, "munion.%s", ns->proc_name->name + 7);
  snprintf (name, GFC_MAX_SYMBOL_LEN, "munion.%s", ns->proc_name->name + 7);
 
 
  /* Build the type node.  */
  /* Build the type node.  */
  type = make_node (UNION_TYPE);
  type = make_node (UNION_TYPE);
 
 
  TYPE_NAME (type) = get_identifier (name);
  TYPE_NAME (type) = get_identifier (name);
  fieldlist = NULL;
  fieldlist = NULL;
 
 
  for (el = ns->entries; el; el = el->next)
  for (el = ns->entries; el; el = el->next)
    {
    {
      /* Search for duplicates.  */
      /* Search for duplicates.  */
      for (el2 = ns->entries; el2 != el; el2 = el2->next)
      for (el2 = ns->entries; el2 != el; el2 = el2->next)
        if (el2->sym->result == el->sym->result)
        if (el2->sym->result == el->sym->result)
          break;
          break;
 
 
      if (el == el2)
      if (el == el2)
        {
        {
          decl = build_decl (input_location,
          decl = build_decl (input_location,
                             FIELD_DECL,
                             FIELD_DECL,
                             get_identifier (el->sym->result->name),
                             get_identifier (el->sym->result->name),
                             gfc_sym_type (el->sym->result));
                             gfc_sym_type (el->sym->result));
          DECL_CONTEXT (decl) = type;
          DECL_CONTEXT (decl) = type;
          fieldlist = chainon (fieldlist, decl);
          fieldlist = chainon (fieldlist, decl);
        }
        }
    }
    }
 
 
  /* Finish off the type.  */
  /* Finish off the type.  */
  TYPE_FIELDS (type) = fieldlist;
  TYPE_FIELDS (type) = fieldlist;
 
 
  gfc_finish_type (type);
  gfc_finish_type (type);
  TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
  TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
  return type;
  return type;
}
}


tree
tree
gfc_get_function_type (gfc_symbol * sym)
gfc_get_function_type (gfc_symbol * sym)
{
{
  tree type;
  tree type;
  tree typelist;
  tree typelist;
  gfc_formal_arglist *f;
  gfc_formal_arglist *f;
  gfc_symbol *arg;
  gfc_symbol *arg;
  int nstr;
  int nstr;
  int alternate_return;
  int alternate_return;
 
 
  /* Make sure this symbol is a function, a subroutine or the main
  /* Make sure this symbol is a function, a subroutine or the main
     program.  */
     program.  */
  gcc_assert (sym->attr.flavor == FL_PROCEDURE
  gcc_assert (sym->attr.flavor == FL_PROCEDURE
              || sym->attr.flavor == FL_PROGRAM);
              || sym->attr.flavor == FL_PROGRAM);
 
 
  if (sym->backend_decl)
  if (sym->backend_decl)
    return TREE_TYPE (sym->backend_decl);
    return TREE_TYPE (sym->backend_decl);
 
 
  nstr = 0;
  nstr = 0;
  alternate_return = 0;
  alternate_return = 0;
  typelist = NULL_TREE;
  typelist = NULL_TREE;
 
 
  if (sym->attr.entry_master)
  if (sym->attr.entry_master)
    {
    {
      /* Additional parameter for selecting an entry point.  */
      /* Additional parameter for selecting an entry point.  */
      typelist = gfc_chainon_list (typelist, gfc_array_index_type);
      typelist = gfc_chainon_list (typelist, gfc_array_index_type);
    }
    }
 
 
  if (sym->result)
  if (sym->result)
    arg = sym->result;
    arg = sym->result;
  else
  else
    arg = sym;
    arg = sym;
 
 
  if (arg->ts.type == BT_CHARACTER)
  if (arg->ts.type == BT_CHARACTER)
    gfc_conv_const_charlen (arg->ts.u.cl);
    gfc_conv_const_charlen (arg->ts.u.cl);
 
 
  /* Some functions we use an extra parameter for the return value.  */
  /* Some functions we use an extra parameter for the return value.  */
  if (gfc_return_by_reference (sym))
  if (gfc_return_by_reference (sym))
    {
    {
      type = gfc_sym_type (arg);
      type = gfc_sym_type (arg);
      if (arg->ts.type == BT_COMPLEX
      if (arg->ts.type == BT_COMPLEX
          || arg->attr.dimension
          || arg->attr.dimension
          || arg->ts.type == BT_CHARACTER)
          || arg->ts.type == BT_CHARACTER)
        type = build_reference_type (type);
        type = build_reference_type (type);
 
 
      typelist = gfc_chainon_list (typelist, type);
      typelist = gfc_chainon_list (typelist, type);
      if (arg->ts.type == BT_CHARACTER)
      if (arg->ts.type == BT_CHARACTER)
        typelist = gfc_chainon_list (typelist, gfc_charlen_type_node);
        typelist = gfc_chainon_list (typelist, gfc_charlen_type_node);
    }
    }
 
 
  /* Build the argument types for the function.  */
  /* Build the argument types for the function.  */
  for (f = sym->formal; f; f = f->next)
  for (f = sym->formal; f; f = f->next)
    {
    {
      arg = f->sym;
      arg = f->sym;
      if (arg)
      if (arg)
        {
        {
          /* Evaluate constant character lengths here so that they can be
          /* Evaluate constant character lengths here so that they can be
             included in the type.  */
             included in the type.  */
          if (arg->ts.type == BT_CHARACTER)
          if (arg->ts.type == BT_CHARACTER)
            gfc_conv_const_charlen (arg->ts.u.cl);
            gfc_conv_const_charlen (arg->ts.u.cl);
 
 
          if (arg->attr.flavor == FL_PROCEDURE)
          if (arg->attr.flavor == FL_PROCEDURE)
            {
            {
              type = gfc_get_function_type (arg);
              type = gfc_get_function_type (arg);
              type = build_pointer_type (type);
              type = build_pointer_type (type);
            }
            }
          else
          else
            type = gfc_sym_type (arg);
            type = gfc_sym_type (arg);
 
 
          /* Parameter Passing Convention
          /* Parameter Passing Convention
 
 
             We currently pass all parameters by reference.
             We currently pass all parameters by reference.
             Parameters with INTENT(IN) could be passed by value.
             Parameters with INTENT(IN) could be passed by value.
             The problem arises if a function is called via an implicit
             The problem arises if a function is called via an implicit
             prototype. In this situation the INTENT is not known.
             prototype. In this situation the INTENT is not known.
             For this reason all parameters to global functions must be
             For this reason all parameters to global functions must be
             passed by reference.  Passing by value would potentially
             passed by reference.  Passing by value would potentially
             generate bad code.  Worse there would be no way of telling that
             generate bad code.  Worse there would be no way of telling that
             this code was bad, except that it would give incorrect results.
             this code was bad, except that it would give incorrect results.
 
 
             Contained procedures could pass by value as these are never
             Contained procedures could pass by value as these are never
             used without an explicit interface, and cannot be passed as
             used without an explicit interface, and cannot be passed as
             actual parameters for a dummy procedure.  */
             actual parameters for a dummy procedure.  */
          if (arg->ts.type == BT_CHARACTER && !sym->attr.is_bind_c)
          if (arg->ts.type == BT_CHARACTER && !sym->attr.is_bind_c)
            nstr++;
            nstr++;
          typelist = gfc_chainon_list (typelist, type);
          typelist = gfc_chainon_list (typelist, type);
        }
        }
      else
      else
        {
        {
          if (sym->attr.subroutine)
          if (sym->attr.subroutine)
            alternate_return = 1;
            alternate_return = 1;
        }
        }
    }
    }
 
 
  /* Add hidden string length parameters.  */
  /* Add hidden string length parameters.  */
  while (nstr--)
  while (nstr--)
    typelist = gfc_chainon_list (typelist, gfc_charlen_type_node);
    typelist = gfc_chainon_list (typelist, gfc_charlen_type_node);
 
 
  if (typelist)
  if (typelist)
    typelist = gfc_chainon_list (typelist, void_type_node);
    typelist = gfc_chainon_list (typelist, void_type_node);
 
 
  if (alternate_return)
  if (alternate_return)
    type = integer_type_node;
    type = integer_type_node;
  else if (!sym->attr.function || gfc_return_by_reference (sym))
  else if (!sym->attr.function || gfc_return_by_reference (sym))
    type = void_type_node;
    type = void_type_node;
  else if (sym->attr.mixed_entry_master)
  else if (sym->attr.mixed_entry_master)
    type = gfc_get_mixed_entry_union (sym->ns);
    type = gfc_get_mixed_entry_union (sym->ns);
  else if (gfc_option.flag_f2c
  else if (gfc_option.flag_f2c
           && sym->ts.type == BT_REAL
           && sym->ts.type == BT_REAL
           && sym->ts.kind == gfc_default_real_kind
           && sym->ts.kind == gfc_default_real_kind
           && !sym->attr.always_explicit)
           && !sym->attr.always_explicit)
    {
    {
      /* Special case: f2c calling conventions require that (scalar)
      /* Special case: f2c calling conventions require that (scalar)
         default REAL functions return the C type double instead.  f2c
         default REAL functions return the C type double instead.  f2c
         compatibility is only an issue with functions that don't
         compatibility is only an issue with functions that don't
         require an explicit interface, as only these could be
         require an explicit interface, as only these could be
         implemented in Fortran 77.  */
         implemented in Fortran 77.  */
      sym->ts.kind = gfc_default_double_kind;
      sym->ts.kind = gfc_default_double_kind;
      type = gfc_typenode_for_spec (&sym->ts);
      type = gfc_typenode_for_spec (&sym->ts);
      sym->ts.kind = gfc_default_real_kind;
      sym->ts.kind = gfc_default_real_kind;
    }
    }
  else if (sym->result && sym->result->attr.proc_pointer)
  else if (sym->result && sym->result->attr.proc_pointer)
    /* Procedure pointer return values.  */
    /* Procedure pointer return values.  */
    {
    {
      if (sym->result->attr.result && strcmp (sym->name,"ppr@") != 0)
      if (sym->result->attr.result && strcmp (sym->name,"ppr@") != 0)
        {
        {
          /* Unset proc_pointer as gfc_get_function_type
          /* Unset proc_pointer as gfc_get_function_type
             is called recursively.  */
             is called recursively.  */
          sym->result->attr.proc_pointer = 0;
          sym->result->attr.proc_pointer = 0;
          type = build_pointer_type (gfc_get_function_type (sym->result));
          type = build_pointer_type (gfc_get_function_type (sym->result));
          sym->result->attr.proc_pointer = 1;
          sym->result->attr.proc_pointer = 1;
        }
        }
      else
      else
       type = gfc_sym_type (sym->result);
       type = gfc_sym_type (sym->result);
    }
    }
  else
  else
    type = gfc_sym_type (sym);
    type = gfc_sym_type (sym);
 
 
  type = build_function_type (type, typelist);
  type = build_function_type (type, typelist);
 
 
  return type;
  return type;
}
}


/* Language hooks for middle-end access to type nodes.  */
/* Language hooks for middle-end access to type nodes.  */
 
 
/* Return an integer type with BITS bits of precision,
/* Return an integer type with BITS bits of precision,
   that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */
   that is unsigned if UNSIGNEDP is nonzero, otherwise signed.  */
 
 
tree
tree
gfc_type_for_size (unsigned bits, int unsignedp)
gfc_type_for_size (unsigned bits, int unsignedp)
{
{
  if (!unsignedp)
  if (!unsignedp)
    {
    {
      int i;
      int i;
      for (i = 0; i <= MAX_INT_KINDS; ++i)
      for (i = 0; i <= MAX_INT_KINDS; ++i)
        {
        {
          tree type = gfc_integer_types[i];
          tree type = gfc_integer_types[i];
          if (type && bits == TYPE_PRECISION (type))
          if (type && bits == TYPE_PRECISION (type))
            return type;
            return type;
        }
        }
 
 
      /* Handle TImode as a special case because it is used by some backends
      /* Handle TImode as a special case because it is used by some backends
         (e.g. ARM) even though it is not available for normal use.  */
         (e.g. ARM) even though it is not available for normal use.  */
#if HOST_BITS_PER_WIDE_INT >= 64
#if HOST_BITS_PER_WIDE_INT >= 64
      if (bits == TYPE_PRECISION (intTI_type_node))
      if (bits == TYPE_PRECISION (intTI_type_node))
        return intTI_type_node;
        return intTI_type_node;
#endif
#endif
    }
    }
  else
  else
    {
    {
      if (bits == TYPE_PRECISION (unsigned_intQI_type_node))
      if (bits == TYPE_PRECISION (unsigned_intQI_type_node))
        return unsigned_intQI_type_node;
        return unsigned_intQI_type_node;
      if (bits == TYPE_PRECISION (unsigned_intHI_type_node))
      if (bits == TYPE_PRECISION (unsigned_intHI_type_node))
        return unsigned_intHI_type_node;
        return unsigned_intHI_type_node;
      if (bits == TYPE_PRECISION (unsigned_intSI_type_node))
      if (bits == TYPE_PRECISION (unsigned_intSI_type_node))
        return unsigned_intSI_type_node;
        return unsigned_intSI_type_node;
      if (bits == TYPE_PRECISION (unsigned_intDI_type_node))
      if (bits == TYPE_PRECISION (unsigned_intDI_type_node))
        return unsigned_intDI_type_node;
        return unsigned_intDI_type_node;
      if (bits == TYPE_PRECISION (unsigned_intTI_type_node))
      if (bits == TYPE_PRECISION (unsigned_intTI_type_node))
        return unsigned_intTI_type_node;
        return unsigned_intTI_type_node;
    }
    }
 
 
  return NULL_TREE;
  return NULL_TREE;
}
}
 
 
/* Return a data type that has machine mode MODE.  If the mode is an
/* Return a data type that has machine mode MODE.  If the mode is an
   integer, then UNSIGNEDP selects between signed and unsigned types.  */
   integer, then UNSIGNEDP selects between signed and unsigned types.  */
 
 
tree
tree
gfc_type_for_mode (enum machine_mode mode, int unsignedp)
gfc_type_for_mode (enum machine_mode mode, int unsignedp)
{
{
  int i;
  int i;
  tree *base;
  tree *base;
 
 
  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
    base = gfc_real_types;
    base = gfc_real_types;
  else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
  else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
    base = gfc_complex_types;
    base = gfc_complex_types;
  else if (SCALAR_INT_MODE_P (mode))
  else if (SCALAR_INT_MODE_P (mode))
    return gfc_type_for_size (GET_MODE_PRECISION (mode), unsignedp);
    return gfc_type_for_size (GET_MODE_PRECISION (mode), unsignedp);
  else if (VECTOR_MODE_P (mode))
  else if (VECTOR_MODE_P (mode))
    {
    {
      enum machine_mode inner_mode = GET_MODE_INNER (mode);
      enum machine_mode inner_mode = GET_MODE_INNER (mode);
      tree inner_type = gfc_type_for_mode (inner_mode, unsignedp);
      tree inner_type = gfc_type_for_mode (inner_mode, unsignedp);
      if (inner_type != NULL_TREE)
      if (inner_type != NULL_TREE)
        return build_vector_type_for_mode (inner_type, mode);
        return build_vector_type_for_mode (inner_type, mode);
      return NULL_TREE;
      return NULL_TREE;
    }
    }
  else
  else
    return NULL_TREE;
    return NULL_TREE;
 
 
  for (i = 0; i <= MAX_REAL_KINDS; ++i)
  for (i = 0; i <= MAX_REAL_KINDS; ++i)
    {
    {
      tree type = base[i];
      tree type = base[i];
      if (type && mode == TYPE_MODE (type))
      if (type && mode == TYPE_MODE (type))
        return type;
        return type;
    }
    }
 
 
  return NULL_TREE;
  return NULL_TREE;
}
}
 
 
/* Return TRUE if TYPE is a type with a hidden descriptor, fill in INFO
/* Return TRUE if TYPE is a type with a hidden descriptor, fill in INFO
   in that case.  */
   in that case.  */
 
 
bool
bool
gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
{
{
  int rank, dim;
  int rank, dim;
  bool indirect = false;
  bool indirect = false;
  tree etype, ptype, field, t, base_decl;
  tree etype, ptype, field, t, base_decl;
  tree data_off, dim_off, dim_size, elem_size;
  tree data_off, dim_off, dim_size, elem_size;
  tree lower_suboff, upper_suboff, stride_suboff;
  tree lower_suboff, upper_suboff, stride_suboff;
 
 
  if (! GFC_DESCRIPTOR_TYPE_P (type))
  if (! GFC_DESCRIPTOR_TYPE_P (type))
    {
    {
      if (! POINTER_TYPE_P (type))
      if (! POINTER_TYPE_P (type))
        return false;
        return false;
      type = TREE_TYPE (type);
      type = TREE_TYPE (type);
      if (! GFC_DESCRIPTOR_TYPE_P (type))
      if (! GFC_DESCRIPTOR_TYPE_P (type))
        return false;
        return false;
      indirect = true;
      indirect = true;
    }
    }
 
 
  rank = GFC_TYPE_ARRAY_RANK (type);
  rank = GFC_TYPE_ARRAY_RANK (type);
  if (rank >= (int) (sizeof (info->dimen) / sizeof (info->dimen[0])))
  if (rank >= (int) (sizeof (info->dimen) / sizeof (info->dimen[0])))
    return false;
    return false;
 
 
  etype = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
  etype = GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
  gcc_assert (POINTER_TYPE_P (etype));
  gcc_assert (POINTER_TYPE_P (etype));
  etype = TREE_TYPE (etype);
  etype = TREE_TYPE (etype);
  gcc_assert (TREE_CODE (etype) == ARRAY_TYPE);
  gcc_assert (TREE_CODE (etype) == ARRAY_TYPE);
  etype = TREE_TYPE (etype);
  etype = TREE_TYPE (etype);
  /* Can't handle variable sized elements yet.  */
  /* Can't handle variable sized elements yet.  */
  if (int_size_in_bytes (etype) <= 0)
  if (int_size_in_bytes (etype) <= 0)
    return false;
    return false;
  /* Nor non-constant lower bounds in assumed shape arrays.  */
  /* Nor non-constant lower bounds in assumed shape arrays.  */
  if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE)
  if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE)
    {
    {
      for (dim = 0; dim < rank; dim++)
      for (dim = 0; dim < rank; dim++)
        if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE
        if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE
            || TREE_CODE (GFC_TYPE_ARRAY_LBOUND (type, dim)) != INTEGER_CST)
            || TREE_CODE (GFC_TYPE_ARRAY_LBOUND (type, dim)) != INTEGER_CST)
          return false;
          return false;
    }
    }
 
 
  memset (info, '\0', sizeof (*info));
  memset (info, '\0', sizeof (*info));
  info->ndimensions = rank;
  info->ndimensions = rank;
  info->element_type = etype;
  info->element_type = etype;
  ptype = build_pointer_type (gfc_array_index_type);
  ptype = build_pointer_type (gfc_array_index_type);
  base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
  base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
  if (!base_decl)
  if (!base_decl)
    {
    {
      base_decl = build_decl (input_location, VAR_DECL, NULL_TREE,
      base_decl = build_decl (input_location, VAR_DECL, NULL_TREE,
                              indirect ? build_pointer_type (ptype) : ptype);
                              indirect ? build_pointer_type (ptype) : ptype);
      GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
      GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
    }
    }
  info->base_decl = base_decl;
  info->base_decl = base_decl;
  if (indirect)
  if (indirect)
    base_decl = build1 (INDIRECT_REF, ptype, base_decl);
    base_decl = build1 (INDIRECT_REF, ptype, base_decl);
 
 
  if (GFC_TYPE_ARRAY_SPAN (type))
  if (GFC_TYPE_ARRAY_SPAN (type))
    elem_size = GFC_TYPE_ARRAY_SPAN (type);
    elem_size = GFC_TYPE_ARRAY_SPAN (type);
  else
  else
    elem_size = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (etype));
    elem_size = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (etype));
  field = TYPE_FIELDS (TYPE_MAIN_VARIANT (type));
  field = TYPE_FIELDS (TYPE_MAIN_VARIANT (type));
  data_off = byte_position (field);
  data_off = byte_position (field);
  field = TREE_CHAIN (field);
  field = TREE_CHAIN (field);
  field = TREE_CHAIN (field);
  field = TREE_CHAIN (field);
  field = TREE_CHAIN (field);
  field = TREE_CHAIN (field);
  dim_off = byte_position (field);
  dim_off = byte_position (field);
  dim_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (field)));
  dim_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (field)));
  field = TYPE_FIELDS (TREE_TYPE (TREE_TYPE (field)));
  field = TYPE_FIELDS (TREE_TYPE (TREE_TYPE (field)));
  stride_suboff = byte_position (field);
  stride_suboff = byte_position (field);
  field = TREE_CHAIN (field);
  field = TREE_CHAIN (field);
  lower_suboff = byte_position (field);
  lower_suboff = byte_position (field);
  field = TREE_CHAIN (field);
  field = TREE_CHAIN (field);
  upper_suboff = byte_position (field);
  upper_suboff = byte_position (field);
 
 
  t = base_decl;
  t = base_decl;
  if (!integer_zerop (data_off))
  if (!integer_zerop (data_off))
    t = build2 (POINTER_PLUS_EXPR, ptype, t, data_off);
    t = build2 (POINTER_PLUS_EXPR, ptype, t, data_off);
  t = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), t);
  t = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), t);
  info->data_location = build1 (INDIRECT_REF, ptr_type_node, t);
  info->data_location = build1 (INDIRECT_REF, ptr_type_node, t);
  if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
  if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
    info->allocated = build2 (NE_EXPR, boolean_type_node,
    info->allocated = build2 (NE_EXPR, boolean_type_node,
                              info->data_location, null_pointer_node);
                              info->data_location, null_pointer_node);
  else if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER)
  else if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER)
    info->associated = build2 (NE_EXPR, boolean_type_node,
    info->associated = build2 (NE_EXPR, boolean_type_node,
                               info->data_location, null_pointer_node);
                               info->data_location, null_pointer_node);
 
 
  for (dim = 0; dim < rank; dim++)
  for (dim = 0; dim < rank; dim++)
    {
    {
      t = build2 (POINTER_PLUS_EXPR, ptype, base_decl,
      t = build2 (POINTER_PLUS_EXPR, ptype, base_decl,
                  size_binop (PLUS_EXPR, dim_off, lower_suboff));
                  size_binop (PLUS_EXPR, dim_off, lower_suboff));
      t = build1 (INDIRECT_REF, gfc_array_index_type, t);
      t = build1 (INDIRECT_REF, gfc_array_index_type, t);
      info->dimen[dim].lower_bound = t;
      info->dimen[dim].lower_bound = t;
      t = build2 (POINTER_PLUS_EXPR, ptype, base_decl,
      t = build2 (POINTER_PLUS_EXPR, ptype, base_decl,
                  size_binop (PLUS_EXPR, dim_off, upper_suboff));
                  size_binop (PLUS_EXPR, dim_off, upper_suboff));
      t = build1 (INDIRECT_REF, gfc_array_index_type, t);
      t = build1 (INDIRECT_REF, gfc_array_index_type, t);
      info->dimen[dim].upper_bound = t;
      info->dimen[dim].upper_bound = t;
      if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE)
      if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE)
        {
        {
          /* Assumed shape arrays have known lower bounds.  */
          /* Assumed shape arrays have known lower bounds.  */
          info->dimen[dim].upper_bound
          info->dimen[dim].upper_bound
            = build2 (MINUS_EXPR, gfc_array_index_type,
            = build2 (MINUS_EXPR, gfc_array_index_type,
                      info->dimen[dim].upper_bound,
                      info->dimen[dim].upper_bound,
                      info->dimen[dim].lower_bound);
                      info->dimen[dim].lower_bound);
          info->dimen[dim].lower_bound
          info->dimen[dim].lower_bound
            = fold_convert (gfc_array_index_type,
            = fold_convert (gfc_array_index_type,
                            GFC_TYPE_ARRAY_LBOUND (type, dim));
                            GFC_TYPE_ARRAY_LBOUND (type, dim));
          info->dimen[dim].upper_bound
          info->dimen[dim].upper_bound
            = build2 (PLUS_EXPR, gfc_array_index_type,
            = build2 (PLUS_EXPR, gfc_array_index_type,
                      info->dimen[dim].lower_bound,
                      info->dimen[dim].lower_bound,
                      info->dimen[dim].upper_bound);
                      info->dimen[dim].upper_bound);
        }
        }
      t = build2 (POINTER_PLUS_EXPR, ptype, base_decl,
      t = build2 (POINTER_PLUS_EXPR, ptype, base_decl,
                  size_binop (PLUS_EXPR, dim_off, stride_suboff));
                  size_binop (PLUS_EXPR, dim_off, stride_suboff));
      t = build1 (INDIRECT_REF, gfc_array_index_type, t);
      t = build1 (INDIRECT_REF, gfc_array_index_type, t);
      t = build2 (MULT_EXPR, gfc_array_index_type, t, elem_size);
      t = build2 (MULT_EXPR, gfc_array_index_type, t, elem_size);
      info->dimen[dim].stride = t;
      info->dimen[dim].stride = t;
      dim_off = size_binop (PLUS_EXPR, dim_off, dim_size);
      dim_off = size_binop (PLUS_EXPR, dim_off, dim_size);
    }
    }
 
 
  return true;
  return true;
}
}
 
 
#include "gt-fortran-trans-types.h"
#include "gt-fortran-trans-types.h"
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.