OSDN Git Service

PR fortran/50409
[pf3gnuchains/gcc-fork.git] / gcc / fortran / decl.c
index 638a738..2dd38b9 100644 (file)
@@ -119,7 +119,7 @@ free_variable (gfc_data_variable *p)
       gfc_free_expr (p->expr);
       gfc_free_iterator (&p->iter, 0);
       free_variable (p->list);
-      gfc_free (p);
+      free (p);
     }
 }
 
@@ -136,7 +136,7 @@ free_value (gfc_data_value *p)
       q = p->next;
       mpz_clear (p->repeat);
       gfc_free_expr (p->expr);
-      gfc_free (p);
+      free (p);
     }
 }
 
@@ -153,7 +153,7 @@ gfc_free_data (gfc_data *p)
       q = p->next;
       free_variable (p->var);
       free_value (p->value);
-      gfc_free (p);
+      free (p);
     }
 }
 
@@ -168,7 +168,7 @@ gfc_free_data_all (gfc_namespace *ns)
   for (;ns->data;)
     {
       d = ns->data->next;
-      gfc_free (ns->data);
+      free (ns->data);
       ns->data = d;
     }
 }
@@ -491,14 +491,14 @@ match_old_style_init (const char *name)
   m = top_val_list (newdata);
   if (m != MATCH_YES)
     {
-      gfc_free (newdata);
+      free (newdata);
       return m;
     }
 
   if (gfc_pure (NULL))
     {
       gfc_error ("Initialization at %C is not allowed in a PURE procedure");
-      gfc_free (newdata);
+      free (newdata);
       return MATCH_ERROR;
     }
 
@@ -508,7 +508,7 @@ match_old_style_init (const char *name)
   /* Mark the variable as having appeared in a data statement.  */
   if (gfc_add_data (&sym->attr, sym->name, &sym->declared_at) == FAILURE)
     {
-      gfc_free (newdata);
+      free (newdata);
       return MATCH_ERROR;
     }
 
@@ -961,7 +961,7 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry)
    across platforms.  */
 
 gfc_try
-verify_c_interop_param (gfc_symbol *sym)
+gfc_verify_c_interop_param (gfc_symbol *sym)
 {
   int is_c_interop = 0;
   gfc_try retval = SUCCESS;
@@ -1000,20 +1000,24 @@ verify_c_interop_param (gfc_symbol *sym)
     {
       if (sym->ns->proc_name->attr.is_bind_c == 1)
        {
-         is_c_interop =
-           (verify_c_interop (&(sym->ts))
-            == SUCCESS ? 1 : 0);
+         is_c_interop = (gfc_verify_c_interop (&(sym->ts)) == SUCCESS ? 1 : 0);
 
          if (is_c_interop != 1)
            {
              /* Make personalized messages to give better feedback.  */
              if (sym->ts.type == BT_DERIVED)
-               gfc_error ("Type '%s' at %L is a parameter to the BIND(C) "
-                          "procedure '%s' but is not C interoperable "
+               gfc_error ("Variable '%s' at %L is a dummy argument to the "
+                          "BIND(C) procedure '%s' but is not C interoperable "
                           "because derived type '%s' is not C interoperable",
                           sym->name, &(sym->declared_at),
                           sym->ns->proc_name->name, 
                           sym->ts.u.derived->name);
+             else if (sym->ts.type == BT_CLASS)
+               gfc_error ("Variable '%s' at %L is a dummy argument to the "
+                          "BIND(C) procedure '%s' but is not C interoperable "
+                          "because it is polymorphic",
+                          sym->name, &(sym->declared_at),
+                          sym->ns->proc_name->name);
              else
                gfc_warning ("Variable '%s' at %L is a parameter to the "
                             "BIND(C) procedure '%s' but may not be C "
@@ -1060,14 +1064,22 @@ verify_c_interop_param (gfc_symbol *sym)
              retval = FAILURE;
            }
 
-         if (sym->attr.optional == 1)
+         if (sym->attr.optional == 1 && sym->attr.value)
            {
-             gfc_error ("Variable '%s' at %L cannot have the "
-                        "OPTIONAL attribute because procedure '%s'"
-                        " is BIND(C)", sym->name, &(sym->declared_at),
+             gfc_error ("Variable '%s' at %L cannot have both the OPTIONAL "
+                        "and the VALUE attribute because procedure '%s' "
+                        "is BIND(C)", sym->name, &(sym->declared_at),
                         sym->ns->proc_name->name);
              retval = FAILURE;
            }
+         else if (sym->attr.optional == 1
+                  && gfc_notify_std (GFC_STD_F2008_TS, "TS29113: Variable '%s' "
+                                     "at %L with OPTIONAL attribute in "
+                                     "procedure '%s' which is BIND(C)",
+                                     sym->name, &(sym->declared_at),
+                                     sym->ns->proc_name->name)
+                     == FAILURE)
+           retval = FAILURE;
 
           /* Make sure that if it has the dimension attribute, that it is
             either assumed size or explicit shape.  */
@@ -1177,10 +1189,8 @@ build_sym (const char *name, gfc_charlen *cl, bool cl_deferred,
 
   sym->attr.implied_index = 0;
 
-  if (sym->ts.type == BT_CLASS
-      && (sym->attr.class_ok = sym->attr.dummy || sym->attr.pointer
-                              || sym->attr.allocatable))
-    gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as, false);
+  if (sym->ts.type == BT_CLASS)
+    return gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as, false);
 
   return SUCCESS;
 }
@@ -1222,7 +1232,7 @@ gfc_set_constant_character_len (int len, gfc_expr *expr, int check_len)
                        &expr->where, slen, check_len);
 
       s[len] = '\0';
-      gfc_free (expr->value.character.string);
+      free (expr->value.character.string);
       expr->value.character.string = s;
       expr->value.character.length = len;
     }
@@ -1277,7 +1287,7 @@ gfc_free_enum_history (void)
   while (current != NULL)
     {
       next = current->next;
-      gfc_free (current);
+      free (current);
       current = next;
     }
   max_enum = NULL;
@@ -1639,10 +1649,9 @@ scalar:
       bool delayed = (gfc_state_stack->sym == c->ts.u.derived)
                     || (!c->ts.u.derived->components
                         && !c->ts.u.derived->attr.zero_comp);
-      gfc_build_class_symbol (&c->ts, &c->attr, &c->as, delayed);
+      return gfc_build_class_symbol (&c->ts, &c->attr, &c->as, delayed);
     }
 
-
   return t;
 }
 
@@ -1724,6 +1733,30 @@ match_pointer_init (gfc_expr **init, int procptr)
 }
 
 
+static gfc_try
+check_function_name (char *name)
+{
+  /* In functions that have a RESULT variable defined, the function name always
+     refers to function calls.  Therefore, the name is not allowed to appear in
+     specification statements. When checking this, be careful about
+     'hidden' procedure pointer results ('ppr@').  */
+
+  if (gfc_current_state () == COMP_FUNCTION)
+    {
+      gfc_symbol *block = gfc_current_block ();
+      if (block && block->result && block->result != block
+         && strcmp (block->result->name, "ppr@") != 0
+         && strcmp (block->name, name) == 0)
+       {
+         gfc_error ("Function name '%s' not allowed at %C", name);
+         return FAILURE;
+       }
+    }
+
+  return SUCCESS;
+}
+
+
 /* Match a variable name with an optional initializer.  When this
    subroutine is called, a variable is expected to be parsed next.
    Depending on what is happening at the moment, updates either the
@@ -1758,9 +1791,7 @@ variable_decl (int elem)
 
   /* Now we could see the optional array spec. or character length.  */
   m = gfc_match_array_spec (&as, true, true);
-  if (gfc_option.flag_cray_pointer && m == MATCH_YES)
-    cp_as = gfc_copy_array_spec (as);
-  else if (m == MATCH_ERROR)
+  if (m == MATCH_ERROR)
     goto cleanup;
 
   if (m == MATCH_NO)
@@ -1768,6 +1799,9 @@ variable_decl (int elem)
   else if (current_as)
     merge_array_spec (current_as, as, true);
 
+  if (gfc_option.flag_cray_pointer)
+    cp_as = gfc_copy_array_spec (as);
+
   /* At this point, we know for sure if the symbol is PARAMETER and can thus
      determine (and check) whether it can be implied-shape.  If it
      was parsed as assumed-size, change it because PARAMETERs can not
@@ -1929,17 +1963,9 @@ variable_decl (int elem)
            goto cleanup;
        }
     }
-
-  /* In functions that have a RESULT variable defined, the function
-     name always refers to function calls.  Therefore, the name is
-     not allowed to appear in specification statements.  */
-  if (gfc_current_state () == COMP_FUNCTION
-      && gfc_current_block () != NULL
-      && gfc_current_block ()->result != NULL
-      && gfc_current_block ()->result != gfc_current_block ()
-      && strcmp (gfc_current_block ()->name, name) == 0)
+    
+  if (check_function_name (name) == FAILURE)
     {
-      gfc_error ("Function name '%s' not allowed at %C", name);
       m = MATCH_ERROR;
       goto cleanup;
     }
@@ -2614,6 +2640,16 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag)
     ts->type = BT_DERIVED;
   else
     {
+      /* Match CLASS declarations.  */
+      m = gfc_match (" class ( * )");
+      if (m == MATCH_ERROR)
+       return MATCH_ERROR;
+      else if (m == MATCH_YES)
+       {
+         gfc_fatal_error ("Unlimited polymorphism at %C not yet supported");
+         return MATCH_ERROR;
+       }
+
       m = gfc_match (" class ( %n )", name);
       if (m != MATCH_YES)
        return m;
@@ -2978,6 +3014,7 @@ gfc_match_import (void)
 
   for(;;)
     {
+      sym = NULL;
       m = gfc_match (" %n", name);
       switch (m)
        {
@@ -2988,7 +3025,7 @@ gfc_match_import (void)
               gfc_error ("Type name '%s' at %C is ambiguous", name);
               return MATCH_ERROR;
            }
-         else if (gfc_current_ns->proc_name->ns->parent !=  NULL
+         else if (!sym && gfc_current_ns->proc_name->ns->parent !=  NULL
                   && gfc_find_symbol (name,
                                       gfc_current_ns->proc_name->ns->parent,
                                       1, &sym))
@@ -3328,7 +3365,7 @@ match_attr_spec (void)
          else if (m == MATCH_YES)
            {
              merge_array_spec (as, current_as, false);
-             gfc_free (as);
+             free (as);
            }
 
          if (m == MATCH_NO)
@@ -3678,11 +3715,13 @@ set_com_block_bind_c (gfc_common_head *com_block, int is_bind_c)
 /* Verify that the given gfc_typespec is for a C interoperable type.  */
 
 gfc_try
-verify_c_interop (gfc_typespec *ts)
+gfc_verify_c_interop (gfc_typespec *ts)
 {
   if (ts->type == BT_DERIVED && ts->u.derived != NULL)
     return (ts->u.derived->ts.is_c_interop || ts->u.derived->attr.is_bind_c)
           ? SUCCESS : FAILURE;
+  else if (ts->type == BT_CLASS)
+    return FAILURE;
   else if (ts->is_c_interop != 1)
     return FAILURE;
   
@@ -3755,7 +3794,7 @@ verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
      the given ts (current_ts), so look in both.  */
   if (tmp_sym->ts.type != BT_UNKNOWN || ts->type != BT_UNKNOWN) 
     {
-      if (verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
+      if (gfc_verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
        {
          /* See if we're dealing with a sym in a common block or not.  */
          if (is_in_common == 1)
@@ -4730,8 +4769,9 @@ match_procedure_decl (void)
            return MATCH_ERROR;
          sym->ts.interface = gfc_new_symbol ("", gfc_current_ns);
          sym->ts.interface->ts = current_ts;
+         sym->ts.interface->attr.flavor = FL_PROCEDURE;
          sym->ts.interface->attr.function = 1;
-         sym->attr.function = sym->ts.interface->attr.function;
+         sym->attr.function = 1;
          sym->attr.if_source = IFSRC_UNKNOWN;
        }
 
@@ -4864,8 +4904,9 @@ match_ppc_decl (void)
          c->ts = ts;
          c->ts.interface = gfc_new_symbol ("", gfc_current_ns);
          c->ts.interface->ts = ts;
+         c->ts.interface->attr.flavor = FL_PROCEDURE;
          c->ts.interface->attr.function = 1;
-         c->attr.function = c->ts.interface->attr.function;
+         c->attr.function = 1;
          c->attr.if_source = IFSRC_UNKNOWN;
        }
 
@@ -4951,6 +4992,7 @@ gfc_match_procedure (void)
     case COMP_MODULE:
     case COMP_SUBROUTINE:
     case COMP_FUNCTION:
+    case COMP_BLOCK:
       m = match_procedure_decl ();
       break;
     case COMP_INTERFACE:
@@ -5212,6 +5254,7 @@ gfc_match_entry (void)
                       "an IF-THEN block");
            break;
          case COMP_DO:
+         case COMP_DO_CONCURRENT:
            gfc_error ("ENTRY statement at %C cannot appear within "
                       "a DO block");
            break;
@@ -5737,7 +5780,7 @@ gfc_match_end (gfc_statement *st)
     {
     case COMP_ASSOCIATE:
     case COMP_BLOCK:
-      if (!strcmp (block_name, "block@"))
+      if (!strncmp (block_name, "block@", strlen("block@")))
        block_name = NULL;
       break;
 
@@ -5817,6 +5860,7 @@ gfc_match_end (gfc_statement *st)
       break;
 
     case COMP_DO:
+    case COMP_DO_CONCURRENT:
       *st = ST_ENDDO;
       target = " do";
       eos_ok = 0;
@@ -5975,6 +6019,12 @@ attr_decl1 (void)
   if (find_special (name, &sym, false))
     return MATCH_ERROR;
 
+  if (check_function_name (name) == FAILURE)
+    {
+      m = MATCH_ERROR;
+      goto cleanup;
+    }
+  
   var_locus = gfc_current_locus;
 
   /* Deal with possible array specification for certain attributes.  */
@@ -6046,10 +6096,12 @@ attr_decl1 (void)
        }
     }
     
-  if (sym->ts.type == BT_CLASS && !sym->attr.class_ok
-      && (sym->attr.class_ok = sym->attr.class_ok || current_attr.allocatable
-                              || current_attr.pointer))
-    gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as, false);
+  if (sym->ts.type == BT_CLASS
+      && gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as, false) == FAILURE)
+    {
+      m = MATCH_ERROR;
+      goto cleanup;
+    }
 
   if (gfc_set_array_spec (sym, as, &var_locus) == FAILURE)
     {
@@ -6458,8 +6510,19 @@ access_attr_decl (gfc_statement st)
        case INTERFACE_INTRINSIC_OP:
          if (gfc_current_ns->operator_access[op] == ACCESS_UNKNOWN)
            {
+             gfc_intrinsic_op other_op;
+
              gfc_current_ns->operator_access[op] =
                (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE;
+
+             /* Handle the case if there is another op with the same
+                function, for INTRINSIC_EQ vs. INTRINSIC_EQ_OS and so on.  */
+             other_op = gfc_equivalent_op (op);
+
+             if (other_op != INTRINSIC_NONE)
+               gfc_current_ns->operator_access[other_op] =
+                 (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE;
+
            }
          else
            {
@@ -6985,6 +7048,7 @@ gfc_match_modproc (void)
   char name[GFC_MAX_SYMBOL_LEN + 1];
   gfc_symbol *sym;
   match m;
+  locus old_locus;
   gfc_namespace *module_ns;
   gfc_interface *old_interface_head, *interface;
 
@@ -7013,10 +7077,23 @@ gfc_match_modproc (void)
      end up with a syntax error and need to recover.  */
   old_interface_head = gfc_current_interface_head ();
 
+  /* Check if the F2008 optional double colon appears.  */
+  gfc_gobble_whitespace ();
+  old_locus = gfc_current_locus;
+  if (gfc_match ("::") == MATCH_YES)
+    {
+      if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: double colon in "
+                        "MODULE PROCEDURE statement at %L", &old_locus)
+         == FAILURE)
+       return MATCH_ERROR;
+    }
+  else
+    gfc_current_locus = old_locus;
+      
   for (;;)
     {
-      locus old_locus = gfc_current_locus;
       bool last = false;
+      old_locus = gfc_current_locus;
 
       m = gfc_match_name (name);
       if (m == MATCH_NO)
@@ -7028,6 +7105,7 @@ gfc_match_modproc (void)
         current namespace.  */
       if (gfc_match_eos () == MATCH_YES)
        last = true;
+
       if (!last && gfc_match_char (',') != MATCH_YES)
        goto syntax;
 
@@ -7069,7 +7147,7 @@ syntax:
   while (interface != old_interface_head)
   {
     gfc_interface *i = interface->next;
-    gfc_free (interface);
+    free (interface);
     interface = i;
   }