2008-01-17 Paul Thomas <pault@gcc.gnu.org>
authorpault <pault@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Jan 2008 07:19:04 +0000 (07:19 +0000)
committerpault <pault@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Jan 2008 07:19:04 +0000 (07:19 +0000)
PR fortran/34429
PR fortran/34431
PR fortran/34471
* decl.c : Remove gfc_function_kind_locus and
gfc_function_type_locus. Add gfc_matching_function.
(match_char_length): If matching a function and the length
does not match, return MATCH_YES and try again later.
(gfc_match_kind_spec): The same.
(match_char_kind): The same.
(gfc_match_type_spec): The same for numeric and derived types.
(match_prefix): Rename as gfc_match_prefix.
(gfc_match_function_decl): Except for function valued character
lengths, defer applying kind, type and charlen info until the
end of specification block.
gfortran.h (gfc_statement): Add ST_GET_FCN_CHARACTERISTICS.
parse.c (decode_specification_statement): New function.
(decode_statement): Call it when a function has kind = -1. Set
and reset gfc_matching function, as function statement is being
matched.
(match_deferred_characteristics): Simplify with a single call
to gfc_match_prefix. Do appropriate error handling. In any
case, make sure that kind = -1 is reset or corrected.
(parse_spec): Call above on seeing ST_GET_FCN_CHARACTERISTICS.
Throw an error if kind = -1 after last specification statement.
parse.h : Prototype for gfc_match_prefix.

2008-01-17  Paul Thomas  <pault@gcc.gnu.org>

PR fortran/34429
* gfortran.dg/function_charlen_1.f90: New test.

PR fortran/34431
* gfortran.dg/function_types_1.f90: New test.
* gfortran.dg/function_types_2.f90: New test.

PR fortran/34471
* gfortran.dg/function_kinds_4.f90: New test.
* gfortran.dg/function_kinds_5.f90: New test.

* gfortran.dg/defined_operators_1.f90: Errors now at function
declarations.
* gfortran.dg/private_type_4.f90: The same.
* gfortran.dg/interface_15.f90: The same.
* gfortran.dg/elemental_args_check_2.f90: The same.
* gfortran.dg/auto_internal_assumed.f90: The same.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131592 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/fortran/ChangeLog
gcc/fortran/decl.c
gcc/fortran/gfortran.h
gcc/fortran/misc.c
gcc/fortran/parse.c
gcc/fortran/parse.h
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/auto_internal_assumed.f90
gcc/testsuite/gfortran.dg/defined_operators_1.f90
gcc/testsuite/gfortran.dg/elemental_args_check_2.f90
gcc/testsuite/gfortran.dg/function_charlen_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/function_kinds_4.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/function_kinds_5.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/function_types_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/function_types_2.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/interface_15.f90
gcc/testsuite/gfortran.dg/private_type_4.f90

index 35944a2..dccfcdf 100644 (file)
@@ -1,3 +1,31 @@
+2008-01-17  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/34429
+       PR fortran/34431
+       PR fortran/34471
+       * decl.c : Remove gfc_function_kind_locus and
+       gfc_function_type_locus. Add gfc_matching_function.
+       (match_char_length): If matching a function and the length
+       does not match, return MATCH_YES and try again later.
+       (gfc_match_kind_spec): The same.
+       (match_char_kind): The same.
+       (gfc_match_type_spec): The same for numeric and derived types.
+       (match_prefix): Rename as gfc_match_prefix.
+       (gfc_match_function_decl): Except for function valued character
+       lengths, defer applying kind, type and charlen info until the
+       end of specification block.
+       gfortran.h (gfc_statement): Add ST_GET_FCN_CHARACTERISTICS.
+       parse.c (decode_specification_statement): New function.
+       (decode_statement): Call it when a function has kind = -1. Set
+       and reset gfc_matching function, as function statement is being
+       matched.
+       (match_deferred_characteristics): Simplify with a single call
+       to gfc_match_prefix. Do appropriate error handling. In any
+       case, make sure that kind = -1 is reset or corrected.
+       (parse_spec): Call above on seeing ST_GET_FCN_CHARACTERISTICS.
+       Throw an error if kind = -1 after last specification statement.
+       parse.h : Prototype for gfc_match_prefix.
+
 2008-01-16  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/34796
index 74d0962..115b30e 100644 (file)
@@ -86,8 +86,7 @@ static enumerator_history *max_enum = NULL;
 
 gfc_symbol *gfc_new_block;
 
-locus gfc_function_kind_locus;
-locus gfc_function_type_locus;
+bool gfc_matching_function;
 
 
 /********************* DATA statement subroutines *********************/
@@ -653,6 +652,12 @@ match_char_length (gfc_expr **expr)
     goto syntax;
 
   m = char_len_param_value (expr);
+  if (m != MATCH_YES && gfc_matching_function)
+    {
+      gfc_undo_symbols ();
+      m = MATCH_YES;
+    }
+
   if (m == MATCH_ERROR)
     return m;
   if (m == MATCH_NO)
@@ -1869,13 +1874,11 @@ kind_expr:
 
   if (n != MATCH_YES)
     {
-      if (gfc_current_state () == COMP_INTERFACE
-            || gfc_current_state () == COMP_NONE
-            || gfc_current_state () == COMP_CONTAINS)
+      if (gfc_matching_function)
        {
-         /* Signal using kind = -1 that the expression might include
-            use associated or imported parameters and try again after
-            the specification expressions.....  */
+         /* The function kind expression might include use associated or 
+            imported parameters and try again after the specification
+            expressions.....  */
          if (gfc_match_char (')') != MATCH_YES)
            {
              gfc_error ("Missing right parenthesis at %C");
@@ -1884,8 +1887,6 @@ kind_expr:
            }
 
          gfc_free_expr (e);
-         ts->kind = -1;
-         gfc_function_kind_locus = loc;
          gfc_undo_symbols ();
          return MATCH_YES;
        }
@@ -1907,6 +1908,7 @@ kind_expr:
     }
 
   msg = gfc_extract_int (e, &ts->kind);
+
   if (msg != NULL)
     {
       gfc_error (msg);
@@ -1977,17 +1979,12 @@ match_char_kind (int * kind, int * is_iso_c)
 
   n = gfc_match_init_expr (&e);
 
-  if (n != MATCH_YES
-      && (gfc_current_state () == COMP_INTERFACE
-         || gfc_current_state () == COMP_NONE
-         || gfc_current_state () == COMP_CONTAINS))
+  if (n != MATCH_YES && gfc_matching_function)
     {
-      /* Signal using kind = -1 that the expression might include
-        use-associated or imported parameters and try again after
-        the specification expressions.  */
+      /* The expression might include use-associated or imported
+        parameters and try again after the specification 
+        expressions.  */
       gfc_free_expr (e);
-      *kind = -1;
-      gfc_function_kind_locus = where;
       gfc_undo_symbols ();
       return MATCH_YES;
     }
@@ -2154,6 +2151,17 @@ syntax:
   return m;
 
 done:
+  /* Except in the case of the length being a function, where symbol
+     association looks after itself, deal with character functions
+     after the specification statements.  */
+  if (gfc_matching_function
+       && !(len && len->expr_type != EXPR_VARIABLE
+                && len->expr_type != EXPR_OP))
+    {
+      gfc_undo_symbols ();
+      return MATCH_YES;
+    }
+
   if (m != MATCH_YES)
     {
       gfc_free_expr (len);
@@ -2209,9 +2217,16 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
   gfc_symbol *sym;
   match m;
   int c;
-  locus loc = gfc_current_locus;
+  bool seen_deferred_kind;
 
+  /* A belt and braces check that the typespec is correctly being treated
+     as a deferred characteristic association.  */
+  seen_deferred_kind = (gfc_current_state () == COMP_FUNCTION)
+                                       && (gfc_current_block ()->result->ts.kind == -1)
+                                       && (ts->kind == -1);
   gfc_clear_ts (ts);
+  if (seen_deferred_kind)
+    ts->kind = -1;
 
   /* Clear the current binding label, in case one is given.  */
   curr_binding_label[0] = '\0';
@@ -2293,18 +2308,24 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
   if (m != MATCH_YES)
     return m;
 
-  if (gfc_current_state () == COMP_INTERFACE
-       || gfc_current_state () == COMP_NONE)
+  ts->type = BT_DERIVED;
+
+  /* Defer association of the derived type until the end of the
+     specification block.  However, if the derived type can be
+     found, add it to the typespec.  */  
+  if (gfc_matching_function)
     {
-      gfc_function_type_locus = loc;
-      ts->type = BT_UNKNOWN;
-      ts->kind = -1;
+      ts->derived = NULL;
+      if (gfc_current_state () != COMP_INTERFACE
+           && !gfc_find_symbol (name, NULL, 1, &sym) && sym)
+       ts->derived = sym;
       return MATCH_YES;
     }
 
   /* Search for the name but allow the components to be defined later.  If
      type = -1, this typespec has been seen in a function declaration but
-     the type could not legally be accessed at that point.  */
+     the type could not be accessed at that point.  */
+  sym = NULL;
   if (ts->kind != -1 && gfc_get_ha_symbol (name, &sym))
     {
       gfc_error ("Type name '%s' at %C is ambiguous", name);
@@ -2312,12 +2333,15 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
     }
   else if (ts->kind == -1)
     {
-      if (gfc_find_symbol (name, NULL, 0, &sym))
+      int iface = gfc_state_stack->previous->state != COMP_INTERFACE
+                   || gfc_current_ns->has_import_set;
+      if (gfc_find_symbol (name, NULL, iface, &sym))
        {       
          gfc_error ("Type name '%s' at %C is ambiguous", name);
          return MATCH_ERROR;
        }
 
+      ts->kind = 0;
       if (sym == NULL)
        return MATCH_NO;
     }
@@ -2326,8 +2350,7 @@ gfc_match_type_spec (gfc_typespec *ts, int implicit_flag)
       && gfc_add_flavor (&sym->attr, FL_DERIVED, sym->name, NULL) == FAILURE)
     return MATCH_ERROR;
 
-  ts->type = BT_DERIVED;
-  ts->kind = 0;
+  gfc_set_sym_referenced (sym);
   ts->derived = sym;
 
   return MATCH_YES;
@@ -2350,6 +2373,12 @@ get_kind:
   if (m == MATCH_NO && ts->type != BT_CHARACTER)
     m = gfc_match_old_kind_spec (ts);
 
+  /* Defer association of the KIND expression of function results
+     until after USE and IMPORT statements.  */
+  if ((gfc_current_state () == COMP_NONE && gfc_error_flag_test ())
+        || gfc_matching_function)
+    return MATCH_YES;
+
   if (m == MATCH_NO)
     m = MATCH_YES;             /* No kind specifier found.  */
 
@@ -3673,8 +3702,8 @@ cleanup:
    can be matched.  Note that if nothing matches, MATCH_YES is
    returned (the null string was matched).  */
 
-static match
-match_prefix (gfc_typespec *ts)
+match
+gfc_match_prefix (gfc_typespec *ts)
 {
   bool seen_type;
 
@@ -3720,7 +3749,7 @@ loop:
 }
 
 
-/* Copy attributes matched by match_prefix() to attributes on a symbol.  */
+/* Copy attributes matched by gfc_match_prefix() to attributes on a symbol.  */
 
 static try
 copy_prefix (symbol_attribute *dest, locus *where)
@@ -4245,7 +4274,7 @@ gfc_match_function_decl (void)
 
   old_loc = gfc_current_locus;
 
-  m = match_prefix (&current_ts);
+  m = gfc_match_prefix (&current_ts);
   if (m != MATCH_YES)
     {
       gfc_current_locus = old_loc;
@@ -4329,6 +4358,22 @@ gfc_match_function_decl (void)
          goto cleanup;
        }
 
+      /* Except in the case of a function valued character length,
+        delay matching the function characteristics until after the
+        specification block by signalling kind=-1.  */
+      if (!(current_ts.type == BT_CHARACTER
+             && current_ts.cl
+             && current_ts.cl->length
+             && current_ts.cl->length->expr_type != EXPR_OP
+             && current_ts.cl->length->expr_type != EXPR_VARIABLE))
+       {
+         sym->declared_at = old_loc;
+         if (current_ts.type != BT_UNKNOWN)
+           current_ts.kind = -1;
+         else
+           current_ts.kind = 0;
+       }
+
       if (result == NULL)
        {
          sym->ts = current_ts;
@@ -4635,7 +4680,7 @@ gfc_match_subroutine (void)
       && gfc_current_state () != COMP_CONTAINS)
     return MATCH_NO;
 
-  m = match_prefix (NULL);
+  m = gfc_match_prefix (NULL);
   if (m != MATCH_YES)
     return m;
 
index 54c6ad8..aac1f82 100644 (file)
@@ -223,7 +223,7 @@ typedef enum
   ST_OMP_PARALLEL, ST_OMP_PARALLEL_DO, ST_OMP_PARALLEL_SECTIONS,
   ST_OMP_PARALLEL_WORKSHARE, ST_OMP_SECTIONS, ST_OMP_SECTION, ST_OMP_SINGLE,
   ST_OMP_THREADPRIVATE, ST_OMP_WORKSHARE, ST_PROCEDURE,
-  ST_NONE
+  ST_GET_FCN_CHARACTERISTICS, ST_NONE
 }
 gfc_statement;
 
index 4bc5c43..5ee5434 100644 (file)
@@ -74,8 +74,8 @@ void
 gfc_clear_ts (gfc_typespec *ts)
 {
   ts->type = BT_UNKNOWN;
-  ts->kind = 0;
   ts->derived = NULL;
+  ts->kind = 0;
   ts->cl = NULL;
   /* flag that says if the type is C interoperable */
   ts->is_c_interop = 0;
index c941b4e..e57e10d 100644 (file)
@@ -85,6 +85,144 @@ match_word (const char *str, match (*subr) (void), locus *old_locus)
        undo_new_statement ();                            \
     } while (0);
 
+
+/* This is a specialist version of decode_statement that is used
+   for the specification statements in a function, whose
+   characteristics are deferred into the specification statements.
+   eg.:  INTEGER (king = mykind) foo ()
+        USE mymodule, ONLY mykind..... 
+   The KIND parameter needs a return after USE or IMPORT, whereas
+   derived type declarations can occur anywhere, up the executable
+   block.  ST_GET_FCN_CHARACTERISTICS is returned when we have run
+   out of the correct kind of specification statements.  */
+static gfc_statement
+decode_specification_statement (void)
+{
+  gfc_statement st;
+  locus old_locus;
+  int c;
+
+  if (gfc_match_eos () == MATCH_YES)
+    return ST_NONE;
+
+  old_locus = gfc_current_locus;
+
+  match ("import", gfc_match_import, ST_IMPORT);
+  match ("use", gfc_match_use, ST_USE);
+
+  if (gfc_numeric_ts (&gfc_current_block ()->ts))
+    goto end_of_block;
+
+  match (NULL, gfc_match_st_function, ST_STATEMENT_FUNCTION);
+  match (NULL, gfc_match_data_decl, ST_DATA_DECL);
+  match (NULL, gfc_match_enumerator_def, ST_ENUMERATOR);
+
+  /* General statement matching: Instead of testing every possible
+     statement, we eliminate most possibilities by peeking at the
+     first character.  */
+
+  c = gfc_peek_char ();
+
+  switch (c)
+    {
+    case 'a':
+      match ("abstract% interface", gfc_match_abstract_interface,
+            ST_INTERFACE);
+      break;
+
+    case 'b':
+      match (NULL, gfc_match_bind_c_stmt, ST_ATTR_DECL);
+      break;
+
+    case 'c':
+      break;
+
+    case 'd':
+      match ("data", gfc_match_data, ST_DATA);
+      match ("dimension", gfc_match_dimension, ST_ATTR_DECL);
+      break;
+
+    case 'e':
+      match ("enum , bind ( c )", gfc_match_enum, ST_ENUM);
+      match ("entry% ", gfc_match_entry, ST_ENTRY);
+      match ("equivalence", gfc_match_equivalence, ST_EQUIVALENCE);
+      match ("external", gfc_match_external, ST_ATTR_DECL);
+      break;
+
+    case 'f':
+      match ("format", gfc_match_format, ST_FORMAT);
+      break;
+
+    case 'g':
+      break;
+
+    case 'i':
+      match ("implicit", gfc_match_implicit, ST_IMPLICIT);
+      match ("implicit% none", gfc_match_implicit_none, ST_IMPLICIT_NONE);
+      match ("interface", gfc_match_interface, ST_INTERFACE);
+      match ("intent", gfc_match_intent, ST_ATTR_DECL);
+      match ("intrinsic", gfc_match_intrinsic, ST_ATTR_DECL);
+      break;
+
+    case 'm':
+      break;
+
+    case 'n':
+      match ("namelist", gfc_match_namelist, ST_NAMELIST);
+      break;
+
+    case 'o':
+      match ("optional", gfc_match_optional, ST_ATTR_DECL);
+      break;
+
+    case 'p':
+      match ("parameter", gfc_match_parameter, ST_PARAMETER);
+      match ("pointer", gfc_match_pointer, ST_ATTR_DECL);
+      if (gfc_match_private (&st) == MATCH_YES)
+       return st;
+      match ("procedure", gfc_match_procedure, ST_PROCEDURE);
+      if (gfc_match_public (&st) == MATCH_YES)
+       return st;
+      match ("protected", gfc_match_protected, ST_ATTR_DECL);
+      break;
+
+    case 'r':
+      break;
+
+    case 's':
+      match ("save", gfc_match_save, ST_ATTR_DECL);
+      break;
+
+    case 't':
+      match ("target", gfc_match_target, ST_ATTR_DECL);
+      match ("type", gfc_match_derived_decl, ST_DERIVED_DECL);
+      break;
+
+    case 'u':
+      break;
+
+    case 'v':
+      match ("value", gfc_match_value, ST_ATTR_DECL);
+      match ("volatile", gfc_match_volatile, ST_ATTR_DECL);
+      break;
+
+    case 'w':
+      break;
+    }
+
+  /* This is not a specification statement.  See if any of the matchers
+     has stored an error message of some sort.  */
+
+end_of_block:
+  gfc_clear_error ();
+  gfc_buffer_error (0);
+  gfc_current_locus = old_locus;
+
+  return ST_GET_FCN_CHARACTERISTICS;
+}
+
+
+/* This is the primary 'decode_statement'.  */
 static gfc_statement
 decode_statement (void)
 {
@@ -100,9 +238,15 @@ decode_statement (void)
   gfc_clear_error ();  /* Clear any pending errors.  */
   gfc_clear_warning ();        /* Clear any pending warnings.  */
 
+  gfc_matching_function = false;
+
   if (gfc_match_eos () == MATCH_YES)
     return ST_NONE;
 
+  if (gfc_current_state () == COMP_FUNCTION
+       && gfc_current_block ()->result->ts.kind == -1)
+    return decode_specification_statement ();
+
   old_locus = gfc_current_locus;
 
   /* Try matching a data declaration or function declaration. The
@@ -113,6 +257,7 @@ decode_statement (void)
       || gfc_current_state () == COMP_INTERFACE
       || gfc_current_state () == COMP_CONTAINS)
     {
+      gfc_matching_function = true;
       m = gfc_match_function_decl ();
       if (m == MATCH_YES)
        return ST_FUNCTION;
@@ -122,6 +267,8 @@ decode_statement (void)
        gfc_undo_symbols ();
       gfc_current_locus = old_locus;
     }
+  gfc_matching_function = false;
+
 
   /* Match statements whose error messages are meant to be overwritten
      by something better.  */
@@ -1870,30 +2017,48 @@ done:
 }
 
 
-/* Recover use associated or imported function characteristics.  */
+/* Associate function characteristics by going back to the function
+   declaration and rematching the prefix.  */
 
-static try
+static match
 match_deferred_characteristics (gfc_typespec * ts)
 {
   locus loc;
-  match m;
+  match m = MATCH_ERROR;
+  char name[GFC_MAX_SYMBOL_LEN + 1];
 
   loc = gfc_current_locus;
 
-  if (gfc_current_block ()->ts.type != BT_UNKNOWN)
+  gfc_current_locus = gfc_current_block ()->declared_at;
+
+  gfc_clear_error ();
+  gfc_buffer_error (1);
+  m = gfc_match_prefix (ts);
+  gfc_buffer_error (0);
+
+  if (ts->type == BT_DERIVED)
     {
-      /* Kind expression for an intrinsic type.  */
-      gfc_current_locus = gfc_function_kind_locus;
-      m = gfc_match_kind_spec (ts, true);
+      ts->kind = 0;
+
+      if (!ts->derived || !ts->derived->components)
+       m = MATCH_ERROR;
     }
-  else
+
+  /* Only permit one go at the characteristic association.  */
+  if (ts->kind == -1)
+    ts->kind = 0;
+
+  /* Set the function locus correctly.  If we have not found the
+     function name, there is an error.  */
+  gfc_match ("function% %n", name);
+  if (m == MATCH_YES && strcmp (name, gfc_current_block ()->name) == 0)
     {
-      /* A derived type.  */
-      gfc_current_locus = gfc_function_type_locus;
-      m = gfc_match_type_spec (ts, 0);
+      gfc_current_block ()->declared_at = gfc_current_locus;
+      gfc_commit_symbols ();
     }
+  else
+    gfc_error_check ();
 
-  gfc_current_ns->proc_name->result->ts = *ts;
   gfc_current_locus =loc;
   return m;
 }
@@ -1906,6 +2071,8 @@ static gfc_statement
 parse_spec (gfc_statement st)
 {
   st_state ss;
+  bool bad_characteristic = false;
+  gfc_typespec *ts;
 
   verify_st_order (&ss, ST_NONE);
   if (st == ST_NONE)
@@ -1984,15 +2151,6 @@ loop:
        }
 
       accept_statement (st);
-
-      /* Look out for function kind/type information that used
-        use associated or imported parameter.  This is signalled
-        by kind = -1.  */
-      if (gfc_current_state () == COMP_FUNCTION
-           && (st == ST_USE || st == ST_IMPORT || st == ST_DERIVED_DECL)
-           && gfc_current_block ()->ts.kind == -1)
-       match_deferred_characteristics (&gfc_current_block ()->ts);
-
       st = next_statement ();
       goto loop;
 
@@ -2002,21 +2160,37 @@ loop:
       st = next_statement ();
       goto loop;
 
+    case ST_GET_FCN_CHARACTERISTICS:
+      /* This statement triggers the association of a function's result
+        characteristics.  */
+      ts = &gfc_current_block ()->result->ts;
+      if (match_deferred_characteristics (ts) != MATCH_YES)
+       bad_characteristic = true;
+
+      st = next_statement ();
+      goto loop;
+
     default:
       break;
     }
 
-  /* If we still have kind = -1 at the end of the specification block,
-     then there is an error. */
-  if (gfc_current_state () == COMP_FUNCTION
-       && gfc_current_block ()->ts.kind == -1)
+  /* If match_deferred_characteristics failed, then there is an error. */
+  if (bad_characteristic)
     {
-      if (gfc_current_block ()->ts.type != BT_UNKNOWN)
+      ts = &gfc_current_block ()->result->ts;
+      if (ts->type != BT_DERIVED)
        gfc_error ("Bad kind expression for function '%s' at %L",
-                  gfc_current_block ()->name, &gfc_function_kind_locus);
+                  gfc_current_block ()->name,
+                  &gfc_current_block ()->declared_at);
       else
        gfc_error ("The type for function '%s' at %L is not accessible",
-                  gfc_current_block ()->name, &gfc_function_type_locus);
+                  gfc_current_block ()->name,
+                  &gfc_current_block ()->declared_at);
+
+      gfc_current_block ()->ts.kind = 0;
+      /* Keep the derived type; if it's bad, it will be discovered later.  */
+      if (!(ts->type = BT_DERIVED && ts->derived))
+        ts->type = BT_UNKNOWN;
     }
 
   return st;
index 307d59a..be885bb 100644 (file)
@@ -66,7 +66,6 @@ const char *gfc_ascii_statement (gfc_statement);
 match gfc_match_enum (void);
 match gfc_match_enumerator_def (void);
 void gfc_free_enum_history (void);
-extern locus gfc_function_kind_locus;
-extern locus gfc_function_type_locus;
-
+extern bool gfc_matching_function;
+match gfc_match_prefix (gfc_typespec *);
 #endif  /* GFC_PARSE_H  */
index ed896b4..c86bb45 100644 (file)
@@ -1,3 +1,23 @@
+2008-01-17  Paul Thomas  <pault@gcc.gnu.org>
+
+       PR fortran/34429
+       * gfortran.dg/function_charlen_1.f90: New test.
+
+       PR fortran/34431
+       * gfortran.dg/function_types_1.f90: New test.
+       * gfortran.dg/function_types_2.f90: New test.
+
+       PR fortran/34471
+       * gfortran.dg/function_kinds_4.f90: New test.
+       * gfortran.dg/function_kinds_5.f90: New test.
+
+       * gfortran.dg/defined_operators_1.f90: Errors now at function
+       declarations.
+       * gfortran.dg/private_type_4.f90: The same.
+       * gfortran.dg/interface_15.f90: The same.
+       * gfortran.dg/elemental_args_check_2.f90: The same.
+       * gfortran.dg/auto_internal_assumed.f90: The same.
+
 2008-01-16  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/sizetype.adb: New test.
index c053216..ec0ea7f 100644 (file)
@@ -3,10 +3,10 @@
 ! internal function.
 !
 character (6) :: c
-  c = f1 ()        ! { dg-error "must not be assumed length" }
+  c = f1 ()
   if (c .ne. 'abcdef') call abort
 contains
-  function f1 ()
+  function f1 () ! { dg-error "must not be assumed length" }
     character (*) :: f1
     f1 = 'abcdef'
   end function f1
index 0233bf0..bd25021 100644 (file)
@@ -7,10 +7,10 @@
 !
 module mymod
   interface operator (.foo.)
-     module procedure foo_0 ! { dg-error "must have at least one argument" }
-     module procedure foo_1 ! { dg-error "must be INTENT" }
-     module procedure foo_2 ! { dg-error "cannot be optional" }
-     module procedure foo_3 ! { dg-error "must have, at most, two arguments" }
+     module procedure foo_0
+     module procedure foo_1
+     module procedure foo_2
+     module procedure foo_3
      module procedure foo_1_OK  ! { dg-error "Ambiguous interfaces" }
      module procedure foo_2_OK
      function foo_chr (chr) ! { dg-error "cannot be assumed character length" }
@@ -22,11 +22,11 @@ module mymod
      end subroutine bad_foo
   end interface
 contains
-  function foo_0 ()
+  function foo_0 () ! { dg-error "must have at least one argument" }
     integer :: foo_1
     foo_0 = 1
   end function foo_0
-  function foo_1 (a)
+  function foo_1 (a) ! { dg-error "must be INTENT" }
     integer :: foo_1
     integer :: a
     foo_1 = 1
@@ -36,7 +36,7 @@ contains
     integer, intent (in) :: a
     foo_1_OK = 1
   end function foo_1_OK
-  function foo_2 (a, b)
+  function foo_2 (a, b) ! { dg-error "cannot be optional" }
     integer :: foo_2
     integer, intent(in) :: a
     integer, intent(in), optional :: b
@@ -48,7 +48,7 @@ contains
     real, intent(in) :: b
     foo_2_OK = 2.0 * a + b
   end function foo_2_OK
-  function foo_3 (a, b, c)
+  function foo_3 (a, b, c) ! { dg-error "must have, at most, two arguments" }
     integer :: foo_3
     integer, intent(in) :: a, b, c
     foo_3 = a + 3 * b - c
index 1a10af3..51e69a4 100644 (file)
@@ -8,10 +8,10 @@
 MODULE M1
 IMPLICIT NONE
 CONTAINS
- PURE ELEMENTAL SUBROUTINE S1(I,F) ! { dg-error "Dummy procedure 'f' not allowed in elemental procedure" }
+ PURE ELEMENTAL SUBROUTINE S1(I,F)
    INTEGER, INTENT(IN) :: I
    INTERFACE
-     PURE INTEGER FUNCTION F(I)
+     PURE INTEGER FUNCTION F(I) ! { dg-error "Dummy procedure 'f' not allowed in elemental procedure" }
       INTEGER, INTENT(IN) :: I
      END FUNCTION F
    END INTERFACE
diff --git a/gcc/testsuite/gfortran.dg/function_charlen_1.f90 b/gcc/testsuite/gfortran.dg/function_charlen_1.f90
new file mode 100644 (file)
index 0000000..e0ecc63
--- /dev/null
@@ -0,0 +1,23 @@
+! { dg-do compile }
+! Tests the fix for PR34429 in which function charlens that were
+! USE associated would cause an error.
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+module m
+  integer, parameter :: strlen = 5
+end module m
+
+character(strlen) function test()
+  use m
+  test = 'A'
+end function test
+
+  interface
+    character(strlen) function test()
+      use m
+    end function test
+  end interface
+  print *, test()
+end
+! { dg-final { cleanup-modules "m" } }
diff --git a/gcc/testsuite/gfortran.dg/function_kinds_4.f90 b/gcc/testsuite/gfortran.dg/function_kinds_4.f90
new file mode 100644 (file)
index 0000000..bcde1e4
--- /dev/null
@@ -0,0 +1,56 @@
+! { dg-do run }
+! Tests the fix for PR34471 in which function KINDs that were
+! USE associated would cause an error.
+!
+! This only needs to be run once.
+! { dg-options "-O2" }
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+module m1
+  integer, parameter :: i1 = 1, i2 = 2
+end module m1
+
+module m2
+  integer, parameter :: i1 = 8
+end module m2
+
+integer(i1) function three()
+  use m1, only: i2
+  use m2                ! This provides the function kind
+  three = i1
+  if(three /= kind(three)) call abort()
+end function three
+
+! At one stage during the development of the patch, this started failing
+! but was not tested in gfortran.dg.  */
+real (kind(0d0)) function foo ()
+  foo = real (kind (foo))
+end function
+
+program main
+implicit none
+ interface
+    integer(8) function three()
+    end function three
+ end interface
+ integer, parameter :: i1 = 4
+ integer :: i
+ real (kind(0d0)) foo
+ i = one()
+ i = two()
+ if(three() /= 8) call abort()
+ if (int(foo()) /= 8) call abort ()
+contains
+ integer(i1) function one()  ! Host associated kind
+   if (kind(one) /= 4) call abort()
+   one = 1
+ end function one
+ integer(i1) function two()  ! Use associated kind
+   use m1, only: i2
+   use m2
+   if (kind(two) /= 8) call abort()
+   two = 1
+ end function two
+end program main
+! { dg-final { cleanup-modules "m1 m2" } }
diff --git a/gcc/testsuite/gfortran.dg/function_kinds_5.f90 b/gcc/testsuite/gfortran.dg/function_kinds_5.f90
new file mode 100644 (file)
index 0000000..fde5bef
--- /dev/null
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! Tests the fix for PR34471 in which function KINDs that were
+! USE associated would cause an error.  This checks a regression
+! caused by an intermediate version of the patch.
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+real (bad_kind(0d0)) function foo () ! { dg-error "must be an intrinsic or" }
+  foo = real (kind (foo))
+end function
diff --git a/gcc/testsuite/gfortran.dg/function_types_1.f90 b/gcc/testsuite/gfortran.dg/function_types_1.f90
new file mode 100644 (file)
index 0000000..fb18d2f
--- /dev/null
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! Tests the fix for PR34431 in which function TYPEs that were
+! USE associated would cause an error.
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+module bar
+contains
+  type(non_exist) function func2() ! { dg-error "not accessible" }
+  end function func2
+end module bar
+! { dg-final { cleanup-modules "bar" } }
diff --git a/gcc/testsuite/gfortran.dg/function_types_2.f90 b/gcc/testsuite/gfortran.dg/function_types_2.f90
new file mode 100644 (file)
index 0000000..b3b5a0a
--- /dev/null
@@ -0,0 +1,104 @@
+! { dg-do compile }
+! Tests the fix for PR34431 in which function TYPEs that were
+! USE associated would cause an error.
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+module m1
+  integer :: hh
+  type t
+    real :: r
+  end type t
+end module m1
+
+module m2
+  type t
+    integer :: k
+  end type t
+end module m2
+
+module m3
+contains
+  type(t) function func()
+    use m2
+    func%k = 77
+  end function func
+end module m3
+
+type(t) function a()
+  use m1, only: hh
+  type t2
+    integer :: j
+  end type t2
+  type t
+    logical :: b
+  end type t
+
+  a%b = .true.
+end function a
+
+type(t) function b()
+  use m1, only: hh
+  use m2
+  use m3
+  b = func ()
+  b%k = 5
+end function b
+
+type(t) function c()
+  use m1, only: hh
+  type t2
+    integer :: j
+  end type t2
+  type t
+    logical :: b
+  end type t
+
+  c%b = .true.
+end function c
+
+program main
+  type t
+    integer :: m
+  end type t
+contains
+  type(t) function a1()
+    use m1, only: hh
+    type t2
+      integer :: j
+    end type t2
+    type t
+      logical :: b
+    end type t
+
+    a1%b = .true.
+  end function a1
+
+  type(t) function b1()
+    use m1, only: hh
+    use m2, only: t
+! NAG f95 believes that the host-associated type(t)
+! should be used:
+!   b1%m = 5
+! However, I (Tobias Burnus) believe that the use-associated one should
+! be used:
+    b1%k = 5
+  end function b1
+
+  type(t) function c1()
+    use m1, only: hh
+    type t2
+      integer :: j
+    end type t2
+    type t
+      logical :: b
+    end type t
+
+    c1%b = .true.
+  end function c1
+
+  type(t) function d1()
+    d1%m = 55
+  end function d1
+end program main
+! { dg-final { cleanup-modules "m1 m2 m3" } }
index 15f4298..2186061 100644 (file)
@@ -8,12 +8,12 @@ MODULE M1
     INTEGER :: I
   END TYPE T1
   INTERFACE I
-    MODULE PROCEDURE F1        ! { dg-error "PUBLIC interface" }
+    MODULE PROCEDURE F1
   END INTERFACE
   PRIVATE ! :: T1,F1
   PUBLIC  :: I
 CONTAINS
-  INTEGER FUNCTION F1(D)
+  INTEGER FUNCTION F1(D)  ! { dg-error "PUBLIC interface" }
     TYPE(T1) :: D
     F1 = D%I
   END FUNCTION
index aca8795..9ff39b2 100644 (file)
@@ -7,11 +7,11 @@ module m1
     end type t1
 
     private :: t1
-    public :: f1     ! { dg-error "cannot be of PRIVATE type" }
+    public :: f1
 
 contains
 
-    type(t1) function f1()
+    type(t1) function f1() ! { dg-error "cannot be of PRIVATE type" }
     end function
 
 end module