示例#1
0
void
gfc_assign_data_value (gfc_expr * lvalue, gfc_expr * rvalue, mpz_t index)
{
    gfc_ref *ref;
    gfc_expr *init;
    gfc_expr *expr;
    gfc_constructor *con;
    gfc_constructor *last_con;
    gfc_symbol *symbol;
    gfc_typespec *last_ts;
    mpz_t offset;

    symbol = lvalue->symtree->n.sym;
    init = symbol->value;
    last_ts = &symbol->ts;
    last_con = NULL;
    mpz_init_set_si (offset, 0);

    /* Find/create the parent expressions for subobject references.  */
    for (ref = lvalue->ref; ref; ref = ref->next)
    {
        /* Break out of the loop if we find a substring.  */
        if (ref->type == REF_SUBSTRING)
        {
            /* A substring should always be the last subobject reference.  */
            gcc_assert (ref->next == NULL);
            break;
        }

        /* Use the existing initializer expression if it exists.  Otherwise
           create a new one.  */
        if (init == NULL)
            expr = gfc_get_expr ();
        else
            expr = init;

        /* Find or create this element.  */
        switch (ref->type)
        {
        case REF_ARRAY:
            if (init == NULL)
            {
                /* The element typespec will be the same as the array
                typespec.  */
                expr->ts = *last_ts;
                /* Setup the expression to hold the constructor.  */
                expr->expr_type = EXPR_ARRAY;
                expr->rank = ref->u.ar.as->rank;
            }
            else
                gcc_assert (expr->expr_type == EXPR_ARRAY);

            if (ref->u.ar.type == AR_ELEMENT)
                get_array_index (&ref->u.ar, &offset);
            else
                mpz_set (offset, index);

            /* Find the same element in the existing constructor.  */
            con = expr->value.constructor;
            con = find_con_by_offset (offset, con);

            if (con == NULL)
            {
                /* Create a new constructor.  */
                con = gfc_get_constructor ();
                mpz_set (con->n.offset, offset);
                gfc_insert_constructor (expr, con);
            }
            break;

        case REF_COMPONENT:
            if (init == NULL)
            {
                /* Setup the expression to hold the constructor.  */
                expr->expr_type = EXPR_STRUCTURE;
                expr->ts.type = BT_DERIVED;
                expr->ts.derived = ref->u.c.sym;
            }
            else
                gcc_assert (expr->expr_type == EXPR_STRUCTURE);
            last_ts = &ref->u.c.component->ts;

            /* Find the same element in the existing constructor.  */
            con = expr->value.constructor;
            con = find_con_by_component (ref->u.c.component, con);

            if (con == NULL)
            {
                /* Create a new constructor.  */
                con = gfc_get_constructor ();
                con->n.component = ref->u.c.component;
                con->next = expr->value.constructor;
                expr->value.constructor = con;
            }
            break;

        default:
            gcc_unreachable ();
        }

        if (init == NULL)
        {
            /* Point the container at the new expression.  */
            if (last_con == NULL)
                symbol->value = expr;
            else
                last_con->expr = expr;
        }
        init = con->expr;
        last_con = con;
    }

    if (ref || last_ts->type == BT_CHARACTER)
        expr = create_character_intializer (init, last_ts, ref, rvalue);
    else
    {
        /* Overwriting an existing initializer is non-standard but usually only
        provokes a warning from other compilers.  */
        if (init != NULL)
        {
            /* Order in which the expressions arrive here depends on whether they
               are from data statements or F95 style declarations. Therefore,
               check which is the most recent.  */
#ifdef USE_MAPPED_LOCATION
            expr = (LOCATION_LINE (init->where.lb->location)
                    > LOCATION_LINE (rvalue->where.lb->location))
                   ? init : rvalue;
#else
            expr = (init->where.lb->linenum > rvalue->where.lb->linenum) ?
                   init : rvalue;
#endif
            gfc_notify_std (GFC_STD_GNU, "Extension: re-initialization "
                            "of '%s' at %L",  symbol->name, &expr->where);
        }

        expr = gfc_copy_expr (rvalue);
        if (!gfc_compare_types (&lvalue->ts, &expr->ts))
            gfc_convert_type (expr, &lvalue->ts, 0);
    }

    if (last_con == NULL)
        symbol->value = expr;
    else
        last_con->expr = expr;
}
示例#2
0
void
gfc_assign_data_value_range (gfc_expr * lvalue, gfc_expr * rvalue,
                             mpz_t index, mpz_t repeat)
{
    gfc_ref *ref;
    gfc_expr *init, *expr;
    gfc_constructor *con, *last_con;
    gfc_symbol *symbol;
    gfc_typespec *last_ts;
    mpz_t offset;

    symbol = lvalue->symtree->n.sym;
    init = symbol->value;
    last_ts = &symbol->ts;
    last_con = NULL;
    mpz_init_set_si (offset, 0);

    /* Find/create the parent expressions for subobject references.  */
    for (ref = lvalue->ref; ref; ref = ref->next)
    {
        /* Use the existing initializer expression if it exists.
        Otherwise create a new one.  */
        if (init == NULL)
            expr = gfc_get_expr ();
        else
            expr = init;

        /* Find or create this element.  */
        switch (ref->type)
        {
        case REF_ARRAY:
            if (init == NULL)
            {
                /* The element typespec will be the same as the array
                typespec.  */
                expr->ts = *last_ts;
                /* Setup the expression to hold the constructor.  */
                expr->expr_type = EXPR_ARRAY;
                expr->rank = ref->u.ar.as->rank;
            }
            else
                gcc_assert (expr->expr_type == EXPR_ARRAY);

            if (ref->u.ar.type == AR_ELEMENT)
            {
                get_array_index (&ref->u.ar, &offset);

                /* This had better not be the bottom of the reference.
                We can still get to a full array via a component.  */
                gcc_assert (ref->next != NULL);
            }
            else
            {
                mpz_set (offset, index);

                /* We're at a full array or an array section.  This means
                that we've better have found a full array, and that we're
                 at the bottom of the reference.  */
                gcc_assert (ref->u.ar.type == AR_FULL);
                gcc_assert (ref->next == NULL);
            }

            /* Find the same element in the existing constructor.  */
            con = expr->value.constructor;
            con = find_con_by_offset (offset, con);

            /* Create a new constructor.  */
            if (con == NULL)
            {
                con = gfc_get_constructor ();
                mpz_set (con->n.offset, offset);
                if (ref->next == NULL)
                    mpz_set (con->repeat, repeat);
                gfc_insert_constructor (expr, con);
            }
            else
                gcc_assert (ref->next != NULL);
            break;

        case REF_COMPONENT:
            if (init == NULL)
            {
                /* Setup the expression to hold the constructor.  */
                expr->expr_type = EXPR_STRUCTURE;
                expr->ts.type = BT_DERIVED;
                expr->ts.derived = ref->u.c.sym;
            }
            else
                gcc_assert (expr->expr_type == EXPR_STRUCTURE);
            last_ts = &ref->u.c.component->ts;

            /* Find the same element in the existing constructor.  */
            con = expr->value.constructor;
            con = find_con_by_component (ref->u.c.component, con);

            if (con == NULL)
            {
                /* Create a new constructor.  */
                con = gfc_get_constructor ();
                con->n.component = ref->u.c.component;
                con->next = expr->value.constructor;
                expr->value.constructor = con;
            }

            /* Since we're only intending to initialize arrays here,
               there better be an inner reference.  */
            gcc_assert (ref->next != NULL);
            break;

        case REF_SUBSTRING:
        default:
            gcc_unreachable ();
        }

        if (init == NULL)
        {
            /* Point the container at the new expression.  */
            if (last_con == NULL)
                symbol->value = expr;
            else
                last_con->expr = expr;
        }
        init = con->expr;
        last_con = con;
    }

    if (last_ts->type == BT_CHARACTER)
        expr = create_character_intializer (init, last_ts, NULL, rvalue);
    else
    {
        /* We should never be overwriting an existing initializer.  */
        gcc_assert (!init);

        expr = gfc_copy_expr (rvalue);
        if (!gfc_compare_types (&lvalue->ts, &expr->ts))
            gfc_convert_type (expr, &lvalue->ts, 0);
    }

    if (last_con == NULL)
        symbol->value = expr;
    else
        last_con->expr = expr;
}
示例#3
0
gfc_try
gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index)
{
  gfc_ref *ref;
  gfc_expr *init;
  gfc_expr *expr;
  gfc_constructor *con;
  gfc_constructor *last_con;
  gfc_constructor *pred;
  gfc_symbol *symbol;
  gfc_typespec *last_ts;
  mpz_t offset;
  splay_tree spt;
  splay_tree_node sptn;

  symbol = lvalue->symtree->n.sym;
  init = symbol->value;
  last_ts = &symbol->ts;
  last_con = NULL;
  mpz_init_set_si (offset, 0);

  /* Find/create the parent expressions for subobject references.  */
  for (ref = lvalue->ref; ref; ref = ref->next)
    {
      /* Break out of the loop if we find a substring.  */
      if (ref->type == REF_SUBSTRING)
	{
	  /* A substring should always be the last subobject reference.  */
	  gcc_assert (ref->next == NULL);
	  break;
	}

      /* Use the existing initializer expression if it exists.  Otherwise
	 create a new one.  */
      if (init == NULL)
	expr = gfc_get_expr ();
      else
	expr = init;

      /* Find or create this element.  */
      switch (ref->type)
	{
	case REF_ARRAY:
	  if (init && expr->expr_type != EXPR_ARRAY)
	    {
	      gfc_error ("'%s' at %L already is initialized at %L",
			 lvalue->symtree->n.sym->name, &lvalue->where,
			 &init->where);
	      return FAILURE;
	    }

	  if (init == NULL)
	    {
	      /* The element typespec will be the same as the array
		 typespec.  */
	      expr->ts = *last_ts;
	      /* Setup the expression to hold the constructor.  */
	      expr->expr_type = EXPR_ARRAY;
	      expr->rank = ref->u.ar.as->rank;
	    }

	  if (ref->u.ar.type == AR_ELEMENT)
	    get_array_index (&ref->u.ar, &offset);
	  else
	    mpz_set (offset, index);

	  /* Check the bounds.  */
	  if (mpz_cmp_si (offset, 0) < 0)
	    {
	      gfc_error ("Data element below array lower bound at %L",
			 &lvalue->where);
	      return FAILURE;
	    }
	  else
	    {
	      mpz_t size;
	      if (spec_size (ref->u.ar.as, &size) == SUCCESS)
		{
		  if (mpz_cmp (offset, size) >= 0)
		  {
		    mpz_clear (size);
		    gfc_error ("Data element above array upper bound at %L",
			       &lvalue->where);
		    return FAILURE;
		  }
		  mpz_clear (size);
		}
	    }

	  /* Splay tree containing offset and gfc_constructor.  */
	  spt = expr->con_by_offset;

	  if (spt == NULL)
	    {
	       spt = splay_tree_new (splay_tree_compare_ints, NULL, NULL);
	       expr->con_by_offset = spt; 
	       con = NULL;
	    }
	 else
	  con = find_con_by_offset (spt, offset);

	  if (con == NULL)
	    {
	      splay_tree_key j;

	      /* Create a new constructor.  */
	      con = gfc_get_constructor ();
	      mpz_set (con->n.offset, offset);
	      j = (splay_tree_key) mpz_get_si (offset);
	      sptn = splay_tree_insert (spt, j, (splay_tree_value) con);
	      /* Fix up the linked list.  */
	      sptn = splay_tree_predecessor (spt, j);
	      if (sptn == NULL)
		{  /* Insert at the head.  */
		   con->next = expr->value.constructor;
		   expr->value.constructor = con;
		}
	      else
		{  /* Insert in the chain.  */
		   pred = (gfc_constructor*) sptn->value;
		   con->next = pred->next;
		   pred->next = con;
		}
	    }
	  break;

	case REF_COMPONENT:
	  if (init == NULL)
	    {
	      /* Setup the expression to hold the constructor.  */
	      expr->expr_type = EXPR_STRUCTURE;
	      expr->ts.type = BT_DERIVED;
	      expr->ts.derived = ref->u.c.sym;
	    }
	  else
	    gcc_assert (expr->expr_type == EXPR_STRUCTURE);
	  last_ts = &ref->u.c.component->ts;

	  /* Find the same element in the existing constructor.  */
	  con = expr->value.constructor;
	  con = find_con_by_component (ref->u.c.component, con);

	  if (con == NULL)
	    {
	      /* Create a new constructor.  */
	      con = gfc_get_constructor ();
	      con->n.component = ref->u.c.component;
	      con->next = expr->value.constructor;
	      expr->value.constructor = con;
	    }
	  break;

	default:
	  gcc_unreachable ();
	}

      if (init == NULL)
	{
	  /* Point the container at the new expression.  */
	  if (last_con == NULL)
	    symbol->value = expr;
	  else
	    last_con->expr = expr;
	}
      init = con->expr;
      last_con = con;
    }

  if (ref || last_ts->type == BT_CHARACTER)
    expr = create_character_intializer (init, last_ts, ref, rvalue);
  else
    {
      /* Overwriting an existing initializer is non-standard but usually only
	 provokes a warning from other compilers.  */
      if (init != NULL)
	{
	  /* Order in which the expressions arrive here depends on whether
	     they are from data statements or F95 style declarations.
	     Therefore, check which is the most recent.  */
	  expr = (LOCATION_LINE (init->where.lb->location)
		  > LOCATION_LINE (rvalue->where.lb->location))
	       ? init : rvalue;
	  gfc_notify_std (GFC_STD_GNU, "Extension: re-initialization "
			  "of '%s' at %L", symbol->name, &expr->where);
	}

      expr = gfc_copy_expr (rvalue);
      if (!gfc_compare_types (&lvalue->ts, &expr->ts))
	gfc_convert_type (expr, &lvalue->ts, 0);
    }

  if (last_con == NULL)
    symbol->value = expr;
  else
    last_con->expr = expr;

  return SUCCESS;
}