OSDN Git Service

2011-01-13 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / parse.c
index c5d3548..b51e12b 100644 (file)
@@ -1,6 +1,6 @@
 /* Main parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-   2009
+   2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
@@ -111,7 +111,7 @@ decode_specification_statement (void)
   match ("import", gfc_match_import, ST_IMPORT);
   match ("use", gfc_match_use, ST_USE);
 
-  if (gfc_current_block ()->ts.type != BT_DERIVED)
+  if (gfc_current_block ()->result->ts.type != BT_DERIVED)
     goto end_of_block;
 
   match (NULL, gfc_match_st_function, ST_STATEMENT_FUNCTION);
@@ -129,6 +129,8 @@ decode_specification_statement (void)
     case 'a':
       match ("abstract% interface", gfc_match_abstract_interface,
             ST_INTERFACE);
+      match ("allocatable", gfc_match_asynchronous, ST_ATTR_DECL);
+      match ("asynchronous", gfc_match_asynchronous, ST_ATTR_DECL);
       break;
 
     case 'b':
@@ -136,6 +138,8 @@ decode_specification_statement (void)
       break;
 
     case 'c':
+      match ("codimension", gfc_match_codimension, ST_ATTR_DECL);
+      match ("contiguous", gfc_match_contiguous, ST_ATTR_DECL);
       break;
 
     case 'd':
@@ -232,9 +236,7 @@ decode_statement (void)
   match m;
   char c;
 
-#ifdef GFC_DEBUG
-  gfc_symbol_state ();
-#endif
+  gfc_enforce_clean_symbol_state ();
 
   gfc_clear_error ();  /* Clear any pending errors.  */
   gfc_clear_warning ();        /* Clear any pending warnings.  */
@@ -289,9 +291,9 @@ decode_statement (void)
   gfc_undo_symbols ();
   gfc_current_locus = old_locus;
 
-  /* Check for the IF, DO, SELECT, WHERE, FORALL and BLOCK statements, which
-     might begin with a block label.  The match functions for these
-     statements are unusual in that their keyword is not seen before
+  /* Check for the IF, DO, SELECT, WHERE, FORALL, CRITICAL, BLOCK and ASSOCIATE
+     statements, which might begin with a block label.  The match functions for
+     these statements are unusual in that their keyword is not seen before
      the matcher is called.  */
 
   if (gfc_match_if (&st) == MATCH_YES)
@@ -309,8 +311,10 @@ decode_statement (void)
   gfc_undo_symbols ();
   gfc_current_locus = old_locus;
 
-  match (NULL, gfc_match_block, ST_BLOCK);
   match (NULL, gfc_match_do, ST_DO);
+  match (NULL, gfc_match_block, ST_BLOCK);
+  match (NULL, gfc_match_associate, ST_ASSOCIATE);
+  match (NULL, gfc_match_critical, ST_CRITICAL);
   match (NULL, gfc_match_select, ST_SELECT_CASE);
   match (NULL, gfc_match_select_type, ST_SELECT_TYPE);
 
@@ -328,6 +332,7 @@ decode_statement (void)
       match ("allocate", gfc_match_allocate, ST_ALLOCATE);
       match ("allocatable", gfc_match_allocatable, ST_ATTR_DECL);
       match ("assign", gfc_match_assign, ST_LABEL_ASSIGNMENT);
+      match ("asynchronous", gfc_match_asynchronous, ST_ATTR_DECL);
       break;
 
     case 'b':
@@ -340,11 +345,13 @@ decode_statement (void)
       match ("call", gfc_match_call, ST_CALL);
       match ("close", gfc_match_close, ST_CLOSE);
       match ("continue", gfc_match_continue, ST_CONTINUE);
+      match ("contiguous", gfc_match_contiguous, ST_ATTR_DECL);
       match ("cycle", gfc_match_cycle, ST_CYCLE);
       match ("case", gfc_match_case, ST_CASE);
       match ("common", gfc_match_common, ST_COMMON);
       match ("contains", gfc_match_eos, ST_CONTAINS);
       match ("class", gfc_match_class_is, ST_CLASS_IS);
+      match ("codimension", gfc_match_codimension, ST_ATTR_DECL);
       break;
 
     case 'd':
@@ -359,6 +366,7 @@ decode_statement (void)
       match ("else", gfc_match_else, ST_ELSE);
       match ("else where", gfc_match_elsewhere, ST_ELSEWHERE);
       match ("else if", gfc_match_elseif, ST_ELSEIF);
+      match ("error stop", gfc_match_error_stop, ST_ERROR_STOP);
       match ("enum , bind ( c )", gfc_match_enum, ST_ENUM);
 
       if (gfc_match_end (&st) == MATCH_YES)
@@ -429,6 +437,9 @@ decode_statement (void)
       match ("sequence", gfc_match_eos, ST_SEQUENCE);
       match ("stop", gfc_match_stop, ST_STOP);
       match ("save", gfc_match_save, ST_ATTR_DECL);
+      match ("sync all", gfc_match_sync_all, ST_SYNC_ALL);
+      match ("sync images", gfc_match_sync_images, ST_SYNC_IMAGES);
+      match ("sync memory", gfc_match_sync_memory, ST_SYNC_MEMORY);
       break;
 
     case 't':
@@ -471,9 +482,7 @@ decode_omp_directive (void)
   locus old_locus;
   char c;
 
-#ifdef GFC_DEBUG
-  gfc_symbol_state ();
-#endif
+  gfc_enforce_clean_symbol_state ();
 
   gfc_clear_error ();  /* Clear any pending errors.  */
   gfc_clear_warning ();        /* Clear any pending warnings.  */
@@ -486,6 +495,9 @@ decode_omp_directive (void)
       return ST_NONE;
     }
 
+  if (gfc_implicit_pure (NULL))
+    gfc_current_ns->proc_name->attr.implicit_pure = 0;
+
   old_locus = gfc_current_locus;
 
   /* General OpenMP directive matching: Instead of testing every possible
@@ -575,9 +587,7 @@ decode_gcc_attribute (void)
 {
   locus old_locus;
 
-#ifdef GFC_DEBUG
-  gfc_symbol_state ();
-#endif
+  gfc_enforce_clean_symbol_state ();
 
   gfc_clear_error ();  /* Clear any pending errors.  */
   gfc_clear_warning ();        /* Clear any pending warnings.  */
@@ -686,7 +696,7 @@ next_free (void)
          return decode_gcc_attribute ();
 
        }
-      else if (c == '$' && gfc_option.flag_openmp)
+      else if (c == '$' && gfc_option.gfc_flag_openmp)
        {
          int i;
 
@@ -704,7 +714,9 @@ next_free (void)
  
   if (at_bol && c == ';')
     {
-      gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+      if (!(gfc_option.allow_std & GFC_STD_F2008))
+       gfc_error_now ("Fortran 2008: Semicolon at %C without preceding "
+                      "statement");
       gfc_next_ascii_char (); /* Eat up the semicolon.  */
       return ST_NONE;
     }
@@ -736,7 +748,7 @@ next_fixed (void)
 
   for (i = 0; i < 5; i++)
     {
-      c = gfc_next_char_literal (0);
+      c = gfc_next_char_literal (NONSTRING);
 
       switch (c)
        {
@@ -762,18 +774,18 @@ next_fixed (void)
             here, except for GCC attributes and OpenMP directives.  */
 
        case '*':
-         c = gfc_next_char_literal (0);
+         c = gfc_next_char_literal (NONSTRING);
          
          if (TOLOWER (c) == 'g')
            {
-             for (i = 0; i < 4; i++, c = gfc_next_char_literal (0))
+             for (i = 0; i < 4; i++, c = gfc_next_char_literal (NONSTRING))
                gcc_assert (TOLOWER (c) == "gcc$"[i]);
 
              return decode_gcc_attribute ();
            }
-         else if (c == '$' && gfc_option.flag_openmp)
+         else if (c == '$' && gfc_option.gfc_flag_openmp)
            {
-             for (i = 0; i < 4; i++, c = gfc_next_char_literal (0))
+             for (i = 0; i < 4; i++, c = gfc_next_char_literal (NONSTRING))
                gcc_assert ((char) gfc_wide_tolower (c) == "$omp"[i]);
 
              if (c != ' ' && c != '0')
@@ -812,7 +824,7 @@ next_fixed (void)
      of a previous statement.  If we see something here besides a
      space or zero, it must be a bad continuation line.  */
 
-  c = gfc_next_char_literal (0);
+  c = gfc_next_char_literal (NONSTRING);
   if (c == '\n')
     goto blank_line;
 
@@ -830,7 +842,7 @@ next_fixed (void)
   do
     {
       loc = gfc_current_locus;
-      c = gfc_next_char_literal (0);
+      c = gfc_next_char_literal (NONSTRING);
     }
   while (gfc_is_whitespace (c));
 
@@ -840,7 +852,11 @@ next_fixed (void)
 
   if (c == ';')
     {
-      gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+      if (digit_flag)
+       gfc_error_now ("Semicolon at %C needs to be preceded by statement");
+      else if (!(gfc_option.allow_std & GFC_STD_F2008))
+       gfc_error_now ("Fortran 2008: Semicolon at %C without preceding "
+                      "statement");
       return ST_NONE;
     }
 
@@ -870,9 +886,12 @@ next_statement (void)
   gfc_statement st;
   locus old_locus;
 
+  gfc_enforce_clean_symbol_state ();
+
   gfc_new_block = NULL;
 
   gfc_current_ns->old_cl_list = gfc_current_ns->cl_list;
+  gfc_current_ns->old_equiv = gfc_current_ns->equiv;
   for (;;)
     {
       gfc_statement_label = NULL;
@@ -933,19 +952,20 @@ next_statement (void)
   case ST_POINTER_ASSIGNMENT: case ST_EXIT: case ST_CYCLE: \
   case ST_ASSIGNMENT: case ST_ARITHMETIC_IF: case ST_WHERE: case ST_FORALL: \
   case ST_LABEL_ASSIGNMENT: case ST_FLUSH: case ST_OMP_FLUSH: \
-  case ST_OMP_BARRIER: case ST_OMP_TASKWAIT
+  case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_ERROR_STOP: \
+  case ST_SYNC_ALL: case ST_SYNC_IMAGES: case ST_SYNC_MEMORY
 
 /* Statements that mark other executable statements.  */
 
 #define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: \
-  case ST_IF_BLOCK: case ST_BLOCK: \
+  case ST_IF_BLOCK: case ST_BLOCK: case ST_ASSOCIATE: \
   case ST_WHERE_BLOCK: case ST_SELECT_CASE: case ST_SELECT_TYPE: \
   case ST_OMP_PARALLEL: \
   case ST_OMP_PARALLEL_SECTIONS: case ST_OMP_SECTIONS: case ST_OMP_ORDERED: \
   case ST_OMP_CRITICAL: case ST_OMP_MASTER: case ST_OMP_SINGLE: \
   case ST_OMP_DO: case ST_OMP_PARALLEL_DO: case ST_OMP_ATOMIC: \
   case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: \
-  case ST_OMP_TASK
+  case ST_OMP_TASK: case ST_CRITICAL
 
 /* Declaration statements */
 
@@ -959,7 +979,7 @@ next_statement (void)
 
 #define case_end case ST_END_BLOCK_DATA: case ST_END_FUNCTION: \
                 case ST_END_PROGRAM: case ST_END_SUBROUTINE: \
-                case ST_END_BLOCK
+                case ST_END_BLOCK: case ST_END_ASSOCIATE
 
 
 /* Push a new state onto the stack.  */
@@ -972,6 +992,13 @@ push_state (gfc_state_data *p, gfc_compile_state new_state, gfc_symbol *sym)
   p->sym = sym;
   p->head = p->tail = NULL;
   p->do_variable = NULL;
+
+  /* If this the state of a construct like BLOCK, DO or IF, the corresponding
+     construct statement was accepted right before pushing the state.  Thus,
+     the construct's gfc_code is available as tail of the parent state.  */
+  gcc_assert (gfc_state_stack);
+  p->construct = gfc_state_stack->tail;
+
   gfc_state_stack = p;
 }
 
@@ -1079,6 +1106,7 @@ check_statement_label (gfc_statement st)
     case ST_ENDDO:
     case ST_ENDIF:
     case ST_END_SELECT:
+    case ST_END_CRITICAL:
     case_executable:
     case_exec_markers:
       type = ST_LABEL_TARGET;
@@ -1143,6 +1171,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_ALLOCATE:
       p = "ALLOCATE";
       break;
+    case ST_ASSOCIATE:
+      p = "ASSOCIATE";
+      break;
     case ST_ATTR_DECL:
       p = _("attribute declaration");
       break;
@@ -1173,6 +1204,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_CONTAINS:
       p = "CONTAINS";
       break;
+    case ST_CRITICAL:
+      p = "CRITICAL";
+      break;
     case ST_CYCLE:
       p = "CYCLE";
       break;
@@ -1200,12 +1234,18 @@ gfc_ascii_statement (gfc_statement st)
     case ST_ELSEWHERE:
       p = "ELSEWHERE";
       break;
+    case ST_END_ASSOCIATE:
+      p = "END ASSOCIATE";
+      break;
     case ST_END_BLOCK:
       p = "END BLOCK";
       break;
     case ST_END_BLOCK_DATA:
       p = "END BLOCK DATA";
       break;
+    case ST_END_CRITICAL:
+      p = "END CRITICAL";
+      break;
     case ST_ENDDO:
       p = "END DO";
       break;
@@ -1248,6 +1288,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_EQUIVALENCE:
       p = "EQUIVALENCE";
       break;
+    case ST_ERROR_STOP:
+      p = "ERROR STOP";
+      break;
     case ST_EXIT:
       p = "EXIT";
       break;
@@ -1336,6 +1379,15 @@ gfc_ascii_statement (gfc_statement st)
     case ST_STOP:
       p = "STOP";
       break;
+    case ST_SYNC_ALL:
+      p = "SYNC ALL";
+      break;
+    case ST_SYNC_IMAGES:
+      p = "SYNC IMAGES";
+      break;
+    case ST_SYNC_MEMORY:
+      p = "SYNC MEMORY";
+      break;
     case ST_SUBROUTINE:
       p = "SUBROUTINE";
       break;
@@ -1552,6 +1604,7 @@ accept_statement (gfc_statement st)
 
     case ST_ENDIF:
     case ST_END_SELECT:
+    case ST_END_CRITICAL:
       if (gfc_statement_label != NULL)
        {
          new_st.op = EXEC_END_BLOCK;
@@ -1605,6 +1658,9 @@ reject_statement (void)
   gfc_free_charlen (gfc_current_ns->cl_list, gfc_current_ns->old_cl_list);
   gfc_current_ns->cl_list = gfc_current_ns->old_cl_list;
 
+  gfc_free_equiv_until (gfc_current_ns->equiv, gfc_current_ns->old_equiv);
+  gfc_current_ns->equiv = gfc_current_ns->old_equiv;
+
   gfc_new_block = NULL;
   gfc_undo_symbols ();
   gfc_clear_warning ();
@@ -1838,13 +1894,12 @@ parse_derived_contains (void)
 
        case ST_DATA_DECL:
          gfc_error ("Components in TYPE at %C must precede CONTAINS");
-         error_flag = true;
-         break;
+         goto error;
 
        case ST_PROCEDURE:
          if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003:  Type-bound"
                                             " procedure at %C") == FAILURE)
-           error_flag = true;
+           goto error;
 
          accept_statement (ST_PROCEDURE);
          seen_comps = true;
@@ -1853,7 +1908,7 @@ parse_derived_contains (void)
        case ST_GENERIC:
          if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003:  GENERIC binding"
                                             " at %C") == FAILURE)
-           error_flag = true;
+           goto error;
 
          accept_statement (ST_GENERIC);
          seen_comps = true;
@@ -1863,7 +1918,7 @@ parse_derived_contains (void)
          if (gfc_notify_std (GFC_STD_F2003,
                              "Fortran 2003:  FINAL procedure declaration"
                              " at %C") == FAILURE)
-           error_flag = true;
+           goto error;
 
          accept_statement (ST_FINAL);
          seen_comps = true;
@@ -1876,7 +1931,7 @@ parse_derived_contains (void)
              && (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Derived type "
                                  "definition at %C with empty CONTAINS "
                                  "section") == FAILURE))
-           error_flag = true;
+           goto error;
 
          /* ST_END_TYPE is accepted by parse_derived after return.  */
          break;
@@ -1886,22 +1941,20 @@ parse_derived_contains (void)
            {
              gfc_error ("PRIVATE statement in TYPE at %C must be inside "
                         "a MODULE");
-             error_flag = true;
-             break;
+             goto error;
            }
 
          if (seen_comps)
            {
              gfc_error ("PRIVATE statement at %C must precede procedure"
                         " bindings");
-             error_flag = true;
-             break;
+             goto error;
            }
 
          if (seen_private)
            {
              gfc_error ("Duplicate PRIVATE statement at %C");
-             error_flag = true;
+             goto error;
            }
 
          accept_statement (ST_PRIVATE);
@@ -1911,18 +1964,22 @@ parse_derived_contains (void)
 
        case ST_SEQUENCE:
          gfc_error ("SEQUENCE statement at %C must precede CONTAINS");
-         error_flag = true;
-         break;
+         goto error;
 
        case ST_CONTAINS:
          gfc_error ("Already inside a CONTAINS block at %C");
-         error_flag = true;
-         break;
+         goto error;
 
        default:
          unexpected_statement (st);
          break;
        }
+
+      continue;
+
+error:
+      error_flag = true;
+      reject_statement ();
     }
 
   pop_state ();
@@ -1937,14 +1994,12 @@ parse_derived_contains (void)
 static void
 parse_derived (void)
 {
-  int compiling_type, seen_private, seen_sequence, seen_component, error_flag;
+  int compiling_type, seen_private, seen_sequence, seen_component;
   gfc_statement st;
   gfc_state_data s;
   gfc_symbol *sym;
   gfc_component *c;
 
-  error_flag = 0;
-
   accept_statement (ST_DERIVED_DECL);
   push_state (&s, COMP_DERIVED, gfc_new_block);
 
@@ -1971,18 +2026,15 @@ parse_derived (void)
 
        case ST_FINAL:
          gfc_error ("FINAL declaration at %C must be inside CONTAINS");
-         error_flag = 1;
          break;
 
        case ST_END_TYPE:
 endType:
          compiling_type = 0;
 
-         if (!seen_component
-             && (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Derived type "
-                                "definition at %C without components")
-                 == FAILURE))
-           error_flag = 1;
+         if (!seen_component)
+           gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Derived type "
+                           "definition at %C without components");
 
          accept_statement (ST_END_TYPE);
          break;
@@ -1992,7 +2044,6 @@ endType:
            {
              gfc_error ("PRIVATE statement in TYPE at %C must be inside "
                         "a MODULE");
-             error_flag = 1;
              break;
            }
 
@@ -2000,15 +2051,11 @@ endType:
            {
              gfc_error ("PRIVATE statement at %C must precede "
                         "structure components");
-             error_flag = 1;
              break;
            }
 
          if (seen_private)
-           {
-             gfc_error ("Duplicate PRIVATE statement at %C");
-             error_flag = 1;
-           }
+           gfc_error ("Duplicate PRIVATE statement at %C");
 
          s.sym->component_access = ACCESS_PRIVATE;
 
@@ -2021,7 +2068,6 @@ endType:
            {
              gfc_error ("SEQUENCE statement at %C must precede "
                         "structure components");
-             error_flag = 1;
              break;
            }
 
@@ -2032,7 +2078,6 @@ endType:
          if (seen_sequence)
            {
              gfc_error ("Duplicate SEQUENCE statement at %C");
-             error_flag = 1;
            }
 
          seen_sequence = 1;
@@ -2041,14 +2086,12 @@ endType:
          break;
 
        case ST_CONTAINS:
-         if (gfc_notify_std (GFC_STD_F2003,
-                             "Fortran 2003:  CONTAINS block in derived type"
-                             " definition at %C") == FAILURE)
-           error_flag = 1;
+         gfc_notify_std (GFC_STD_F2003,
+                         "Fortran 2003:  CONTAINS block in derived type"
+                         " definition at %C");
 
          accept_statement (ST_CONTAINS);
-         if (parse_derived_contains ())
-           error_flag = 1;
+         parse_derived_contains ();
          goto endType;
 
        default:
@@ -2065,15 +2108,13 @@ endType:
     {
       /* Look for allocatable components.  */
       if (c->attr.allocatable
-         || (c->ts.type == BT_CLASS
-             && c->ts.u.derived->components->attr.allocatable)
+         || (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
          || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.alloc_comp))
        sym->attr.alloc_comp = 1;
 
       /* Look for pointer components.  */
       if (c->attr.pointer
-         || (c->ts.type == BT_CLASS
-             && c->ts.u.derived->components->attr.pointer)
+         || (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.class_pointer)
          || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.pointer_comp))
        sym->attr.pointer_comp = 1;
 
@@ -2083,6 +2124,11 @@ endType:
              && c->ts.u.derived->attr.proc_pointer_comp))
        sym->attr.proc_pointer_comp = 1;
 
+      /* Looking for coarray components.  */
+      if (c->attr.codimension
+         || (c->attr.coarray_comp && !c->attr.pointer && !c->attr.allocatable))
+       sym->attr.coarray_comp = 1;
+
       /* Look for private components.  */
       if (sym->component_access == ACCESS_PRIVATE
          || c->attr.access == ACCESS_PRIVATE
@@ -2102,14 +2148,11 @@ endType:
 static void
 parse_enum (void)
 {
-  int error_flag;
   gfc_statement st;
   int compiling_enum;
   gfc_state_data s;
   int seen_enumerator = 0;
 
-  error_flag = 0;
-
   push_state (&s, COMP_ENUM, gfc_new_block);
 
   compiling_enum = 1;
@@ -2131,10 +2174,7 @@ parse_enum (void)
        case ST_END_ENUM:
          compiling_enum = 0;
          if (!seen_enumerator)
-           {
-             gfc_error ("ENUM declaration at %C has no ENUMERATORS");
-             error_flag = 1;
-           }
+           gfc_error ("ENUM declaration at %C has no ENUMERATORS");
          accept_statement (st);
          break;
 
@@ -2226,32 +2266,16 @@ loop:
     }
 
 
-  /* Make sure that a generic interface has only subroutines or
-     functions and that the generic name has the right attribute.  */
-  if (current_interface.type == INTERFACE_GENERIC)
+  /* Make sure that the generic name has the right attribute.  */
+  if (current_interface.type == INTERFACE_GENERIC
+      && current_state == COMP_NONE)
     {
-      if (current_state == COMP_NONE)
-       {
-         if (new_state == COMP_FUNCTION)
-           gfc_add_function (&sym->attr, sym->name, NULL);
-         else if (new_state == COMP_SUBROUTINE)
-           gfc_add_subroutine (&sym->attr, sym->name, NULL);
-
-         current_state = new_state;
-       }
-      else
-       {
-         if (new_state != current_state)
-           {
-             if (new_state == COMP_SUBROUTINE)
-               gfc_error ("SUBROUTINE at %C does not belong in a "
-                          "generic function interface");
+      if (new_state == COMP_FUNCTION && sym)
+       gfc_add_function (&sym->attr, sym->name, NULL);
+      else if (new_state == COMP_SUBROUTINE && sym)
+       gfc_add_subroutine (&sym->attr, sym->name, NULL);
 
-             if (new_state == COMP_FUNCTION)
-               gfc_error ("FUNCTION at %C does not belong in a "
-                          "generic subroutine interface");
-           }
-       }
+      current_state = new_state;
     }
 
   if (current_interface.type == INTERFACE_ABSTRACT)
@@ -2340,7 +2364,7 @@ match_deferred_characteristics (gfc_typespec * ts)
     {
       ts->kind = 0;
 
-      if (!ts->u.derived || !ts->u.derived->components)
+      if (!ts->u.derived)
        m = MATCH_ERROR;
     }
 
@@ -2358,7 +2382,10 @@ match_deferred_characteristics (gfc_typespec * ts)
       gfc_commit_symbols ();
     }
   else
-    gfc_error_check ();
+    {
+      gfc_error_check ();
+      gfc_undo_symbols ();
+    }
 
   gfc_current_locus =loc;
   return m;
@@ -2430,6 +2457,7 @@ loop:
        case ST_STATEMENT_FUNCTION:
          gfc_error ("%s statement is not allowed inside of BLOCK at %C",
                     gfc_ascii_statement (st));
+         reject_statement ();
          break;
 
        default:
@@ -2516,6 +2544,7 @@ declSt:
            {
              gfc_error ("%s statement must appear in a MODULE",
                         gfc_ascii_statement (st));
+             reject_statement ();
              break;
            }
 
@@ -2523,6 +2552,7 @@ declSt:
            {
              gfc_error ("%s statement at %C follows another accessibility "
                         "specification", gfc_ascii_statement (st));
+             reject_statement ();
              break;
            }
 
@@ -3044,6 +3074,61 @@ check_do_closure (void)
 static void parse_progunit (gfc_statement);
 
 
+/* Parse a CRITICAL block.  */
+
+static void
+parse_critical_block (void)
+{
+  gfc_code *top, *d;
+  gfc_state_data s;
+  gfc_statement st;
+
+  s.ext.end_do_label = new_st.label1;
+
+  accept_statement (ST_CRITICAL);
+  top = gfc_state_stack->tail;
+
+  push_state (&s, COMP_CRITICAL, gfc_new_block);
+
+  d = add_statement ();
+  d->op = EXEC_CRITICAL;
+  top->block = d;
+
+  do
+    {
+      st = parse_executable (ST_NONE);
+
+      switch (st)
+       {
+         case ST_NONE:
+           unexpected_eof ();
+           break;
+
+         case ST_END_CRITICAL:
+           if (s.ext.end_do_label != NULL
+               && s.ext.end_do_label != gfc_statement_label)
+             gfc_error_now ("Statement label in END CRITICAL at %C does not "
+                            "match CRITIAL label");
+
+           if (gfc_statement_label != NULL)
+             {
+               new_st.op = EXEC_NOP;
+               add_statement ();
+             }
+           break;
+
+         default:
+           unexpected_statement (st);
+           break;
+       }
+    }
+  while (st != ST_END_CRITICAL);
+
+  pop_state ();
+  accept_statement (st);
+}
+
+
 /* Set up the local namespace for a BLOCK construct.  */
 
 gfc_namespace*
@@ -3091,7 +3176,8 @@ parse_block_construct (void)
   my_ns = gfc_build_block_ns (gfc_current_ns);
 
   new_st.op = EXEC_BLOCK;
-  new_st.ext.ns = my_ns;
+  new_st.ext.block.ns = my_ns;
+  new_st.ext.block.assoc = NULL;
   accept_statement (ST_BLOCK);
 
   push_state (&s, COMP_BLOCK, my_ns->proc_name);
@@ -3104,6 +3190,74 @@ parse_block_construct (void)
 }
 
 
+/* Parse an ASSOCIATE construct.  This is essentially a BLOCK construct
+   behind the scenes with compiler-generated variables.  */
+
+static void
+parse_associate (void)
+{
+  gfc_namespace* my_ns;
+  gfc_state_data s;
+  gfc_statement st;
+  gfc_association_list* a;
+
+  gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ASSOCIATE construct at %C");
+
+  my_ns = gfc_build_block_ns (gfc_current_ns);
+
+  new_st.op = EXEC_BLOCK;
+  new_st.ext.block.ns = my_ns;
+  gcc_assert (new_st.ext.block.assoc);
+
+  /* Add all associate-names as BLOCK variables.  Creating them is enough
+     for now, they'll get their values during trans-* phase.  */
+  gfc_current_ns = my_ns;
+  for (a = new_st.ext.block.assoc; a; a = a->next)
+    {
+      gfc_symbol* sym;
+
+      if (gfc_get_sym_tree (a->name, NULL, &a->st, false))
+       gcc_unreachable ();
+
+      sym = a->st->n.sym;
+      sym->attr.flavor = FL_VARIABLE;
+      sym->assoc = a;
+      sym->declared_at = a->where;
+      gfc_set_sym_referenced (sym);
+
+      /* Initialize the typespec.  It is not available in all cases,
+        however, as it may only be set on the target during resolution.
+        Still, sometimes it helps to have it right now -- especially
+        for parsing component references on the associate-name
+        in case of assication to a derived-type.  */
+      sym->ts = a->target->ts;
+    }
+
+  accept_statement (ST_ASSOCIATE);
+  push_state (&s, COMP_ASSOCIATE, my_ns->proc_name);
+
+loop:
+  st = parse_executable (ST_NONE);
+  switch (st)
+    {
+    case ST_NONE:
+      unexpected_eof ();
+
+    case_end:
+      accept_statement (st);
+      my_ns->code = gfc_state_stack->head;
+      break;
+
+    default:
+      unexpected_statement (st);
+      goto loop;
+    }
+
+  gfc_current_ns = gfc_current_ns->parent;
+  pop_state ();
+}
+
+
 /* Parse a DO loop.  Note that the ST_CYCLE and ST_EXIT statements are
    handled inside of parse_executable(), because they aren't really
    loop statements.  */
@@ -3469,6 +3623,7 @@ parse_executable (gfc_statement st)
          case ST_CYCLE:
          case ST_PAUSE:
          case ST_STOP:
+         case ST_ERROR_STOP:
          case ST_END_SUBROUTINE:
 
          case ST_DO:
@@ -3501,6 +3656,10 @@ parse_executable (gfc_statement st)
          parse_block_construct ();
          break;
 
+       case ST_ASSOCIATE:
+         parse_associate ();
+         break;
+
        case ST_IF_BLOCK:
          parse_if_block ();
          break;
@@ -3519,6 +3678,10 @@ parse_executable (gfc_statement st)
            return ST_IMPLIED_ENDDO;
          break;
 
+       case ST_CRITICAL:
+         parse_critical_block ();
+         break;
+
        case ST_WHERE_BLOCK:
          parse_where_block ();
          break;
@@ -3591,6 +3754,7 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
                  || (old_sym->ts.type != BT_UNKNOWN
                        && !old_sym->attr.implicit_type)
                  || old_sym->attr.flavor == FL_PARAMETER
+                 || old_sym->attr.use_assoc
                  || old_sym->attr.in_common
                  || old_sym->attr.in_equivalence
                  || old_sym->attr.data
@@ -3607,10 +3771,7 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
          st->n.sym = sym;
          sym->refs++;
 
-         /* Free the old (local) symbol.  */
-         old_sym->refs--;
-         if (old_sym->refs == 0)
-           gfc_free_symbol (old_sym);
+         gfc_release_symbol (old_sym);
        }
 
 fixup_contained:
@@ -3692,6 +3853,12 @@ parse_contained (int module)
          sym->attr.contained = 1;
          sym->attr.referenced = 1;
 
+         /* Set implicit_pure so that it can be reset if any of the
+            tests for purity fail.  This is used for some optimisation
+            during translation.  */
+         if (!sym->attr.pure)
+           sym->attr.implicit_pure = 1;
+
          parse_progunit (ST_NONE);
 
          /* Fix up any sibling functions that refer to this one.  */
@@ -3818,6 +3985,7 @@ contains:
     {
       gfc_error ("CONTAINS statement at %C is already in a contained "
                 "program unit");
+      reject_statement ();
       st = next_statement ();
       goto loop;
     }
@@ -4022,7 +4190,8 @@ resolve_all_program_units (gfc_namespace *gfc_global_ns_list)
   gfc_current_ns = gfc_global_ns_list;
   for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
     {
-      gfc_current_locus = gfc_current_ns->proc_name->declared_at;
+      if (gfc_current_ns->proc_name)
+       gfc_current_locus = gfc_current_ns->proc_name->declared_at;
       gfc_resolve (gfc_current_ns);
       gfc_current_ns->derived_types = gfc_derived_types;
       gfc_derived_types = NULL;
@@ -4198,7 +4367,7 @@ loop:
   gfc_resolve (gfc_current_ns);
 
   /* Dump the parse tree if requested.  */
-  if (gfc_option.dump_parse_tree)
+  if (gfc_option.dump_fortran_original)
     gfc_dump_parse_tree (gfc_current_ns, stdout);
 
   gfc_get_errors (NULL, &errors);
@@ -4233,7 +4402,11 @@ prog_units:
      later and all their interfaces resolved.  */
   gfc_current_ns->code = s.head;
   if (next)
-    next->sibling = gfc_current_ns;
+    {
+      for (; next->sibling; next = next->sibling)
+       ;
+      next->sibling = gfc_current_ns;
+    }
   else
     gfc_global_ns_list = gfc_current_ns;
 
@@ -4252,7 +4425,7 @@ prog_units:
 
   /* Do the parse tree dump.  */ 
   gfc_current_ns
-       = gfc_option.dump_parse_tree ? gfc_global_ns_list : NULL;
+       = gfc_option.dump_fortran_original ? gfc_global_ns_list : NULL;
 
   for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
     {