OSDN Git Service

PR fortran/15586
[pf3gnuchains/gcc-fork.git] / gcc / fortran / decl.c
index 4a566a9..69c0fc8 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 #include "config.h"
@@ -32,7 +32,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 static int old_char_selector;
 
-/* When variables aquire types and attributes from a declaration
+/* When variables acquire types and attributes from a declaration
    statement, they get them from the following static variables.  The
    first part of a declaration sets these variables and the second
    part copies these into symbol structures.  */
@@ -530,29 +530,34 @@ syntax:
 }
 
 
-/* Special subroutine for finding a symbol.  If we're compiling a
-   function or subroutine and the parent compilation unit is an
-   interface, then check to see if the name we've been given is the
-   name of the interface (located in another namespace).  If so,
-   return that symbol.  If not, use gfc_get_symbol().  */
+/* Special subroutine for finding a symbol.  Check if the name is found
+   in the current name space.  If not, and we're compiling a function or
+   subroutine and the parent compilation unit is an interface, then check
+   to see if the name we've been given is the name of the interface
+   (located in another namespace).  */
 
 static int
 find_special (const char *name, gfc_symbol ** result)
 {
   gfc_state_data *s;
+  int i;
 
+  i = gfc_get_symbol (name, NULL, result);
+  if (i==0) 
+    goto end;
+  
   if (gfc_current_state () != COMP_SUBROUTINE
       && gfc_current_state () != COMP_FUNCTION)
-    goto normal;
+    goto end;
 
   s = gfc_state_stack->previous;
   if (s == NULL)
-    goto normal;
+    goto end;
 
   if (s->state != COMP_INTERFACE)
-    goto normal;
+    goto end;
   if (s->sym == NULL)
-    goto normal;               /* Nameless interface */
+    goto end;                  /* Nameless interface */
 
   if (strcmp (name, s->sym->name) == 0)
     {
@@ -560,8 +565,8 @@ find_special (const char *name, gfc_symbol ** result)
       return 0;
     }
 
-normal:
-  return gfc_get_symbol (name, NULL, result);
+end:
+  return i;
 }
 
 
@@ -616,7 +621,8 @@ build_sym (const char *name, gfc_charlen * cl,
   symbol_attribute attr;
   gfc_symbol *sym;
 
-  if (find_special (name, &sym))
+  /* if (find_special (name, &sym)) */
+  if (gfc_get_symbol (name, NULL, &sym))
     return FAILURE;
 
   /* Start updating the symbol table.  Add basic type attribute
@@ -740,6 +746,13 @@ add_init_expr_to_sym (const char *name, gfc_expr ** initp,
          /* Update symbol character length according initializer.  */
          if (sym->ts.cl->length == NULL)
            {
+             /* If there are multiple CHARACTER variables declared on
+                the same line, we don't want them to share the same
+               length.  */
+             sym->ts.cl = gfc_get_charlen ();
+             sym->ts.cl->next = gfc_current_ns->cl_list;
+             gfc_current_ns->cl_list = sym->ts.cl;
+
              if (init->expr_type == EXPR_CONSTANT)
                sym->ts.cl->length =
                        gfc_int_expr (init->value.character.length);
@@ -894,7 +907,7 @@ gfc_match_null (gfc_expr ** result)
    symbol table or the current interface.  */
 
 static match
-variable_decl (void)
+variable_decl (int elem)
 {
   char name[GFC_MAX_SYMBOL_LEN + 1];
   gfc_expr *initializer, *char_len;
@@ -938,8 +951,20 @@ variable_decl (void)
          cl->length = char_len;
          break;
 
+       /* Non-constant lengths need to be copied after the first
+          element.  */
        case MATCH_NO:
-         cl = current_ts.cl;
+         if (elem > 1 && current_ts.cl->length
+               && current_ts.cl->length->expr_type != EXPR_CONSTANT)
+           {
+             cl = gfc_get_charlen ();
+             cl->next = gfc_current_ns->cl_list;
+             gfc_current_ns->cl_list = cl;
+             cl->length = gfc_copy_expr (current_ts.cl->length);
+           }
+         else
+           cl = current_ts.cl;
+
          break;
 
        case MATCH_ERROR:
@@ -1069,7 +1094,7 @@ variable_decl (void)
     t = add_init_expr_to_sym (name, &initializer, &var_locus);
   else
     {
-      if (current_ts.type == BT_DERIVED && !initializer)
+      if (current_ts.type == BT_DERIVED && !current_attr.pointer && !initializer)
        initializer = gfc_default_initializer (&current_ts);
       t = build_struct (name, cl, &initializer, &as);
     }
@@ -1361,6 +1386,24 @@ match_type_spec (gfc_typespec * ts, int implicit_flag)
 
   gfc_clear_ts (ts);
 
+  if (gfc_match (" byte") == MATCH_YES)
+    {
+      if (gfc_notify_std(GFC_STD_GNU, "Extension: BYTE type at %C") 
+         == FAILURE)
+       return MATCH_ERROR;
+
+      if (gfc_validate_kind (BT_INTEGER, 1, true) < 0)
+       {
+         gfc_error ("BYTE type used at %C "
+                    "is not available on the target machine");
+         return MATCH_ERROR;
+       }
+      
+      ts->type = BT_INTEGER;
+      ts->kind = 1;
+      return MATCH_YES;
+    }
+
   if (gfc_match (" integer") == MATCH_YES)
     {
       ts->type = BT_INTEGER;
@@ -1849,6 +1892,20 @@ match_attr_spec (void)
          goto cleanup;
        }
 
+      if ((d == DECL_PRIVATE || d == DECL_PUBLIC)
+            && gfc_current_state () != COMP_MODULE)
+       {
+         if (d == DECL_PRIVATE)
+           attr = "PRIVATE";
+         else
+           attr = "PUBLIC";
+
+         gfc_error ("%s attribute at %L is not allowed outside of a MODULE",
+                    attr, &seen_at[d]);
+         m = MATCH_ERROR;
+         goto cleanup;
+       }
+
       switch (d)
        {
        case DECL_ALLOCATABLE:
@@ -1938,6 +1995,7 @@ gfc_match_data_decl (void)
 {
   gfc_symbol *sym;
   match m;
+  int elem;
 
   m = match_type_spec (&current_ts, 0);
   if (m != MATCH_YES)
@@ -1989,10 +2047,12 @@ ok:
   if (m == MATCH_NO && current_ts.type == BT_CHARACTER && old_char_selector)
     gfc_match_char (',');
 
-  /* Give the types/attributes to symbols that follow.  */
+  /* Give the types/attributes to symbols that follow. Give the element
+     a number so that repeat character length expressions can be copied.  */
+  elem = 1;
   for (;;)
     {
-      m = variable_decl ();
+      m = variable_decl (elem++);
       if (m == MATCH_ERROR)
        goto cleanup;
       if (m == MATCH_NO)
@@ -2359,11 +2419,57 @@ gfc_match_entry (void)
     return m;
 
   state = gfc_current_state ();
-  if (state != COMP_SUBROUTINE
-      && state != COMP_FUNCTION)
+  if (state != COMP_SUBROUTINE && state != COMP_FUNCTION)
     {
-      gfc_error ("ENTRY statement at %C cannot appear within %s",
-                gfc_state_name (gfc_current_state ()));
+      switch (state)
+       {
+         case COMP_PROGRAM:
+           gfc_error ("ENTRY statement at %C cannot appear within a PROGRAM");
+           break;
+         case COMP_MODULE:
+           gfc_error ("ENTRY statement at %C cannot appear within a MODULE");
+           break;
+         case COMP_BLOCK_DATA:
+           gfc_error
+             ("ENTRY statement at %C cannot appear within a BLOCK DATA");
+           break;
+         case COMP_INTERFACE:
+           gfc_error
+             ("ENTRY statement at %C cannot appear within an INTERFACE");
+           break;
+         case COMP_DERIVED:
+           gfc_error
+             ("ENTRY statement at %C cannot appear "
+              "within a DERIVED TYPE block");
+           break;
+         case COMP_IF:
+           gfc_error
+             ("ENTRY statement at %C cannot appear within an IF-THEN block");
+           break;
+         case COMP_DO:
+           gfc_error
+             ("ENTRY statement at %C cannot appear within a DO block");
+           break;
+         case COMP_SELECT:
+           gfc_error
+             ("ENTRY statement at %C cannot appear within a SELECT block");
+           break;
+         case COMP_FORALL:
+           gfc_error
+             ("ENTRY statement at %C cannot appear within a FORALL block");
+           break;
+         case COMP_WHERE:
+           gfc_error
+             ("ENTRY statement at %C cannot appear within a WHERE block");
+           break;
+         case COMP_CONTAINS:
+           gfc_error
+             ("ENTRY statement at %C cannot appear "
+              "within a contained subprogram");
+           break;
+         default:
+           gfc_internal_error ("gfc_match_entry(): Bad state");
+       }
       return MATCH_ERROR;
     }
 
@@ -2395,7 +2501,7 @@ gfc_match_entry (void)
   else
     {
       /* An entry in a function.  */
-      m = gfc_match_formal_arglist (entry, 0, 0);
+      m = gfc_match_formal_arglist (entry, 0, 1);
       if (m != MATCH_YES)
        return MATCH_ERROR;
 
@@ -2407,8 +2513,7 @@ gfc_match_entry (void)
              || gfc_add_function (&entry->attr, entry->name, NULL) == FAILURE)
            return MATCH_ERROR;
 
-         entry->result = proc->result;
-
+         entry->result = entry;
        }
       else
        {
@@ -2423,6 +2528,8 @@ gfc_match_entry (void)
              || gfc_add_function (&entry->attr, result->name,
                                   NULL) == FAILURE)
            return MATCH_ERROR;
+
+         entry->result = result;
        }
 
       if (proc->attr.recursive && result == NULL)
@@ -3100,6 +3207,16 @@ do_parm (void)
       goto cleanup;
     }
 
+  if (sym->ts.type == BT_CHARACTER
+      && sym->ts.cl != NULL
+      && sym->ts.cl->length != NULL
+      && sym->ts.cl->length->expr_type == EXPR_CONSTANT
+      && init->expr_type == EXPR_CONSTANT
+      && init->ts.type == BT_CHARACTER
+      && init->ts.kind == 1)
+    gfc_set_constant_character_len (
+      mpz_get_si (sym->ts.cl->length->value.integer), init);
+
   sym->value = init;
   return MATCH_YES;
 
@@ -3218,7 +3335,7 @@ syntax:
 
 /* Match a module procedure statement.  Note that we have to modify
    symbols in the parent's namespace because the current one was there
-   to receive symbols that are in a interface's formal argument list.  */
+   to receive symbols that are in an interface's formal argument list.  */
 
 match
 gfc_match_modproc (void)