OSDN Git Service

2007-02-21 Bernhard Fischer <aldot@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / parse.c
index b120bbb..6e36ea2 100644 (file)
@@ -1,6 +1,6 @@
 /* Main parser.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, 
-   Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
 This file is part of GCC.
@@ -20,7 +20,6 @@ along with GCC; see the file COPYING.  If not, write to the Free
 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.  */
 
-
 #include "config.h"
 #include "system.h"
 #include <setjmp.h>
@@ -28,9 +27,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "match.h"
 #include "parse.h"
 
-/* Current statement label.  Zero means no statement label.  Because
-   new_st can get wiped during statement matching, we have to keep it
-   separate.  */
+/* Current statement label.  Zero means no statement label.  Because new_st
+   can get wiped during statement matching, we have to keep it separate.  */
 
 gfc_st_label *gfc_statement_label;
 
@@ -51,7 +49,7 @@ static void reject_statement (void);
    gfc_match_eos().  */
 
 static match
-match_word (const char *str, match (*subr) (void), locus * old_locus)
+match_word (const char *str, match (*subr) (void), locus *old_locus)
 {
   match m;
 
@@ -79,11 +77,11 @@ match_word (const char *str, match (*subr) (void), locus * old_locus)
    ambiguity.  */
 
 #define match(keyword, subr, st)                               \
-    do {                                                        \
+    do {                                                       \
       if (match_word(keyword, subr, &old_locus) == MATCH_YES)  \
-        return st;                                             \
+       return st;                                              \
       else                                                     \
-        undo_new_statement ();                                  \
+       undo_new_statement ();                            \
     } while (0);
 
 static gfc_statement
@@ -229,6 +227,7 @@ decode_statement (void)
       match ("inquire", gfc_match_inquire, ST_INQUIRE);
       match ("implicit", gfc_match_implicit, ST_IMPLICIT);
       match ("implicit% none", gfc_match_implicit_none, ST_IMPLICIT_NONE);
+      match ("import", gfc_match_import, ST_IMPORT);
       match ("interface", gfc_match_interface, ST_INTERFACE);
       match ("intent", gfc_match_intent, ST_ATTR_DECL);
       match ("intrinsic", gfc_match_intrinsic, ST_ATTR_DECL);
@@ -259,6 +258,7 @@ decode_statement (void)
       match ("program", gfc_match_program, ST_PROGRAM);
       if (gfc_match_public (&st) == MATCH_YES)
        return st;
+      match ("protected", gfc_match_protected, ST_ATTR_DECL);
       break;
 
     case 'r':
@@ -279,7 +279,12 @@ decode_statement (void)
       break;
 
     case 'u':
-      match ("use% ", gfc_match_use, ST_USE);
+      match ("use", gfc_match_use, ST_USE);
+      break;
+
+    case 'v':
+      match ("value", gfc_match_value, ST_ATTR_DECL);
+      match ("volatile", gfc_match_volatile, ST_ATTR_DECL);
       break;
 
     case 'w':
@@ -315,7 +320,8 @@ decode_omp_directive (void)
 
   if (gfc_pure (NULL))
     {
-      gfc_error_now ("OpenMP directives at %C may not appear in PURE or ELEMENTAL procedures");
+      gfc_error_now ("OpenMP directives at %C may not appear in PURE "
+                    "or ELEMENTAL procedures");
       gfc_error_recovery ();
       return ST_NONE;
     }
@@ -410,8 +416,9 @@ static gfc_statement
 next_free (void)
 {
   match m;
-  int c, d, cnt;
+  int c, d, cnt, at_bol;
 
+  at_bol = gfc_at_bol ();
   gfc_gobble_whitespace ();
 
   c = gfc_peek_char ();
@@ -426,11 +433,11 @@ next_free (void)
        {
          gfc_match_small_literal_int (&c, &cnt);
 
-          if (cnt > 5)
+         if (cnt > 5)
            gfc_error_now ("Too many digits in statement label at %C");
-         
+
          if (c == 0)
-           gfc_error_now ("Statement label at %C is zero");
+           gfc_error_now ("Zero is not a valid statement label at %C");
 
          do
            c = gfc_next_char ();
@@ -439,6 +446,7 @@ next_free (void)
          if (!gfc_is_whitespace (c))
            gfc_error_now ("Non-numeric character in statement label at %C");
 
+         return ST_NONE;
        }
       else
        {
@@ -446,10 +454,18 @@ next_free (void)
 
          gfc_gobble_whitespace ();
 
+         if (at_bol && gfc_peek_char () == ';')
+           {
+             gfc_error_now ("Semicolon at %C needs to be preceded by "
+                            "statement");
+             gfc_next_char (); /* Eat up the semicolon.  */
+             return ST_NONE;
+           }
+
          if (gfc_match_eos () == MATCH_YES)
            {
-             gfc_warning_now
-               ("Ignoring statement label in empty statement at %C");
+             gfc_warning_now ("Ignoring statement label in empty statement "
+                              "at %C");
              gfc_free_st_label (gfc_statement_label);
              gfc_statement_label = NULL;
              return ST_NONE;
@@ -469,10 +485,18 @@ next_free (void)
            gcc_assert (c == "!$omp"[i]);
 
          gcc_assert (c == ' ');
+         gfc_gobble_whitespace ();
          return decode_omp_directive ();
        }
     }
 
+  if (at_bol && c == ';')
+    {
+      gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+      gfc_next_char (); /* Eat up the semicolon.  */
+      return ST_NONE;
+    }
+
   return decode_statement ();
 }
 
@@ -570,7 +594,7 @@ next_fixed (void)
   if (c == '\n')
     goto blank_line;
 
-  if (c != ' ' && c!= '0')
+  if (c != ' ' && c != '0')
     {
       gfc_buffer_error (0);
       gfc_error ("Bad continuation line at %C");
@@ -592,6 +616,12 @@ next_fixed (void)
     goto blank_line;
   gfc_current_locus = loc;
 
+  if (c == ';')
+    {
+      gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+      return ST_NONE;
+    }
+
   if (gfc_match_eos () == MATCH_YES)
     goto blank_line;
 
@@ -600,7 +630,7 @@ next_fixed (void)
 
 blank_line:
   if (digit_flag)
-    gfc_warning ("Statement label in blank line will be ignored at %C");
+    gfc_warning ("Ignoring statement label in empty statement at %C");
   gfc_advance_line ();
   return ST_NONE;
 }
@@ -624,6 +654,7 @@ next_statement (void)
       if (gfc_at_eol ())
        {
          if (gfc_option.warn_line_truncation
+             && gfc_current_locus.lb
              && gfc_current_locus.lb->truncated)
            gfc_warning_now ("Line truncated at %C");
 
@@ -638,8 +669,7 @@ next_statement (void)
          break;
        }
 
-      st =
-       (gfc_current_form == FORM_FIXED) ? next_fixed () : next_free ();
+      st = (gfc_current_form == FORM_FIXED) ? next_fixed () : next_free ();
 
       if (st != ST_NONE)
        break;
@@ -692,21 +722,19 @@ next_statement (void)
    are detected in gfc_match_end().  */
 
 #define case_end case ST_END_BLOCK_DATA: case ST_END_FUNCTION: \
-                 case ST_END_PROGRAM: case ST_END_SUBROUTINE
+                case ST_END_PROGRAM: case ST_END_SUBROUTINE
 
 
 /* Push a new state onto the stack.  */
 
 static void
-push_state (gfc_state_data * p, gfc_compile_state new_state, gfc_symbol * sym)
+push_state (gfc_state_data *p, gfc_compile_state new_state, gfc_symbol *sym)
 {
-
   p->state = new_state;
   p->previous = gfc_state_stack;
   p->sym = sym;
   p->head = p->tail = NULL;
   p->do_variable = NULL;
-
   gfc_state_stack = p;
 }
 
@@ -716,7 +744,6 @@ push_state (gfc_state_data * p, gfc_compile_state new_state, gfc_symbol * sym)
 static void
 pop_state (void)
 {
-
   gfc_state_stack = gfc_state_stack->previous;
 }
 
@@ -739,7 +766,7 @@ gfc_find_state (gfc_compile_state state)
 /* Starts a new level in the statement list.  */
 
 static gfc_code *
-new_level (gfc_code * q)
+new_level (gfc_code *q)
 {
   gfc_code *p;
 
@@ -826,8 +853,8 @@ check_statement_label (gfc_statement st)
       break;
 
       /* Statement labels are not restricted from appearing on a
-         particular line.  However, there are plenty of situations
-         where the resulting label can't be referenced.  */
+        particular line.  However, there are plenty of situations
+        where the resulting label can't be referenced.  */
 
     default:
       type = ST_LABEL_BAD_TARGET;
@@ -1010,6 +1037,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_IMPLIED_ENDDO:
       p = _("implied END DO");
       break;
+    case ST_IMPORT:
+      p = "IMPORT";
+      break;
     case ST_INQUIRE:
       p = "INQUIRE";
       break;
@@ -1196,7 +1226,7 @@ gfc_ascii_statement (gfc_statement st)
 /* Create a symbol for the main program and assign it to ns->proc_name.  */
  
 static void 
-main_program_symbol (gfc_namespace * ns)
+main_program_symbol (gfc_namespace *ns)
 {
   gfc_symbol *main_program;
   symbol_attribute attr;
@@ -1220,7 +1250,6 @@ main_program_symbol (gfc_namespace * ns)
 static void
 accept_statement (gfc_statement st)
 {
-
   switch (st)
     {
     case ST_USE:
@@ -1241,8 +1270,8 @@ accept_statement (gfc_statement st)
       break;
 
       /* If the statement is the end of a block, lay down a special code
-         that allows a branch to the end of the block from within the
-         construct.  */
+        that allows a branch to the end of the block from within the
+        construct.  */
 
     case ST_ENDIF:
     case ST_END_SELECT:
@@ -1255,8 +1284,8 @@ accept_statement (gfc_statement st)
       break;
 
       /* The end-of-program unit statements do not get the special
-         marker and require a statement of some sort if they are a
-         branch target.  */
+        marker and require a statement of some sort if they are a
+        branch target.  */
 
     case ST_END_PROGRAM:
     case ST_END_FUNCTION:
@@ -1291,7 +1320,7 @@ accept_statement (gfc_statement st)
 static void
 reject_statement (void)
 {
-
+  gfc_new_block = NULL;
   gfc_undo_symbols ();
   gfc_clear_warning ();
   undo_new_statement ();
@@ -1304,7 +1333,6 @@ reject_statement (void)
 static void
 unexpected_statement (gfc_statement st)
 {
-
   gfc_error ("Unexpected %s statement at %C", gfc_ascii_statement (st));
 
   reject_statement ();
@@ -1320,36 +1348,38 @@ unexpected_statement (gfc_statement st)
    valid before calling here, ie ENTRY statements are not allowed in
    INTERFACE blocks.  The following diagram is taken from the standard:
 
-            +---------------------------------------+
-            | program  subroutine  function  module |
-            +---------------------------------------+
-            |                 use                   |
-            |---------------------------------------+
-            |        |        implicit none         |
-            |        +-----------+------------------+
-            |        | parameter |  implicit        |
-            |        +-----------+------------------+
-            | format |           |  derived type    |
-            | entry  | parameter |  interface       |
-            |        |   data    |  specification   |
-            |        |           |  statement func  |
-            |        +-----------+------------------+
-            |        |   data    |    executable    |
-            +--------+-----------+------------------+
-            |                contains               |
-            +---------------------------------------+
-            |      internal module/subprogram       |
-            +---------------------------------------+
-            |                   end                 |
-            +---------------------------------------+
+           +---------------------------------------+
+           | program  subroutine  function  module |
+           +---------------------------------------+
+           |            use               |
+           +---------------------------------------+
+           |            import         |
+           +---------------------------------------+
+           |   |       implicit none    |
+           |   +-----------+------------------+
+           |   | parameter |  implicit |
+           |   +-----------+------------------+
+           | format |     |  derived type    |
+           | entry  | parameter |  interface       |
+           |   |   data    |  specification   |
+           |   |          |  statement func  |
+           |   +-----------+------------------+
+           |   |   data    |    executable    |
+           +--------+-----------+------------------+
+           |           contains               |
+           +---------------------------------------+
+           |      internal module/subprogram       |
+           +---------------------------------------+
+           |              end           |
+           +---------------------------------------+
 
 */
 
 typedef struct
 {
   enum
-  { ORDER_START, ORDER_USE, ORDER_IMPLICIT_NONE, ORDER_IMPLICIT,
-    ORDER_SPEC, ORDER_EXEC
+  { ORDER_START, ORDER_USE, ORDER_IMPORT, ORDER_IMPLICIT_NONE,
+    ORDER_IMPLICIT, ORDER_SPEC, ORDER_EXEC
   }
   state;
   gfc_statement last_statement;
@@ -1358,7 +1388,7 @@ typedef struct
 st_state;
 
 static try
-verify_st_order (st_state * p, gfc_statement st)
+verify_st_order (st_state *p, gfc_statement st)
 {
 
   switch (st)
@@ -1373,14 +1403,20 @@ verify_st_order (st_state * p, gfc_statement st)
       p->state = ORDER_USE;
       break;
 
+    case ST_IMPORT:
+      if (p->state > ORDER_IMPORT)
+       goto order;
+      p->state = ORDER_IMPORT;
+      break;
+
     case ST_IMPLICIT_NONE:
       if (p->state > ORDER_IMPLICIT_NONE)
        goto order;
 
-   /* The '>' sign cannot be a '>=', because a FORMAT or ENTRY
-      statement disqualifies a USE but not an IMPLICIT NONE.
-      Duplicate IMPLICIT NONEs are caught when the implicit types
-      are set.  */
+      /* The '>' sign cannot be a '>=', because a FORMAT or ENTRY
+        statement disqualifies a USE but not an IMPLICIT NONE.
+        Duplicate IMPLICIT NONEs are caught when the implicit types
+        are set.  */
 
       p->state = ORDER_IMPLICIT_NONE;
       break;
@@ -1426,9 +1462,8 @@ verify_st_order (st_state * p, gfc_statement st)
       break;
 
     default:
-      gfc_internal_error
-       ("Unexpected %s statement in verify_st_order() at %C",
-        gfc_ascii_statement (st));
+      gfc_internal_error ("Unexpected %s statement in verify_st_order() at %C",
+                         gfc_ascii_statement (st));
     }
 
   /* All is well, record the statement in case we need it next time.  */
@@ -1474,8 +1509,9 @@ parse_derived (void)
 {
   int compiling_type, seen_private, seen_sequence, seen_component, error_flag;
   gfc_statement st;
-  gfc_component *c;
   gfc_state_data s;
+  gfc_symbol *sym;
+  gfc_component *c;
 
   error_flag = 0;
 
@@ -1517,8 +1553,8 @@ parse_derived (void)
        case ST_PRIVATE:
          if (gfc_find_state (COMP_MODULE) == FAILURE)
            {
-             gfc_error
-               ("PRIVATE statement in TYPE at %C must be inside a MODULE");
+             gfc_error ("PRIVATE statement in TYPE at %C must be inside "
+                        "a MODULE");
              error_flag = 1;
              break;
            }
@@ -1572,25 +1608,22 @@ parse_derived (void)
        }
     }
 
-  /* Sanity checks on the structure.  If the structure has the
-     SEQUENCE attribute, then all component structures must also have
-     SEQUENCE.  */
-  if (error_flag == 0 && gfc_current_block ()->attr.sequence)
-    for (c = gfc_current_block ()->components; c; c = c->next)
-      {
-       if (c->ts.type == BT_DERIVED && c->ts.derived->attr.sequence == 0)
-         {
-           gfc_error
-             ("Component %s of SEQUENCE type declared at %C does not "
-              "have the SEQUENCE attribute", c->ts.derived->name);
-         }
-      }
+  /* Look for allocatable components.  */
+  sym = gfc_current_block ();
+  for (c = sym->components; c; c = c->next)
+    {
+      if (c->allocatable
+         || (c->ts.type == BT_DERIVED && c->ts.derived->attr.alloc_comp))
+       {
+         sym->attr.alloc_comp = 1;
+         break;
+       }
+     }
 
   pop_state ();
 }
 
 
-
 /* Parse an ENUM.  */
  
 static void
@@ -1612,35 +1645,36 @@ parse_enum (void)
     {
       st = next_statement ();
       switch (st)
-        {
-        case ST_NONE:
-          unexpected_eof ();
-          break;
+       {
+       case ST_NONE:
+         unexpected_eof ();
+         break;
 
-        case ST_ENUMERATOR:
+       case ST_ENUMERATOR:
          seen_enumerator = 1;
-          accept_statement (st);
-          break;
+         accept_statement (st);
+         break;
 
-        case ST_END_ENUM:
-          compiling_enum = 0;
+       case ST_END_ENUM:
+         compiling_enum = 0;
          if (!seen_enumerator)
-            {
-              gfc_error ("ENUM declaration at %C has no ENUMERATORS");
+           {
+             gfc_error ("ENUM declaration at %C has no ENUMERATORS");
              error_flag = 1;
-            }
-          accept_statement (st);
-          break;
-
-        default:
-          gfc_free_enum_history ();
-          unexpected_statement (st);
-          break;
-        }
+           }
+         accept_statement (st);
+         break;
+
+       default:
+         gfc_free_enum_history ();
+         unexpected_statement (st);
+         break;
+       }
     }
   pop_state ();
 }
 
+
 /* Parse an interface.  We must be able to deal with the possibility
    of recursive interfaces.  The parse_spec() subroutine is mutually
    recursive with parse_interface().  */
@@ -1655,6 +1689,7 @@ parse_interface (void)
   gfc_interface_info save;
   gfc_state_data s1, s2;
   gfc_statement st;
+  locus proc_locus;
 
   accept_statement (ST_INTERFACE);
 
@@ -1662,7 +1697,8 @@ parse_interface (void)
   save = current_interface;
 
   sym = (current_interface.type == INTERFACE_GENERIC
-        || current_interface.type == INTERFACE_USER_OP) ? gfc_new_block : NULL;
+        || current_interface.type == INTERFACE_USER_OP)
+       ? gfc_new_block : NULL;
 
   push_state (&s1, COMP_INTERFACE, sym);
   current_state = COMP_NONE;
@@ -1726,14 +1762,12 @@ loop:
          if (new_state != current_state)
            {
              if (new_state == COMP_SUBROUTINE)
-               gfc_error
-                 ("SUBROUTINE at %C does not belong in a generic function "
-                  "interface");
+               gfc_error ("SUBROUTINE at %C does not belong in a "
+                          "generic function interface");
 
              if (new_state == COMP_FUNCTION)
-               gfc_error
-                 ("FUNCTION at %C does not belong in a generic subroutine "
-                  "interface");
+               gfc_error ("FUNCTION at %C does not belong in a "
+                          "generic subroutine interface");
            }
        }
     }
@@ -1742,6 +1776,7 @@ loop:
   accept_statement (st);
   prog_unit = gfc_new_block;
   prog_unit->formal_ns = gfc_current_ns;
+  proc_locus = gfc_current_locus;
 
 decl:
   /* Read data declaration statements.  */
@@ -1757,8 +1792,15 @@ decl:
 
   current_interface = save;
   gfc_add_interface (prog_unit);
-
   pop_state ();
+
+  if (current_interface.ns
+       && current_interface.ns->proc_name
+       && strcmp (current_interface.ns->proc_name->name,
+                  prog_unit->name) == 0)
+    gfc_error ("INTERFACE procedure '%s' at %L has the same name as the "
+              "enclosing procedure", prog_unit->name, &proc_locus);
+
   goto loop;
 
 done:
@@ -1793,6 +1835,7 @@ loop:
       /* Fall through */
 
     case ST_USE:
+    case ST_IMPORT:
     case ST_IMPLICIT_NONE:
     case ST_IMPLICIT:
     case ST_PARAMETER:
@@ -1894,7 +1937,7 @@ parse_where_block (void)
 
        case ST_WHERE_BLOCK:
          parse_where_block ();
-          break;
+         break;
 
        case ST_ASSIGNMENT:
        case ST_WHERE:
@@ -1904,9 +1947,8 @@ parse_where_block (void)
        case ST_ELSEWHERE:
          if (seen_empty_else)
            {
-             gfc_error
-               ("ELSEWHERE statement at %C follows previous unmasked "
-                "ELSEWHERE");
+             gfc_error ("ELSEWHERE statement at %C follows previous "
+                        "unmasked ELSEWHERE");
              break;
            }
 
@@ -1931,7 +1973,6 @@ parse_where_block (void)
          reject_statement ();
          break;
        }
-
     }
   while (st != ST_END_WHERE);
 
@@ -2037,9 +2078,8 @@ parse_if_block (void)
        case ST_ELSEIF:
          if (seen_else)
            {
-             gfc_error
-               ("ELSE IF statement at %C cannot follow ELSE statement at %L",
-                &else_locus);
+             gfc_error ("ELSE IF statement at %C cannot follow ELSE "
+                        "statement at %L", &else_locus);
 
              reject_statement ();
              break;
@@ -2117,9 +2157,8 @@ parse_select_block (void)
       if (st == ST_CASE)
        break;
 
-      gfc_error
-       ("Expected a CASE or END SELECT statement following SELECT CASE "
-        "at %C");
+      gfc_error ("Expected a CASE or END SELECT statement following SELECT "
+                "CASE at %C");
 
       reject_statement ();
     }
@@ -2149,8 +2188,8 @@ parse_select_block (void)
        case ST_END_SELECT:
          break;
 
-        /* Can't have an executable statement because of
-           parse_executable().  */
+       /* Can't have an executable statement because of
+          parse_executable().  */
        default:
          unexpected_statement (st);
          break;
@@ -2210,8 +2249,7 @@ check_do_closure (void)
       if (p == gfc_state_stack)
        return 1;
 
-      gfc_error
-       ("End of nonblock DO statement at %C is within another block");
+      gfc_error ("End of nonblock DO statement at %C is within another block");
       return 2;
     }
 
@@ -2269,8 +2307,8 @@ loop:
     case ST_ENDDO:
       if (s.ext.end_do_label != NULL
          && s.ext.end_do_label != gfc_statement_label)
-       gfc_error_now
-         ("Statement label in ENDDO at %C doesn't match DO label");
+       gfc_error_now ("Statement label in ENDDO at %C doesn't match "
+                      "DO label");
 
       if (gfc_statement_label != NULL)
        {
@@ -2280,6 +2318,14 @@ loop:
       break;
 
     case ST_IMPLIED_ENDDO:
+     /* If the do-stmt of this DO construct has a do-construct-name,
+       the corresponding end-do must be an end-do-stmt (with a matching
+       name, but in that case we must have seen ST_ENDDO first).
+       We only complain about this in pedantic mode.  */
+     if (gfc_current_block () != NULL)
+       gfc_error_now ("named block DO at %L requires matching ENDDO name",
+                      &gfc_current_block()->declared_at);
+
       break;
 
     default:
@@ -2327,12 +2373,12 @@ parse_omp_do (gfc_statement omp_st)
       && gfc_state_stack->previous->ext.end_do_label == gfc_statement_label)
     {
       /* In
-         DO 100 I=1,10
-           !$OMP DO
-             DO J=1,10
-             ...
-             100 CONTINUE
-         there should be no !$OMP END DO.  */
+        DO 100 I=1,10
+          !$OMP DO
+            DO J=1,10
+            ...
+            100 CONTINUE
+        there should be no !$OMP END DO.  */
       pop_state ();
       return ST_IMPLIED_ENDDO;
     }
@@ -2533,8 +2579,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
       if (((cp->ext.omp_name == NULL) ^ (new_st.ext.omp_name == NULL))
          || (new_st.ext.omp_name != NULL
              && strcmp (cp->ext.omp_name, new_st.ext.omp_name) != 0))
-       gfc_error ("Name after !$omp critical and !$omp end critical does"
-                  " not match at %C");
+       gfc_error ("Name after !$omp critical and !$omp end critical does "
+                  "not match at %C");
       gfc_free ((char *) new_st.ext.omp_name);
       break;
     case EXEC_OMP_END_SINGLE:
@@ -2589,9 +2635,8 @@ parse_executable (gfc_statement st)
          case ST_FORALL:
          case ST_WHERE:
          case ST_SELECT_CASE:
-           gfc_error
-             ("%s statement at %C cannot terminate a non-block DO loop",
-              gfc_ascii_statement (st));
+           gfc_error ("%s statement at %C cannot terminate a non-block "
+                      "DO loop", gfc_ascii_statement (st));
            break;
 
          default:
@@ -2678,7 +2723,7 @@ static void parse_progunit (gfc_statement);
    the child namespace as the parser didn't know about this procedure.  */
 
 static void
-gfc_fixup_sibling_symbols (gfc_symbol * sym, gfc_namespace * siblings)
+gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
 {
   gfc_namespace *ns;
   gfc_symtree *st;
@@ -2688,24 +2733,25 @@ gfc_fixup_sibling_symbols (gfc_symbol * sym, gfc_namespace * siblings)
   for (ns = siblings; ns; ns = ns->sibling)
     {
       gfc_find_sym_tree (sym->name, ns, 0, &st);
-      if (!st)
-        continue;
+
+      if (!st || (st->n.sym->attr.dummy && ns == st->n.sym->ns))
+       continue;
 
       old_sym = st->n.sym;
       if ((old_sym->attr.flavor == FL_PROCEDURE
           || old_sym->ts.type == BT_UNKNOWN)
          && old_sym->ns == ns
-          && ! old_sym->attr.contained)
-        {
-          /* Replace it with the symbol from the parent namespace.  */
-          st->n.sym = sym;
-          sym->refs++;
-
-          /* Free the old (local) symbol.  */
-          old_sym->refs--;
-          if (old_sym->refs == 0)
-            gfc_free_symbol (old_sym);
-        }
+         && !old_sym->attr.contained)
+       {
+         /* Replace it with the symbol from the parent namespace.  */
+         st->n.sym = sym;
+         sym->refs++;
+
+         /* Free the old (local) symbol.  */
+         old_sym->refs--;
+         if (old_sym->refs == 0)
+           gfc_free_symbol (old_sym);
+       }
 
       /* Do the same for any contained procedures.  */
       gfc_fixup_sibling_symbols (sym, ns->contained);
@@ -2720,6 +2766,7 @@ parse_contained (int module)
   gfc_statement st;
   gfc_symbol *sym;
   gfc_entry_list *el;
+  int contains_statements = 0;
 
   push_state (&s1, COMP_CONTAINS, NULL);
   parent_ns = gfc_current_ns;
@@ -2740,6 +2787,7 @@ parse_contained (int module)
 
        case ST_FUNCTION:
        case ST_SUBROUTINE:
+         contains_statements = 1;
          accept_statement (st);
 
          push_state (&s2,
@@ -2752,9 +2800,8 @@ parse_contained (int module)
          if (!module)
            {
              if (gfc_get_symbol (gfc_new_block->name, parent_ns, &sym))
-               gfc_error
-                 ("Contained procedure '%s' at %C is already ambiguous",
-                  gfc_new_block->name);
+               gfc_error ("Contained procedure '%s' at %C is already "
+                          "ambiguous", gfc_new_block->name);
              else
                {
                  if (gfc_add_procedure (&sym->attr, PROC_INTERNAL, sym->name,
@@ -2772,18 +2819,18 @@ parse_contained (int module)
 
              gfc_commit_symbols ();
            }
-          else
-            sym = gfc_new_block;
+         else
+           sym = gfc_new_block;
 
-          /* Mark this as a contained function, so it isn't replaced
-             by other module functions.  */
-          sym->attr.contained = 1;
+         /* Mark this as a contained function, so it isn't replaced
+            by other module functions.  */
+         sym->attr.contained = 1;
          sym->attr.referenced = 1;
 
          parse_progunit (ST_NONE);
 
-          /* Fix up any sibling functions that refer to this one.  */
-          gfc_fixup_sibling_symbols (sym, gfc_current_ns);
+         /* Fix up any sibling functions that refer to this one.  */
+         gfc_fixup_sibling_symbols (sym, gfc_current_ns);
          /* Or refer to any of its alternate entry points.  */
          for (el = gfc_current_ns->entries; el; el = el->next)
            gfc_fixup_sibling_symbols (el->sym, gfc_current_ns);
@@ -2794,8 +2841,7 @@ parse_contained (int module)
          pop_state ();
          break;
 
-        /* These statements are associated with the end of the host
-           unit.  */
+       /* These statements are associated with the end of the host unit.  */
        case ST_END_FUNCTION:
        case ST_END_MODULE:
        case ST_END_PROGRAM:
@@ -2823,6 +2869,10 @@ parse_contained (int module)
   gfc_free_namespace (ns);
 
   pop_state ();
+  if (!contains_statements)
+    /* This is valid in Fortran 2008.  */
+    gfc_notify_std (GFC_STD_GNU, "Extension: CONTAINS statement without "
+                   "FUNCTION or SUBROUTINE statement at %C");
 }
 
 
@@ -2960,22 +3010,23 @@ parse_block_data (void)
     {
       if (blank_block)
        gfc_error ("Blank BLOCK DATA at %C conflicts with "
-                  "prior BLOCK DATA at %L", &blank_locus);
+                 "prior BLOCK DATA at %L", &blank_locus);
       else
        {
-         blank_block = 1;
-         blank_locus = gfc_current_locus;
+        blank_block = 1;
+        blank_locus = gfc_current_locus;
        }
     }
   else
     {
       s = gfc_get_gsymbol (gfc_new_block->name);
-      if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_BLOCK_DATA))
+      if (s->defined
+         || (s->type != GSYM_UNKNOWN && s->type != GSYM_BLOCK_DATA))
        global_used(s, NULL);
       else
        {
-         s->type = GSYM_BLOCK_DATA;
-         s->where = gfc_current_locus;
+        s->type = GSYM_BLOCK_DATA;
+        s->where = gfc_current_locus;
         s->defined = 1;
        }
     }
@@ -3047,7 +3098,8 @@ add_global_procedure (int sub)
   s = gfc_get_gsymbol(gfc_new_block->name);
 
   if (s->defined
-       || (s->type != GSYM_UNKNOWN && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
+      || (s->type != GSYM_UNKNOWN
+         && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
     global_used(s, NULL);
   else
     {
@@ -3169,7 +3221,7 @@ loop:
       prog_locus = gfc_current_locus;
 
       push_state (&s, COMP_PROGRAM, gfc_new_block);
-      main_program_symbol(gfc_current_ns);
+      main_program_symbol (gfc_current_ns);
       parse_progunit (st);
       break;
     }
@@ -3186,12 +3238,12 @@ loop:
   if (s.state == COMP_MODULE)
     {
       gfc_dump_module (s.sym->name, errors_before == errors);
-      if (errors == 0 && ! gfc_option.flag_no_backend)
+      if (errors == 0)
        gfc_generate_module_code (gfc_current_ns);
     }
   else
     {
-      if (errors == 0 && ! gfc_option.flag_no_backend)
+      if (errors == 0)
        gfc_generate_code (gfc_current_ns);
     }