gfc_typebound_proc*
gfc_find_typebound_intrinsic_op (gfc_symbol* derived, gfc_try* t,
                                 gfc_intrinsic_op op, bool noaccess,
                                 locus* where)
{
    gfc_typebound_proc* res;

    /* Set default to failure.  */
    if (t)
        *t = FAILURE;

    /* Try to find it in the current type's namespace.  */
    if (derived->f2k_derived)
        res = derived->f2k_derived->tb_op[op];
    else
        res = NULL;

    /* Check access.  */
    if (res && !res->error)
    {
        /* We found one.  */
        if (t)
            *t = SUCCESS;

        if (!noaccess && derived->attr.use_assoc
                && res->access == ACCESS_PRIVATE)
        {
            if (where)
                gfc_error ("'%s' of '%s' is PRIVATE at %L",
                           gfc_op2string (op), derived->name, where);
            if (t)
                *t = FAILURE;
        }

        return res;
    }

    /* Otherwise, recurse on parent type if derived is an extension.  */
    if (derived->attr.extension)
    {
        gfc_symbol* super_type;
        super_type = gfc_get_derived_super_type (derived);
        gcc_assert (super_type);

        return gfc_find_typebound_intrinsic_op (super_type, t, op,
                                                noaccess, where);
    }

    /* Nothing found.  */
    return NULL;
}
void
gfc_check_interfaces (gfc_namespace * ns)
{
    gfc_namespace *old_ns, *ns2;
    char interface_name[100];
    gfc_intrinsic_op i;

    old_ns = gfc_current_ns;
    gfc_current_ns = ns;

    gfc_traverse_ns (ns, check_sym_interfaces);

    gfc_traverse_user_op (ns, check_uop_interfaces);

    for (i = GFC_INTRINSIC_BEGIN; i != GFC_INTRINSIC_END; i++)
    {
        if (i == INTRINSIC_USER)
            continue;

        if (i == INTRINSIC_ASSIGN)
            strcpy (interface_name, "intrinsic assignment operator");
        else
            sprintf (interface_name, "intrinsic '%s' operator",
                     gfc_op2string (i));

        if (check_interface0 (ns->operator[i], interface_name))
            continue;

        check_operator_interface (ns->operator[i], i);

        for (ns2 = ns->parent; ns2; ns2 = ns2->parent)
            if (check_interface1 (ns->operator[i], ns2->operator[i], 0,
                                  interface_name))
                break;
    }

    gfc_current_ns = old_ns;
}
Exemple #3
0
static void
show_f2k_derived (gfc_namespace* f2k)
{
  gfc_finalizer* f;
  int op;

  show_indent ();
  fputs ("Procedure bindings:", dumpfile);
  ++show_level;

  /* Finalizer bindings.  */
  for (f = f2k->finalizers; f; f = f->next)
    {
      show_indent ();
      fprintf (dumpfile, "FINAL %s", f->proc_tree->n.sym->name);
    }

  /* Type-bound procedures.  */
  gfc_traverse_symtree (f2k->tb_sym_root, &show_typebound_symtree);

  --show_level;

  show_indent ();
  fputs ("Operator bindings:", dumpfile);
  ++show_level;

  /* User-defined operators.  */
  gfc_traverse_symtree (f2k->tb_uop_root, &show_typebound_symtree);

  /* Intrinsic operators.  */
  for (op = GFC_INTRINSIC_BEGIN; op != GFC_INTRINSIC_END; ++op)
    if (f2k->tb_op[op])
      show_typebound_proc (f2k->tb_op[op],
			   gfc_op2string ((gfc_intrinsic_op) op));

  --show_level;
}
Exemple #4
0
static void
show_namespace (gfc_namespace *ns)
{
  gfc_interface *intr;
  gfc_namespace *save;
  int op;
  gfc_equiv *eq;
  int i;

  gcc_assert (ns);
  save = gfc_current_ns;

  show_indent ();
  fputs ("Namespace:", dumpfile);

  i = 0;
  do
    {
      int l = i;
      while (i < GFC_LETTERS - 1
	     && gfc_compare_types (&ns->default_type[i+1],
				   &ns->default_type[l]))
	i++;

      if (i > l)
	fprintf (dumpfile, " %c-%c: ", l+'A', i+'A');
      else
	fprintf (dumpfile, " %c: ", l+'A');

      show_typespec(&ns->default_type[l]);
      i++;
    } while (i < GFC_LETTERS);

  if (ns->proc_name != NULL)
    {
      show_indent ();
      fprintf (dumpfile, "procedure name = %s", ns->proc_name->name);
    }

  ++show_level;
  gfc_current_ns = ns;
  gfc_traverse_symtree (ns->common_root, show_common);

  gfc_traverse_symtree (ns->sym_root, show_symtree);

  for (op = GFC_INTRINSIC_BEGIN; op != GFC_INTRINSIC_END; op++)
    {
      /* User operator interfaces */
      intr = ns->op[op];
      if (intr == NULL)
	continue;

      show_indent ();
      fprintf (dumpfile, "Operator interfaces for %s:",
	       gfc_op2string ((gfc_intrinsic_op) op));

      for (; intr; intr = intr->next)
	fprintf (dumpfile, " %s", intr->sym->name);
    }

  if (ns->uop_root != NULL)
    {
      show_indent ();
      fputs ("User operators:\n", dumpfile);
      gfc_traverse_user_op (ns, show_uop);
    }
  
  for (eq = ns->equiv; eq; eq = eq->next)
    show_equiv (eq);

  fputc ('\n', dumpfile);
  show_indent ();
  fputs ("code:", dumpfile);
  show_code (show_level, ns->code);
  --show_level;

  for (ns = ns->contained; ns; ns = ns->sibling)
    {
      fputs ("\nCONTAINS\n", dumpfile);
      ++show_level;
      show_namespace (ns);
      --show_level;
    }

  fputc ('\n', dumpfile);
  gfc_current_ns = save;
}
void
gfc_show_namespace (gfc_namespace * ns)
{
  gfc_interface *intr;
  gfc_namespace *save;
  gfc_intrinsic_op op;
  gfc_equiv *eq;
  int i;

  save = gfc_current_ns;
  show_level++;

  show_indent ();
  gfc_status ("Namespace:");

  if (ns != NULL)
    {
      i = 0;
      do
	{
	  int l = i;
	  while (i < GFC_LETTERS - 1
		 && gfc_compare_types(&ns->default_type[i+1],
				      &ns->default_type[l]))
	    i++;

	  if (i > l)
	    gfc_status(" %c-%c: ", l+'A', i+'A');
	  else
	    gfc_status(" %c: ", l+'A');

	  gfc_show_typespec(&ns->default_type[l]);
	  i++;
      } while (i < GFC_LETTERS);

      if (ns->proc_name != NULL)
	{
	  show_indent ();
	  gfc_status ("procedure name = %s", ns->proc_name->name);
	}

      gfc_current_ns = ns;
      gfc_traverse_symtree (ns->common_root, show_common);

      gfc_traverse_symtree (ns->sym_root, show_symtree);

      for (op = GFC_INTRINSIC_BEGIN; op != GFC_INTRINSIC_END; op++)
	{
	  /* User operator interfaces */
	  intr = ns->operator[op];
	  if (intr == NULL)
	    continue;

	  show_indent ();
	  gfc_status ("Operator interfaces for %s:", gfc_op2string (op));

	  for (; intr; intr = intr->next)
	    gfc_status (" %s", intr->sym->name);
	}

      if (ns->uop_root != NULL)
	{
	  show_indent ();
	  gfc_status ("User operators:\n");
	  gfc_traverse_user_op (ns, show_uop);
	}
    }
  
  for (eq = ns->equiv; eq; eq = eq->next)
    gfc_show_equiv (eq);

  gfc_status_char ('\n');
  gfc_status_char ('\n');

  gfc_show_code (0, ns->code);

  for (ns = ns->contained; ns; ns = ns->sibling)
    {
      show_indent ();
      gfc_status ("CONTAINS\n");
      gfc_show_namespace (ns);
    }

  show_level--;
  gfc_status_char ('\n');
  gfc_current_ns = save;
}
match
gfc_match_end_interface (void)
{
    char name[GFC_MAX_SYMBOL_LEN + 1];
    interface_type type;
    gfc_intrinsic_op operator;
    match m;

    m = gfc_match_space ();

    if (gfc_match_generic_spec (&type, name, &operator) == MATCH_ERROR)
        return MATCH_ERROR;

    /* If we're not looking at the end of the statement now, or if this
       is not a nameless interface but we did not see a space, punt.  */
    if (gfc_match_eos () != MATCH_YES
            || (type != INTERFACE_NAMELESS
                && m != MATCH_YES))
    {
        gfc_error
        ("Syntax error: Trailing garbage in END INTERFACE statement at %C");
        return MATCH_ERROR;
    }

    m = MATCH_YES;

    switch (current_interface.type)
    {
    case INTERFACE_NAMELESS:
        if (type != current_interface.type)
        {
            gfc_error ("Expected a nameless interface at %C");
            m = MATCH_ERROR;
        }

        break;

    case INTERFACE_INTRINSIC_OP:
        if (type != current_interface.type || operator != current_interface.op)
        {

            if (current_interface.op == INTRINSIC_ASSIGN)
                gfc_error ("Expected 'END INTERFACE ASSIGNMENT (=)' at %C");
            else
                gfc_error ("Expecting 'END INTERFACE OPERATOR (%s)' at %C",
                           gfc_op2string (current_interface.op));

            m = MATCH_ERROR;
        }

        break;

    case INTERFACE_USER_OP:
        /* Comparing the symbol node names is OK because only use-associated
           symbols can be renamed.  */
        if (type != current_interface.type
                || strcmp (current_interface.sym->name, name) != 0)
        {
            gfc_error ("Expecting 'END INTERFACE OPERATOR (.%s.)' at %C",
                       current_interface.sym->name);
            m = MATCH_ERROR;
        }

        break;

    case INTERFACE_GENERIC:
        if (type != current_interface.type
                || strcmp (current_interface.sym->name, name) != 0)
        {
            gfc_error ("Expecting 'END INTERFACE %s' at %C",
                       current_interface.sym->name);
            m = MATCH_ERROR;
        }

        break;
    }

    return m;
}