OSDN Git Service

compiler: Use backend interface for type sizes and alignments.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / parse.c
index c35db2d..317fb84 100644 (file)
@@ -1,5 +1,6 @@
 /* Main parser.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
@@ -36,6 +37,7 @@ static locus label_locus;
 static jmp_buf eof_buf;
 
 gfc_state_data *gfc_state_stack;
+static bool last_was_use_stmt = false;
 
 /* TODO: Re-order functions to kill these forward decls.  */
 static void check_statement_label (gfc_statement);
@@ -73,6 +75,26 @@ match_word (const char *str, match (*subr) (void), locus *old_locus)
 }
 
 
+/* Load symbols from all USE statements encounted in this scoping unit.  */
+
+static void
+use_modules (void)
+{
+  gfc_error_buf old_error;
+
+  gfc_push_error (&old_error);
+  gfc_buffer_error (0);
+  gfc_use_modules ();
+  gfc_buffer_error (1);
+  gfc_pop_error (&old_error);
+  gfc_commit_symbols ();
+  gfc_warning_check ();
+  gfc_current_ns->old_cl_list = gfc_current_ns->cl_list;
+  gfc_current_ns->old_equiv = gfc_current_ns->equiv;
+  last_was_use_stmt = false;
+}
+
+
 /* Figure out what the next statement is, (mostly) regardless of
    proper ordering.  The do...while(0) is there to prevent if/else
    ambiguity.  */
@@ -107,10 +129,21 @@ decode_specification_statement (void)
 
   old_locus = gfc_current_locus;
 
+  if (match_word ("use", gfc_match_use, &old_locus) == MATCH_YES)
+    {
+      last_was_use_stmt = true;
+      return ST_USE;
+    }
+  else
+    {
+      undo_new_statement ();
+      if (last_was_use_stmt)
+       use_modules ();
+    }
+
   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);
@@ -128,6 +161,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':
@@ -135,6 +170,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':
@@ -231,9 +268,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.  */
@@ -249,6 +284,22 @@ decode_statement (void)
 
   old_locus = gfc_current_locus;
 
+  c = gfc_peek_ascii_char ();
+
+  if (c == 'u')
+    {
+      if (match_word ("use", gfc_match_use, &old_locus) == MATCH_YES)
+       {
+         last_was_use_stmt = true;
+         return ST_USE;
+       }
+      else
+       undo_new_statement ();
+    }
+
+  if (last_was_use_stmt)
+    use_modules ();
+
   /* Try matching a data declaration or function declaration. The
       input "REALFUNCTIONA(N)" can mean several things in different
       contexts, so it (and its relatives) get special treatment.  */
@@ -288,9 +339,9 @@ decode_statement (void)
   gfc_undo_symbols ();
   gfc_current_locus = old_locus;
 
-  /* Check for the IF, DO, SELECT, WHERE and FORALL 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,14 +360,16 @@ decode_statement (void)
   gfc_current_locus = old_locus;
 
   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);
 
   /* General statement matching: Instead of testing every possible
      statement, we eliminate most possibilities by peeking at the
      first character.  */
 
-  c = gfc_peek_ascii_char ();
-
   switch (c)
     {
     case 'a':
@@ -325,6 +378,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':
@@ -337,10 +391,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':
@@ -355,6 +412,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)
@@ -372,6 +430,7 @@ decode_statement (void)
       break;
 
     case 'g':
+      match ("generic", gfc_match_generic, ST_GENERIC);
       match ("go to", gfc_match_goto, ST_GOTO);
       break;
 
@@ -385,8 +444,12 @@ decode_statement (void)
       match ("intrinsic", gfc_match_intrinsic, ST_ATTR_DECL);
       break;
 
+    case 'l':
+      match ("lock", gfc_match_lock, ST_LOCK);
+      break;
+
     case 'm':
-      match ("module% procedure", gfc_match_modproc, ST_MODULE_PROC);
+      match ("module% procedure", gfc_match_modproc, ST_MODULE_PROC);
       match ("module", gfc_match_module, ST_MODULE);
       break;
 
@@ -424,15 +487,19 @@ 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':
       match ("target", gfc_match_target, ST_ATTR_DECL);
       match ("type", gfc_match_derived_decl, ST_DERIVED_DECL);
+      match ("type is", gfc_match_type_is, ST_TYPE_IS);
       break;
 
     case 'u':
-      match ("use", gfc_match_use, ST_USE);
+      match ("unlock", gfc_match_unlock, ST_UNLOCK);
       break;
 
     case 'v':
@@ -465,9 +532,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.  */
@@ -480,6 +545,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
@@ -503,6 +571,7 @@ decode_omp_directive (void)
       match ("do", gfc_match_omp_do, ST_OMP_DO);
       break;
     case 'e':
+      match ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC);
       match ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL);
       match ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO);
       match ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER);
@@ -544,6 +613,7 @@ decode_omp_directive (void)
     case 't':
       match ("task", gfc_match_omp_task, ST_OMP_TASK);
       match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
+      match ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD);
       match ("threadprivate", gfc_match_omp_threadprivate,
             ST_OMP_THREADPRIVATE);
     case 'w':
@@ -564,6 +634,32 @@ decode_omp_directive (void)
   return ST_NONE;
 }
 
+static gfc_statement
+decode_gcc_attribute (void)
+{
+  locus old_locus;
+
+  gfc_enforce_clean_symbol_state ();
+
+  gfc_clear_error ();  /* Clear any pending errors.  */
+  gfc_clear_warning ();        /* Clear any pending warnings.  */
+  old_locus = gfc_current_locus;
+
+  match ("attributes", gfc_match_gcc_attributes, ST_ATTR_DECL);
+
+  /* All else has failed, so give up.  See if any of the matchers has
+     stored an error message of some sort.  */
+
+  if (gfc_error_check () == 0)
+    gfc_error_now ("Unclassifiable GCC directive at %C");
+
+  reject_statement ();
+
+  gfc_error_recovery ();
+
+  return ST_NONE;
+}
+
 #undef match
 
 
@@ -625,7 +721,7 @@ next_free (void)
          if (gfc_match_eos () == MATCH_YES)
            {
              gfc_warning_now ("Ignoring statement label in empty statement "
-                              "at %C");
+                              "at %L", &label_locus);
              gfc_free_st_label (gfc_statement_label);
              gfc_statement_label = NULL;
              return ST_NONE;
@@ -635,24 +731,46 @@ next_free (void)
   else if (c == '!')
     {
       /* Comments have already been skipped by the time we get here,
-        except for OpenMP directives.  */
-      if (gfc_option.flag_openmp)
+        except for GCC attributes and OpenMP directives.  */
+
+      gfc_next_ascii_char (); /* Eat up the exclamation sign.  */
+      c = gfc_peek_ascii_char ();
+
+      if (c == 'g')
+       {
+         int i;
+
+         c = gfc_next_ascii_char ();
+         for (i = 0; i < 4; i++, c = gfc_next_ascii_char ())
+           gcc_assert (c == "gcc$"[i]);
+
+         gfc_gobble_whitespace ();
+         return decode_gcc_attribute ();
+
+       }
+      else if (c == '$' && gfc_option.gfc_flag_openmp)
        {
          int i;
 
          c = gfc_next_ascii_char ();
-         for (i = 0; i < 5; i++, c = gfc_next_ascii_char ())
-           gcc_assert (c == "!$omp"[i]);
+         for (i = 0; i < 4; i++, c = gfc_next_ascii_char ())
+           gcc_assert (c == "$omp"[i]);
 
          gcc_assert (c == ' ' || c == '\t');
          gfc_gobble_whitespace ();
+         if (last_was_use_stmt)
+           use_modules ();
          return decode_omp_directive ();
        }
-    }
 
+      gcc_unreachable (); 
+    }
   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;
     }
@@ -684,7 +802,7 @@ next_fixed (void)
 
   for (i = 0; i < 5; i++)
     {
-      c = gfc_next_char_literal (0);
+      c = gfc_next_char_literal (NONSTRING);
 
       switch (c)
        {
@@ -707,12 +825,22 @@ next_fixed (void)
          break;
 
          /* Comments have already been skipped by the time we get
-            here, except for OpenMP directives.  */
+            here, except for GCC attributes and OpenMP directives.  */
+
        case '*':
-         if (gfc_option.flag_openmp)
+         c = gfc_next_char_literal (NONSTRING);
+         
+         if (TOLOWER (c) == 'g')
+           {
+             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.gfc_flag_openmp)
            {
-             for (i = 0; i < 5; i++, c = gfc_next_char_literal (0))
-               gcc_assert ((char) gfc_wide_tolower (c) == "*$omp"[i]);
+             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')
                {
@@ -720,7 +848,8 @@ next_fixed (void)
                  gfc_error ("Bad continuation line at %C");
                  return ST_NONE;
                }
-
+             if (last_was_use_stmt)
+               use_modules ();
              return decode_omp_directive ();
            }
          /* FALLTHROUGH */
@@ -750,7 +879,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;
 
@@ -768,7 +897,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));
 
@@ -778,7 +907,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;
     }
 
@@ -790,7 +923,10 @@ next_fixed (void)
 
 blank_line:
   if (digit_flag)
-    gfc_warning ("Ignoring statement label in empty statement at %C");
+    gfc_warning_now ("Ignoring statement label in empty statement at %L",
+                    &label_locus);
+    
+  gfc_current_locus.lb->truncated = 0;
   gfc_advance_line ();
   return ST_NONE;
 }
@@ -804,22 +940,20 @@ 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;
       gfc_buffer_error (1);
 
       if (gfc_at_eol ())
-       {
-         if ((gfc_option.warn_line_truncation || gfc_current_form == FORM_FREE)
-             && gfc_current_locus.lb
-             && gfc_current_locus.lb->truncated)
-           gfc_warning_now ("Line truncated at %C");
-
-         gfc_advance_line ();
-       }
+       gfc_advance_line ();
 
       gfc_skip_comments ();
 
@@ -873,17 +1007,21 @@ 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_OMP_TASKYIELD: \
+  case ST_ERROR_STOP: case ST_SYNC_ALL: case ST_SYNC_IMAGES: \
+  case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK
 
 /* Statements that mark other executable statements.  */
 
-#define case_exec_markers case ST_DO: case ST_FORALL_BLOCK: case ST_IF_BLOCK: \
-  case ST_WHERE_BLOCK: case ST_SELECT_CASE: case ST_OMP_PARALLEL: \
+#define case_exec_markers case ST_DO: case ST_FORALL_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 */
 
@@ -896,7 +1034,8 @@ 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: \
+                case ST_END_BLOCK: case ST_END_ASSOCIATE
 
 
 /* Push a new state onto the stack.  */
@@ -909,6 +1048,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;
 }
 
@@ -923,7 +1069,7 @@ pop_state (void)
 
 /* Try to find the given state in the state stack.  */
 
-try
+gfc_try
 gfc_find_state (gfc_compile_state state)
 {
   gfc_state_data *p;
@@ -1016,6 +1162,9 @@ check_statement_label (gfc_statement st)
     case ST_ENDDO:
     case ST_ENDIF:
     case ST_END_SELECT:
+    case ST_END_CRITICAL:
+    case ST_END_BLOCK:
+    case ST_END_ASSOCIATE:
     case_executable:
     case_exec_markers:
       type = ST_LABEL_TARGET;
@@ -1080,12 +1229,18 @@ 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;
     case ST_BACKSPACE:
       p = "BACKSPACE";
       break;
+    case ST_BLOCK:
+      p = "BLOCK";
+      break;
     case ST_BLOCK_DATA:
       p = "BLOCK DATA";
       break;
@@ -1107,6 +1262,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;
@@ -1134,9 +1292,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;
@@ -1179,6 +1346,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;
@@ -1195,6 +1365,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_FUNCTION:
       p = "FUNCTION";
       break;
+    case ST_GENERIC:
+      p = "GENERIC";
+      break;
     case ST_GOTO:
       p = "GOTO";
       break;
@@ -1219,6 +1392,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_INTERFACE:
       p = "INTERFACE";
       break;
+    case ST_LOCK:
+      p = "LOCK";
+      break;
     case ST_PARAMETER:
       p = "PARAMETER";
       break;
@@ -1264,12 +1440,24 @@ 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;
     case ST_TYPE:
       p = "TYPE";
       break;
+    case ST_UNLOCK:
+      p = "UNLOCK";
+      break;
     case ST_USE:
       p = "USE";
       break;
@@ -1292,6 +1480,15 @@ gfc_ascii_statement (gfc_statement st)
     case ST_SELECT_CASE:
       p = "SELECT CASE";
       break;
+    case ST_SELECT_TYPE:
+      p = "SELECT TYPE";
+      break;
+    case ST_TYPE_IS:
+      p = "TYPE IS";
+      break;
+    case ST_CLASS_IS:
+      p = "CLASS IS";
+      break;
     case ST_SEQUENCE:
       p = "SEQUENCE";
       break;
@@ -1325,6 +1522,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_DO:
       p = "!$OMP DO";
       break;
+    case ST_OMP_END_ATOMIC:
+      p = "!$OMP END ATOMIC";
+      break;
     case ST_OMP_END_CRITICAL:
       p = "!$OMP END CRITICAL";
       break;
@@ -1397,6 +1597,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_TASKWAIT:
       p = "!$OMP TASKWAIT";
       break;
+    case ST_OMP_TASKYIELD:
+      p = "!$OMP TASKYIELD";
+      break;
     case ST_OMP_THREADPRIVATE:
       p = "!$OMP THREADPRIVATE";
       break;
@@ -1440,10 +1643,6 @@ accept_statement (gfc_statement st)
 {
   switch (st)
     {
-    case ST_USE:
-      gfc_use_module ();
-      break;
-
     case ST_IMPLICIT_NONE:
       gfc_set_implicit_none ();
       break;
@@ -1459,16 +1658,36 @@ accept_statement (gfc_statement st)
 
       /* 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.  */
+        construct.  IF and SELECT are treated differently from DO
+        (where EXEC_NOP is added inside the loop) for two
+        reasons:
+         1. END DO has a meaning in the sense that after a GOTO to
+           it, the loop counter must be increased.
+         2. IF blocks and SELECT blocks can consist of multiple
+           parallel blocks (IF ... ELSE IF ... ELSE ... END IF).
+           Putting the label before the END IF would make the jump
+           from, say, the ELSE IF block to the END IF illegal.  */
 
     case ST_ENDIF:
     case ST_END_SELECT:
+    case ST_END_CRITICAL:
       if (gfc_statement_label != NULL)
        {
-         new_st.op = EXEC_NOP;
+         new_st.op = EXEC_END_NESTED_BLOCK;
          add_statement ();
        }
+      break;
 
+      /* In the case of BLOCK and ASSOCIATE blocks, there cannot be more than
+        one parallel block.  Thus, we add the special code to the nested block
+        itself, instead of the parent one.  */
+    case ST_END_BLOCK:
+    case ST_END_ASSOCIATE:
+      if (gfc_statement_label != NULL)
+       {
+         new_st.op = EXEC_END_BLOCK;
+         add_statement ();
+       }
       break;
 
       /* The end-of-program unit statements do not get the special
@@ -1483,6 +1702,11 @@ accept_statement (gfc_statement st)
          new_st.op = EXEC_RETURN;
          add_statement ();
        }
+      else
+       {
+         new_st.op = EXEC_END_PROCEDURE;
+         add_statement ();
+       }
 
       break;
 
@@ -1508,6 +1732,13 @@ accept_statement (gfc_statement st)
 static void
 reject_statement (void)
 {
+  /* Revert to the previous charlen chain.  */
+  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 ();
@@ -1533,7 +1764,7 @@ unexpected_statement (gfc_statement st)
    issue an error and return FAILURE.  Otherwise we return SUCCESS.
 
    Individual parsers need to verify that the statements seen are
-   valid before calling here, ie ENTRY statements are not allowed in
+   valid before calling here, i.e., ENTRY statements are not allowed in
    INTERFACE blocks.  The following diagram is taken from the standard:
 
            +---------------------------------------+
@@ -1563,20 +1794,27 @@ unexpected_statement (gfc_statement st)
 
 */
 
+enum state_order
+{
+  ORDER_START,
+  ORDER_USE,
+  ORDER_IMPORT,
+  ORDER_IMPLICIT_NONE,
+  ORDER_IMPLICIT,
+  ORDER_SPEC,
+  ORDER_EXEC
+};
+
 typedef struct
 {
-  enum
-  { ORDER_START, ORDER_USE, ORDER_IMPORT, ORDER_IMPLICIT_NONE,
-    ORDER_IMPLICIT, ORDER_SPEC, ORDER_EXEC
-  }
-  state;
+  enum state_order state;
   gfc_statement last_statement;
   locus where;
 }
 st_state;
 
-static try
-verify_st_order (st_state *p, gfc_statement st)
+static gfc_try
+verify_st_order (st_state *p, gfc_statement st, bool silent)
 {
 
   switch (st)
@@ -1660,9 +1898,10 @@ verify_st_order (st_state *p, gfc_statement st)
   return SUCCESS;
 
 order:
-  gfc_error ("%s statement at %C cannot follow %s statement at %L",
-            gfc_ascii_statement (st),
-            gfc_ascii_statement (p->last_statement), &p->where);
+  if (!silent)
+    gfc_error ("%s statement at %C cannot follow %s statement at %L",
+              gfc_ascii_statement (st),
+              gfc_ascii_statement (p->last_statement), &p->where);
 
   return FAILURE;
 }
@@ -1690,20 +1929,154 @@ unexpected_eof (void)
 }
 
 
+/* Parse the CONTAINS section of a derived type definition.  */
+
+gfc_access gfc_typebound_default_access;
+
+static bool
+parse_derived_contains (void)
+{
+  gfc_state_data s;
+  bool seen_private = false;
+  bool seen_comps = false;
+  bool error_flag = false;
+  bool to_finish;
+
+  gcc_assert (gfc_current_state () == COMP_DERIVED);
+  gcc_assert (gfc_current_block ());
+
+  /* Derived-types with SEQUENCE and/or BIND(C) must not have a CONTAINS
+     section.  */
+  if (gfc_current_block ()->attr.sequence)
+    gfc_error ("Derived-type '%s' with SEQUENCE must not have a CONTAINS"
+              " section at %C", gfc_current_block ()->name);
+  if (gfc_current_block ()->attr.is_bind_c)
+    gfc_error ("Derived-type '%s' with BIND(C) must not have a CONTAINS"
+              " section at %C", gfc_current_block ()->name);
+
+  accept_statement (ST_CONTAINS);
+  push_state (&s, COMP_DERIVED_CONTAINS, NULL);
+
+  gfc_typebound_default_access = ACCESS_PUBLIC;
+
+  to_finish = false;
+  while (!to_finish)
+    {
+      gfc_statement st;
+      st = next_statement ();
+      switch (st)
+       {
+       case ST_NONE:
+         unexpected_eof ();
+         break;
+
+       case ST_DATA_DECL:
+         gfc_error ("Components in TYPE at %C must precede CONTAINS");
+         goto error;
+
+       case ST_PROCEDURE:
+         if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003:  Type-bound"
+                                            " procedure at %C") == FAILURE)
+           goto error;
+
+         accept_statement (ST_PROCEDURE);
+         seen_comps = true;
+         break;
+
+       case ST_GENERIC:
+         if (gfc_notify_std (GFC_STD_F2003, "Fortran 2003:  GENERIC binding"
+                                            " at %C") == FAILURE)
+           goto error;
+
+         accept_statement (ST_GENERIC);
+         seen_comps = true;
+         break;
+
+       case ST_FINAL:
+         if (gfc_notify_std (GFC_STD_F2003,
+                             "Fortran 2003:  FINAL procedure declaration"
+                             " at %C") == FAILURE)
+           goto error;
+
+         accept_statement (ST_FINAL);
+         seen_comps = true;
+         break;
+
+       case ST_END_TYPE:
+         to_finish = true;
+
+         if (!seen_comps
+             && (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Derived type "
+                                 "definition at %C with empty CONTAINS "
+                                 "section") == FAILURE))
+           goto error;
+
+         /* ST_END_TYPE is accepted by parse_derived after return.  */
+         break;
+
+       case ST_PRIVATE:
+         if (gfc_find_state (COMP_MODULE) == FAILURE)
+           {
+             gfc_error ("PRIVATE statement in TYPE at %C must be inside "
+                        "a MODULE");
+             goto error;
+           }
+
+         if (seen_comps)
+           {
+             gfc_error ("PRIVATE statement at %C must precede procedure"
+                        " bindings");
+             goto error;
+           }
+
+         if (seen_private)
+           {
+             gfc_error ("Duplicate PRIVATE statement at %C");
+             goto error;
+           }
+
+         accept_statement (ST_PRIVATE);
+         gfc_typebound_default_access = ACCESS_PRIVATE;
+         seen_private = true;
+         break;
+
+       case ST_SEQUENCE:
+         gfc_error ("SEQUENCE statement at %C must precede CONTAINS");
+         goto error;
+
+       case ST_CONTAINS:
+         gfc_error ("Already inside a CONTAINS block at %C");
+         goto error;
+
+       default:
+         unexpected_statement (st);
+         break;
+       }
+
+      continue;
+
+error:
+      error_flag = true;
+      reject_statement ();
+    }
+
+  pop_state ();
+  gcc_assert (gfc_current_state () == COMP_DERIVED);
+
+  return error_flag;
+}
+
+
 /* Parse a derived type.  */
 
 static void
 parse_derived (void)
 {
-  int compiling_type, seen_private, seen_sequence, seen_component, error_flag;
-  int seen_contains, seen_contains_comp;
+  int compiling_type, seen_private, seen_sequence, seen_component;
   gfc_statement st;
   gfc_state_data s;
-  gfc_symbol *derived_sym = NULL;
   gfc_symbol *sym;
-  gfc_component *c;
-
-  error_flag = 0;
+  gfc_component *c, *lock_comp = NULL;
 
   accept_statement (ST_DERIVED_DECL);
   push_state (&s, COMP_DERIVED, gfc_new_block);
@@ -1712,8 +2085,6 @@ parse_derived (void)
   seen_private = 0;
   seen_sequence = 0;
   seen_component = 0;
-  seen_contains = 0;
-  seen_contains_comp = 0;
 
   compiling_type = 1;
 
@@ -1727,62 +2098,30 @@ parse_derived (void)
 
        case ST_DATA_DECL:
        case ST_PROCEDURE:
-         if (seen_contains)
-           {
-             gfc_error ("Components in TYPE at %C must precede CONTAINS");
-             error_flag = 1;
-           }
-
          accept_statement (st);
          seen_component = 1;
          break;
 
        case ST_FINAL:
-         if (!seen_contains)
-           {
-             gfc_error ("FINAL declaration at %C must be inside CONTAINS");
-             error_flag = 1;
-           }
-
-         if (gfc_notify_std (GFC_STD_F2003,
-                             "Fortran 2003:  FINAL procedure declaration"
-                             " at %C") == FAILURE)
-           error_flag = 1;
-
-         accept_statement (ST_FINAL);
-         seen_contains_comp = 1;
+         gfc_error ("FINAL declaration at %C must be inside CONTAINS");
          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_contains && !seen_contains_comp
-             && (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Derived type "
-                                "definition at %C with empty CONTAINS "
-                                "section") == 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;
 
        case ST_PRIVATE:
-         if (seen_contains)
-           {
-             gfc_error ("PRIVATE statement at %C must precede CONTAINS");
-             error_flag = 1;
-           }
-
          if (gfc_find_state (COMP_MODULE) == FAILURE)
            {
              gfc_error ("PRIVATE statement in TYPE at %C must be inside "
                         "a MODULE");
-             error_flag = 1;
              break;
            }
 
@@ -1790,33 +2129,23 @@ parse_derived (void)
            {
              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;
+
          accept_statement (ST_PRIVATE);
          seen_private = 1;
          break;
 
        case ST_SEQUENCE:
-         if (seen_contains)
-           {
-             gfc_error ("SEQUENCE statement at %C must precede CONTAINS");
-             error_flag = 1;
-           }
-
          if (seen_component)
            {
              gfc_error ("SEQUENCE statement at %C must precede "
                         "structure components");
-             error_flag = 1;
              break;
            }
 
@@ -1827,7 +2156,6 @@ parse_derived (void)
          if (seen_sequence)
            {
              gfc_error ("Duplicate SEQUENCE statement at %C");
-             error_flag = 1;
            }
 
          seen_sequence = 1;
@@ -1836,20 +2164,13 @@ parse_derived (void)
          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;
-
-         if (seen_contains)
-           {
-             gfc_error ("Already inside a CONTAINS block at %C");
-             error_flag = 1;
-           }
+         gfc_notify_std (GFC_STD_F2003,
+                         "Fortran 2003:  CONTAINS block in derived type"
+                         " definition at %C");
 
-         seen_contains = 1;
          accept_statement (ST_CONTAINS);
-         break;
+         parse_derived_contains ();
+         goto endType;
 
        default:
          unexpected_statement (st);
@@ -1860,35 +2181,116 @@ parse_derived (void)
   /* need to verify that all fields of the derived type are
    * interoperable with C if the type is declared to be bind(c)
    */
-  derived_sym = gfc_current_block();
-
   sym = gfc_current_block ();
   for (c = sym->components; c; c = c->next)
     {
+      bool coarray, lock_type, allocatable, pointer;
+      coarray = lock_type = allocatable = pointer = false;
+
       /* Look for allocatable components.  */
-      if (c->allocatable
-         || (c->ts.type == BT_DERIVED && c->ts.derived->attr.alloc_comp))
+      if (c->attr.allocatable
+         || (c->ts.type == BT_CLASS && c->attr.class_ok
+             && CLASS_DATA (c)->attr.allocatable)
+         || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.alloc_comp))
        {
+         allocatable = true;
          sym->attr.alloc_comp = 1;
-         break;
        }
 
       /* Look for pointer components.  */
-      if (c->pointer
-         || (c->ts.type == BT_DERIVED && c->ts.derived->attr.pointer_comp))
+      if (c->attr.pointer
+         || (c->ts.type == BT_CLASS && c->attr.class_ok
+             && CLASS_DATA (c)->attr.class_pointer)
+         || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.pointer_comp))
        {
+         pointer = true;
          sym->attr.pointer_comp = 1;
-         break;
        }
 
-      /* Look for private components.  */
-      if (sym->component_access == ACCESS_PRIVATE
-         || c->access == ACCESS_PRIVATE
-         || (c->ts.type == BT_DERIVED && c->ts.derived->attr.private_comp))
+      /* Look for procedure pointer components.  */
+      if (c->attr.proc_pointer
+         || (c->ts.type == BT_DERIVED
+             && c->ts.u.derived->attr.proc_pointer_comp))
+       sym->attr.proc_pointer_comp = 1;
+
+      /* Looking for coarray components.  */
+      if (c->attr.codimension
+         || (c->ts.type == BT_CLASS && c->attr.class_ok
+             && CLASS_DATA (c)->attr.codimension))
        {
-         sym->attr.private_comp = 1;
-         break;
+         coarray = true;
+         sym->attr.coarray_comp = 1;
+       }
+     
+      if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.coarray_comp)
+       {
+         coarray = true;
+         if (!pointer && !allocatable)
+           sym->attr.coarray_comp = 1;
+       }
+
+      /* Looking for lock_type components.  */
+      if ((c->ts.type == BT_DERIVED
+             && c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
+             && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
+         || (c->ts.type == BT_CLASS && c->attr.class_ok
+             && CLASS_DATA (c)->ts.u.derived->from_intmod
+                == INTMOD_ISO_FORTRAN_ENV
+             && CLASS_DATA (c)->ts.u.derived->intmod_sym_id
+                == ISOFORTRAN_LOCK_TYPE)
+         || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.lock_comp
+             && !allocatable && !pointer))
+       {
+         lock_type = 1;
+         lock_comp = c;
+         sym->attr.lock_comp = 1;
        }
+
+      /* Check for F2008, C1302 - and recall that pointers may not be coarrays
+        (5.3.14) and that subobjects of coarray are coarray themselves (2.4.7),
+        unless there are nondirect [allocatable or pointer] components
+        involved (cf. 1.3.33.1 and 1.3.33.3).  */
+
+      if (pointer && !coarray && lock_type)
+       gfc_error ("Component %s at %L of type LOCK_TYPE must have a "
+                  "codimension or be a subcomponent of a coarray, "
+                  "which is not possible as the component has the "
+                  "pointer attribute", c->name, &c->loc);
+      else if (pointer && !coarray && c->ts.type == BT_DERIVED
+              && c->ts.u.derived->attr.lock_comp)
+       gfc_error ("Pointer component %s at %L has a noncoarray subcomponent "
+                  "of type LOCK_TYPE, which must have a codimension or be a "
+                  "subcomponent of a coarray", c->name, &c->loc);
+
+      if (lock_type && allocatable && !coarray)
+       gfc_error ("Allocatable component %s at %L of type LOCK_TYPE must have "
+                  "a codimension", c->name, &c->loc);
+      else if (lock_type && allocatable && c->ts.type == BT_DERIVED
+              && c->ts.u.derived->attr.lock_comp)
+       gfc_error ("Allocatable component %s at %L must have a codimension as "
+                  "it has a noncoarray subcomponent of type LOCK_TYPE",
+                  c->name, &c->loc);
+
+      if (sym->attr.coarray_comp && !coarray && lock_type)
+       gfc_error ("Noncoarray component %s at %L of type LOCK_TYPE or with "
+                  "subcomponent of type LOCK_TYPE must have a codimension or "
+                  "be a subcomponent of a coarray. (Variables of type %s may "
+                  "not have a codimension as already a coarray "
+                  "subcomponent exists)", c->name, &c->loc, sym->name);
+
+      if (sym->attr.lock_comp && coarray && !lock_type)
+       gfc_error ("Noncoarray component %s at %L of type LOCK_TYPE or with "
+                  "subcomponent of type LOCK_TYPE must have a codimension or "
+                  "be a subcomponent of a coarray. (Variables of type %s may "
+                  "not have a codimension as %s at %L has a codimension or a "
+                  "coarray subcomponent)", lock_comp->name, &lock_comp->loc,
+                  sym->name, c->name, &c->loc);
+
+      /* Look for private components.  */
+      if (sym->component_access == ACCESS_PRIVATE
+         || c->attr.access == ACCESS_PRIVATE
+         || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.private_comp))
+       sym->attr.private_comp = 1;
     }
 
   if (!seen_component)
@@ -1903,14 +2305,11 @@ parse_derived (void)
 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;
@@ -1932,10 +2331,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;
 
@@ -1958,7 +2354,7 @@ static gfc_statement parse_spec (gfc_statement);
 static void
 parse_interface (void)
 {
-  gfc_compile_state new_state, current_state;
+  gfc_compile_state new_state = COMP_NONE, current_state;
   gfc_symbol *prog_unit, *sym;
   gfc_interface_info save;
   gfc_state_data s1, s2;
@@ -1992,16 +2388,13 @@ loop:
        new_state = COMP_SUBROUTINE;
       else if (st == ST_FUNCTION)
        new_state = COMP_FUNCTION;
-      if (gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
-                                 gfc_new_block->formal, NULL) == FAILURE)
+      if (gfc_new_block->attr.pointer)
        {
-         reject_statement ();
-         gfc_free_namespace (gfc_current_ns);
-         goto loop;
+         gfc_new_block->attr.pointer = 0;
+         gfc_new_block->attr.proc_pointer = 1;
        }
-      if (current_interface.type != INTERFACE_ABSTRACT &&
-        !gfc_new_block->attr.dummy &&
-        gfc_add_external (&gfc_new_block->attr, &gfc_current_locus) == FAILURE)
+      if (gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
+                                 gfc_new_block->formal, NULL) == FAILURE)
        {
          reject_statement ();
          gfc_free_namespace (gfc_current_ns);
@@ -2030,37 +2423,21 @@ 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)
     {
-      gfc_new_block->attr.abstract = 1;
+      gfc_add_abstract (&gfc_new_block->attr, &gfc_current_locus);
       if (gfc_is_intrinsic_typename (gfc_new_block->name))
        gfc_error ("Name '%s' of ABSTRACT INTERFACE at %C "
                   "cannot be the same as an intrinsic type",
@@ -2099,6 +2476,10 @@ decl:
       goto decl;
     }
 
+  /* Add EXTERNAL attribute to function or subroutine.  */
+  if (current_interface.type != INTERFACE_ABSTRACT && !prog_unit->attr.dummy)
+    gfc_add_external (&prog_unit->attr, &gfc_current_locus);
+
   current_interface = save;
   gfc_add_interface (prog_unit);
   pop_state ();
@@ -2140,7 +2521,7 @@ match_deferred_characteristics (gfc_typespec * ts)
     {
       ts->kind = 0;
 
-      if (!ts->derived || !ts->derived->components)
+      if (!ts->u.derived)
        m = MATCH_ERROR;
     }
 
@@ -2150,40 +2531,137 @@ match_deferred_characteristics (gfc_typespec * ts)
 
   /* 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)
+  if (m == MATCH_YES
+      && gfc_match ("function% %n", name) == MATCH_YES
+      && strcmp (name, gfc_current_block ()->name) == 0)
     {
       gfc_current_block ()->declared_at = gfc_current_locus;
       gfc_commit_symbols ();
     }
   else
-    gfc_error_check ();
+    {
+      gfc_error_check ();
+      gfc_undo_symbols ();
+    }
 
   gfc_current_locus =loc;
   return m;
 }
 
 
-/* Parse a set of specification statements.  Returns the statement
-   that doesn't fit.  */
+/* Check specification-expressions in the function result of the currently
+   parsed block and ensure they are typed (give an IMPLICIT type if necessary).
+   For return types specified in a FUNCTION prefix, the IMPLICIT rules of the
+   scope are not yet parsed so this has to be delayed up to parse_spec.  */
 
-static gfc_statement
-parse_spec (gfc_statement st)
+static void
+check_function_result_typed (void)
+{
+  gfc_typespec* ts = &gfc_current_ns->proc_name->result->ts;
+
+  gcc_assert (gfc_current_state () == COMP_FUNCTION);
+  gcc_assert (ts->type != BT_UNKNOWN);
+
+  /* Check type-parameters, at the moment only CHARACTER lengths possible.  */
+  /* TODO:  Extend when KIND type parameters are implemented.  */
+  if (ts->type == BT_CHARACTER && ts->u.cl && ts->u.cl->length)
+    gfc_expr_check_typed (ts->u.cl->length, gfc_current_ns, true);
+}
+
+
+/* Parse a set of specification statements.  Returns the statement
+   that doesn't fit.  */
+
+static gfc_statement
+parse_spec (gfc_statement st)
 {
   st_state ss;
+  bool function_result_typed = false;
   bool bad_characteristic = false;
   gfc_typespec *ts;
 
-  verify_st_order (&ss, ST_NONE);
+  verify_st_order (&ss, ST_NONE, false);
   if (st == ST_NONE)
     st = next_statement ();
 
+  /* If we are not inside a function or don't have a result specified so far,
+     do nothing special about it.  */
+  if (gfc_current_state () != COMP_FUNCTION)
+    function_result_typed = true;
+  else
+    {
+      gfc_symbol* proc = gfc_current_ns->proc_name;
+      gcc_assert (proc);
+
+      if (proc->result->ts.type == BT_UNKNOWN)
+       function_result_typed = true;
+    }
+
 loop:
+
+  /* If we're inside a BLOCK construct, some statements are disallowed.
+     Check this here.  Attribute declaration statements like INTENT, OPTIONAL
+     or VALUE are also disallowed, but they don't have a particular ST_*
+     key so we have to check for them individually in their matcher routine.  */
+  if (gfc_current_state () == COMP_BLOCK)
+    switch (st)
+      {
+       case ST_IMPLICIT:
+       case ST_IMPLICIT_NONE:
+       case ST_NAMELIST:
+       case ST_COMMON:
+       case ST_EQUIVALENCE:
+       case ST_STATEMENT_FUNCTION:
+         gfc_error ("%s statement is not allowed inside of BLOCK at %C",
+                    gfc_ascii_statement (st));
+         reject_statement ();
+         break;
+
+       default:
+         break;
+      }
+  
+  /* If we find a statement that can not be followed by an IMPLICIT statement
+     (and thus we can expect to see none any further), type the function result
+     if it has not yet been typed.  Be careful not to give the END statement
+     to verify_st_order!  */
+  if (!function_result_typed && st != ST_GET_FCN_CHARACTERISTICS)
+    {
+      bool verify_now = false;
+
+      if (st == ST_END_FUNCTION || st == ST_CONTAINS)
+       verify_now = true;
+      else
+       {
+         st_state dummyss;
+         verify_st_order (&dummyss, ST_NONE, false);
+         verify_st_order (&dummyss, st, false);
+
+         if (verify_st_order (&dummyss, ST_IMPLICIT, true) == FAILURE)
+           verify_now = true;
+       }
+
+      if (verify_now)
+       {
+         check_function_result_typed ();
+         function_result_typed = true;
+       }
+    }
+
   switch (st)
     {
     case ST_NONE:
       unexpected_eof ();
 
+    case ST_IMPLICIT_NONE:
+    case ST_IMPLICIT:
+      if (!function_result_typed)
+       {
+         check_function_result_typed ();
+         function_result_typed = true;
+       }
+      goto declSt;
+
     case ST_FORMAT:
     case ST_ENTRY:
     case ST_DATA:      /* Not allowed in interfaces */
@@ -2194,14 +2672,13 @@ loop:
 
     case ST_USE:
     case ST_IMPORT:
-    case ST_IMPLICIT_NONE:
-    case ST_IMPLICIT:
     case ST_PARAMETER:
     case ST_PUBLIC:
     case ST_PRIVATE:
     case ST_DERIVED_DECL:
     case_decl:
-      if (verify_st_order (&ss, st) == FAILURE)
+declSt:
+      if (verify_st_order (&ss, st, false) == FAILURE)
        {
          reject_statement ();
          st = next_statement ();
@@ -2224,6 +2701,7 @@ loop:
            {
              gfc_error ("%s statement must appear in a MODULE",
                         gfc_ascii_statement (st));
+             reject_statement ();
              break;
            }
 
@@ -2231,6 +2709,7 @@ loop:
            {
              gfc_error ("%s statement at %C follows another accessibility "
                         "specification", gfc_ascii_statement (st));
+             reject_statement ();
              break;
            }
 
@@ -2289,8 +2768,8 @@ loop:
 
       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;
+      if (!(ts->type == BT_DERIVED && ts->u.derived))
+       ts->type = BT_UNKNOWN;
     }
 
   return st;
@@ -2313,10 +2792,10 @@ parse_where_block (void)
   push_state (&s, COMP_WHERE, gfc_new_block);
 
   d = add_statement ();
-  d->expr = top->expr;
+  d->expr1 = top->expr1;
   d->op = EXEC_WHERE;
 
-  top->expr = NULL;
+  top->expr1 = NULL;
   top->block = d;
 
   seen_empty_else = 0;
@@ -2343,15 +2822,16 @@ parse_where_block (void)
            {
              gfc_error ("ELSEWHERE statement at %C follows previous "
                         "unmasked ELSEWHERE");
+             reject_statement ();
              break;
            }
 
-         if (new_st.expr == NULL)
+         if (new_st.expr1 == NULL)
            seen_empty_else = 1;
 
          d = new_level (gfc_state_stack->head);
          d->op = EXEC_WHERE;
-         d->expr = new_st.expr;
+         d->expr1 = new_st.expr1;
 
          accept_statement (st);
 
@@ -2456,8 +2936,8 @@ parse_if_block (void)
   new_st.op = EXEC_IF;
   d = add_statement ();
 
-  d->expr = top->expr;
-  top->expr = NULL;
+  d->expr1 = top->expr1;
+  top->expr1 = NULL;
   top->block = d;
 
   do
@@ -2481,7 +2961,7 @@ parse_if_block (void)
 
          d = new_level (gfc_state_stack->head);
          d->op = EXEC_IF;
-         d->expr = new_st.expr;
+         d->expr1 = new_st.expr1;
 
          accept_statement (st);
 
@@ -2596,6 +3076,93 @@ parse_select_block (void)
 }
 
 
+/* Pop the current selector from the SELECT TYPE stack.  */
+
+static void
+select_type_pop (void)
+{
+  gfc_select_type_stack *old = select_type_stack;
+  select_type_stack = old->prev;
+  free (old);
+}
+
+
+/* Parse a SELECT TYPE construct (F03:R821).  */
+
+static void
+parse_select_type_block (void)
+{
+  gfc_statement st;
+  gfc_code *cp;
+  gfc_state_data s;
+
+  accept_statement (ST_SELECT_TYPE);
+
+  cp = gfc_state_stack->tail;
+  push_state (&s, COMP_SELECT_TYPE, gfc_new_block);
+
+  /* Make sure that the next statement is a TYPE IS, CLASS IS, CLASS DEFAULT
+     or END SELECT.  */
+  for (;;)
+    {
+      st = next_statement ();
+      if (st == ST_NONE)
+       unexpected_eof ();
+      if (st == ST_END_SELECT)
+       /* Empty SELECT CASE is OK.  */
+       goto done;
+      if (st == ST_TYPE_IS || st == ST_CLASS_IS)
+       break;
+
+      gfc_error ("Expected TYPE IS, CLASS IS or END SELECT statement "
+                "following SELECT TYPE at %C");
+
+      reject_statement ();
+    }
+
+  /* At this point, we're got a nonempty select block.  */
+  cp = new_level (cp);
+  *cp = new_st;
+
+  accept_statement (st);
+
+  do
+    {
+      st = parse_executable (ST_NONE);
+      switch (st)
+       {
+       case ST_NONE:
+         unexpected_eof ();
+
+       case ST_TYPE_IS:
+       case ST_CLASS_IS:
+         cp = new_level (gfc_state_stack->head);
+         *cp = new_st;
+         gfc_clear_new_st ();
+
+         accept_statement (st);
+         /* Fall through */
+
+       case ST_END_SELECT:
+         break;
+
+       /* Can't have an executable statement because of
+          parse_executable().  */
+       default:
+         unexpected_statement (st);
+         break;
+       }
+    }
+  while (st != ST_END_SELECT);
+
+done:
+  pop_state ();
+  accept_statement (st);
+  gfc_current_ns = gfc_current_ns->parent;
+  select_type_pop ();
+}
+
+
 /* Given a symbol, make sure it is not an iteration variable for a DO
    statement.  This subroutine is called when the symbol is seen in a
    context that causes it to become redefined.  If the symbol is an
@@ -2631,7 +3198,7 @@ check_do_closure (void)
     return 0;
 
   for (p = gfc_state_stack; p; p = p->previous)
-    if (p->state == COMP_DO)
+    if (p->state == COMP_DO || p->state == COMP_DO_CONCURRENT)
       break;
 
   if (p == NULL)
@@ -2639,7 +3206,6 @@ check_do_closure (void)
 
   if (p->ext.end_do_label == gfc_statement_label)
     {
-
       if (p == gfc_state_stack)
        return 1;
 
@@ -2650,7 +3216,8 @@ check_do_closure (void)
   /* At this point, the label doesn't terminate the innermost loop.
      Make sure it doesn't terminate another one.  */
   for (; p; p = p->previous)
-    if (p->state == COMP_DO && p->ext.end_do_label == gfc_statement_label)
+    if ((p->state == COMP_DO || p->state == COMP_DO_CONCURRENT)
+       && p->ext.end_do_label == gfc_statement_label)
       {
        gfc_error ("End of nonblock DO statement at %C is interwoven "
                   "with another DO loop");
@@ -2661,6 +3228,199 @@ check_do_closure (void)
 }
 
 
+/* Parse a series of contained program units.  */
+
+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*
+gfc_build_block_ns (gfc_namespace *parent_ns)
+{
+  gfc_namespace* my_ns;
+  static int numblock = 1;
+
+  my_ns = gfc_get_namespace (parent_ns, 1);
+  my_ns->construct_entities = 1;
+
+  /* Give the BLOCK a symbol of flavor LABEL; this is later needed for correct
+     code generation (so it must not be NULL).
+     We set its recursive argument if our container procedure is recursive, so
+     that local variables are accordingly placed on the stack when it
+     will be necessary.  */
+  if (gfc_new_block)
+    my_ns->proc_name = gfc_new_block;
+  else
+    {
+      gfc_try t;
+      char buffer[20];  /* Enough to hold "block@2147483648\n".  */
+
+      snprintf(buffer, sizeof(buffer), "block@%d", numblock++);
+      gfc_get_symbol (buffer, my_ns, &my_ns->proc_name);
+      t = gfc_add_flavor (&my_ns->proc_name->attr, FL_LABEL,
+                         my_ns->proc_name->name, NULL);
+      gcc_assert (t == SUCCESS);
+      gfc_commit_symbol (my_ns->proc_name);
+    }
+
+  if (parent_ns->proc_name)
+    my_ns->proc_name->attr.recursive = parent_ns->proc_name->attr.recursive;
+
+  return my_ns;
+}
+
+
+/* Parse a BLOCK construct.  */
+
+static void
+parse_block_construct (void)
+{
+  gfc_namespace* my_ns;
+  gfc_state_data s;
+
+  gfc_notify_std (GFC_STD_F2008, "Fortran 2008: BLOCK construct at %C");
+
+  my_ns = gfc_build_block_ns (gfc_current_ns);
+
+  new_st.op = EXEC_BLOCK;
+  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);
+  gfc_current_ns = my_ns;
+
+  parse_progunit (ST_NONE);
+
+  gfc_current_ns = gfc_current_ns->parent;
+  pop_state ();
+}
+
+
+/* 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.  */
@@ -2672,8 +3432,10 @@ parse_do_block (void)
   gfc_code *top;
   gfc_state_data s;
   gfc_symtree *stree;
+  gfc_exec_op do_op;
 
-  s.ext.end_do_label = new_st.label;
+  do_op = new_st.op;
+  s.ext.end_do_label = new_st.label1;
 
   if (new_st.ext.iterator != NULL)
     stree = new_st.ext.iterator->var->symtree;
@@ -2683,7 +3445,8 @@ parse_do_block (void)
   accept_statement (ST_DO);
 
   top = gfc_state_stack->tail;
-  push_state (&s, COMP_DO, gfc_new_block);
+  push_state (&s, do_op == EXEC_DO_CONCURRENT ? COMP_DO_CONCURRENT : COMP_DO,
+             gfc_new_block);
 
   s.do_variable = stree;
 
@@ -2717,7 +3480,7 @@ loop:
        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_error_now ("Named block DO at %L requires matching ENDDO name",
                       &gfc_current_block()->declared_at);
 
       break;
@@ -2798,12 +3561,13 @@ parse_omp_do (gfc_statement omp_st)
 
 /* Parse the statements of OpenMP atomic directive.  */
 
-static void
+static gfc_statement
 parse_omp_atomic (void)
 {
   gfc_statement st;
   gfc_code *cp, *np;
   gfc_state_data s;
+  int count;
 
   accept_statement (ST_OMP_ATOMIC);
 
@@ -2812,21 +3576,35 @@ parse_omp_atomic (void)
   np = new_level (cp);
   np->op = cp->op;
   np->block = NULL;
+  count = 1 + (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE);
 
-  for (;;)
+  while (count)
     {
       st = next_statement ();
       if (st == ST_NONE)
        unexpected_eof ();
       else if (st == ST_ASSIGNMENT)
-       break;
+       {
+         accept_statement (st);
+         count--;
+       }
       else
        unexpected_statement (st);
     }
 
-  accept_statement (st);
-
   pop_state ();
+
+  st = next_statement ();
+  if (st == ST_OMP_END_ATOMIC)
+    {
+      gfc_clear_new_st ();
+      gfc_commit_symbols ();
+      gfc_warning_check ();
+      st = next_statement ();
+    }
+  else if (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE)
+    gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
+  return st;
 }
 
 
@@ -2936,8 +3714,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
                  continue;
 
                case ST_OMP_ATOMIC:
-                 parse_omp_atomic ();
-                 break;
+                 st = parse_omp_atomic ();
+                 continue;
 
                default:
                  cycle = false;
@@ -2978,7 +3756,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
              && 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_free (CONST_CAST (char *, new_st.ext.omp_name));
+      free (CONST_CAST (char *, new_st.ext.omp_name));
       break;
     case EXEC_OMP_END_SINGLE:
       cp->ext.omp_clauses->lists[OMP_LIST_COPYPRIVATE]
@@ -3026,6 +3804,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:
@@ -3054,6 +3833,14 @@ parse_executable (gfc_statement st)
            return ST_IMPLIED_ENDDO;
          break;
 
+       case ST_BLOCK:
+         parse_block_construct ();
+         break;
+
+       case ST_ASSOCIATE:
+         parse_associate ();
+         break;
+
        case ST_IF_BLOCK:
          parse_if_block ();
          break;
@@ -3062,12 +3849,20 @@ parse_executable (gfc_statement st)
          parse_select_block ();
          break;
 
+       case ST_SELECT_TYPE:
+         parse_select_type_block();
+         break;
+
        case ST_DO:
          parse_do_block ();
          if (check_do_closure () == 1)
            return ST_IMPLIED_ENDDO;
          break;
 
+       case ST_CRITICAL:
+         parse_critical_block ();
+         break;
+
        case ST_WHERE_BLOCK:
          parse_where_block ();
          break;
@@ -3100,8 +3895,8 @@ parse_executable (gfc_statement st)
          continue;
 
        case ST_OMP_ATOMIC:
-         parse_omp_atomic ();
-         break;
+         st = parse_omp_atomic ();
+         continue;
 
        default:
          return st;
@@ -3112,11 +3907,6 @@ parse_executable (gfc_statement st)
 }
 
 
-/* Parse a series of contained program units.  */
-
-static void parse_progunit (gfc_statement);
-
-
 /* Fix the symbols for sibling functions.  These are incorrectly added to
    the child namespace as the parser didn't know about this procedure.  */
 
@@ -3130,10 +3920,16 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
   sym->attr.referenced = 1;
   for (ns = siblings; ns; ns = ns->sibling)
     {
-      gfc_find_sym_tree (sym->name, ns, 0, &st);
+      st = gfc_find_symtree (ns->sym_root, sym->name);
 
       if (!st || (st->n.sym->attr.dummy && ns == st->n.sym->ns))
-       continue;
+       goto fixup_contained;
+
+      if ((st->n.sym->attr.flavor == FL_DERIVED
+          && sym->attr.generic && sym->attr.function)
+         ||(sym->attr.flavor == FL_DERIVED
+            && st->n.sym->attr.generic && st->n.sym->attr.function))
+       goto fixup_contained;
 
       old_sym = st->n.sym;
       if (old_sym->ns == ns
@@ -3145,6 +3941,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
@@ -3155,18 +3952,17 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
                  || old_sym->attr.intrinsic
                  || old_sym->attr.generic
                  || old_sym->attr.flavor == FL_NAMELIST
+                 || old_sym->attr.flavor == FL_LABEL
                  || old_sym->attr.proc == PROC_ST_FUNCTION))
        {
          /* 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);
+         gfc_release_symbol (old_sym);
        }
 
+fixup_contained:
       /* Do the same for any contained procedures.  */
       gfc_fixup_sibling_symbols (sym, ns->contained);
     }
@@ -3245,6 +4041,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.  */
@@ -3297,7 +4099,7 @@ parse_contained (int module)
 }
 
 
-/* Parse a PROGRAM, SUBROUTINE or FUNCTION unit.  */
+/* Parse a PROGRAM, SUBROUTINE, FUNCTION unit or BLOCK construct.  */
 
 static void
 parse_progunit (gfc_statement st)
@@ -3312,7 +4114,10 @@ parse_progunit (gfc_statement st)
       unexpected_eof ();
 
     case ST_CONTAINS:
-      goto contains;
+      /* This is not allowed within BLOCK!  */
+      if (gfc_current_state () != COMP_BLOCK)
+       goto contains;
+      break;
 
     case_end:
       accept_statement (st);
@@ -3336,7 +4141,10 @@ loop:
          unexpected_eof ();
 
        case ST_CONTAINS:
-         goto contains;
+         /* This is not allowed within BLOCK!  */
+         if (gfc_current_state () != COMP_BLOCK)
+           goto contains;
+         break;
 
        case_end:
          accept_statement (st);
@@ -3365,6 +4173,7 @@ contains:
     {
       gfc_error ("CONTAINS statement at %C is already in a contained "
                 "program unit");
+      reject_statement ();
       st = next_statement ();
       goto loop;
     }
@@ -3408,7 +4217,7 @@ gfc_global_used (gfc_gsymbol *sym, locus *where)
       name = "MODULE";
       break;
     default:
-      gfc_internal_error ("gfc_gsymbol_type(): Bad type");
+      gfc_internal_error ("gfc_global_used(): Bad type");
       name = NULL;
     }
 
@@ -3509,6 +4318,8 @@ loop:
       st = next_statement ();
       goto loop;
     }
+
+  s->ns = gfc_current_ns;
 }
 
 
@@ -3530,6 +4341,7 @@ add_global_procedure (int sub)
       s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
       s->where = gfc_current_locus;
       s->defined = 1;
+      s->ns = gfc_current_ns;
     }
 }
 
@@ -3552,19 +4364,131 @@ add_global_program (void)
       s->type = GSYM_PROGRAM;
       s->where = gfc_current_locus;
       s->defined = 1;
+      s->ns = gfc_current_ns;
+    }
+}
+
+
+/* Resolve all the program units when whole file scope option
+   is active. */
+static void
+resolve_all_program_units (gfc_namespace *gfc_global_ns_list)
+{
+  gfc_free_dt_list ();
+  gfc_current_ns = gfc_global_ns_list;
+  for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
+    {
+      if (gfc_current_ns->proc_name
+         && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
+       continue; /* Already resolved.  */
+
+      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;
+    }
+}
+
+
+static void
+clean_up_modules (gfc_gsymbol *gsym)
+{
+  if (gsym == NULL)
+    return;
+
+  clean_up_modules (gsym->left);
+  clean_up_modules (gsym->right);
+
+  if (gsym->type != GSYM_MODULE || !gsym->ns)
+    return;
+
+  gfc_current_ns = gsym->ns;
+  gfc_derived_types = gfc_current_ns->derived_types;
+  gfc_done_2 ();
+  gsym->ns = NULL;
+  return;
+}
+
+
+/* Translate all the program units when whole file scope option
+   is active. This could be in a different order to resolution if
+   there are forward references in the file.  */
+static void
+translate_all_program_units (gfc_namespace *gfc_global_ns_list,
+                            bool main_in_tu)
+{
+  int errors;
+
+  gfc_current_ns = gfc_global_ns_list;
+  gfc_get_errors (NULL, &errors);
+
+  /* If the main program is in the translation unit and we have
+     -fcoarray=libs, generate the static variables.  */
+  if (gfc_option.coarray == GFC_FCOARRAY_LIB && main_in_tu)
+    gfc_init_coarray_decl (true);
+
+  /* We first translate all modules to make sure that later parts
+     of the program can use the decl. Then we translate the nonmodules.  */
+
+  for (; !errors && gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
+    {
+      if (!gfc_current_ns->proc_name
+         || gfc_current_ns->proc_name->attr.flavor != FL_MODULE)
+       continue;
+
+      gfc_current_locus = gfc_current_ns->proc_name->declared_at;
+      gfc_derived_types = gfc_current_ns->derived_types;
+      gfc_generate_module_code (gfc_current_ns);
+      gfc_current_ns->translated = 1;
+    }
+
+  gfc_current_ns = gfc_global_ns_list;
+  for (; !errors && gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
+    {
+      if (gfc_current_ns->proc_name
+         && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
+       continue;
+
+      gfc_current_locus = gfc_current_ns->proc_name->declared_at;
+      gfc_derived_types = gfc_current_ns->derived_types;
+      gfc_generate_code (gfc_current_ns);
+      gfc_current_ns->translated = 1;
+    }
+
+  /* Clean up all the namespaces after translation.  */
+  gfc_current_ns = gfc_global_ns_list;
+  for (;gfc_current_ns;)
+    {
+      gfc_namespace *ns;
+
+      if (gfc_current_ns->proc_name
+         && gfc_current_ns->proc_name->attr.flavor == FL_MODULE)
+       {
+         gfc_current_ns = gfc_current_ns->sibling;
+         continue;
+       }
+
+      ns = gfc_current_ns->sibling;
+      gfc_derived_types = gfc_current_ns->derived_types;
+      gfc_done_2 ();
+      gfc_current_ns = ns;
     }
+
+  clean_up_modules (gfc_gsym_root);
 }
 
 
 /* Top level parser.  */
 
-try
+gfc_try
 gfc_parse_file (void)
 {
   int seen_program, errors_before, errors;
   gfc_state_data top, s;
   gfc_statement st;
   locus prog_locus;
+  gfc_namespace *next;
 
   gfc_start_source_files ();
 
@@ -3583,6 +4507,10 @@ gfc_parse_file (void)
   if (setjmp (eof_buf))
     return FAILURE;    /* Come here on unexpected EOF */
 
+  /* Prepare the global namespace that will contain the
+     program units.  */
+  gfc_global_ns_list = next = NULL;
+
   seen_program = 0;
 
   /* Exit early for empty files.  */
@@ -3609,6 +4537,8 @@ loop:
       accept_statement (st);
       add_global_program ();
       parse_progunit (ST_NONE);
+      if (gfc_option.flag_whole_file)
+       goto prog_units;
       break;
 
     case ST_SUBROUTINE:
@@ -3616,6 +4546,8 @@ loop:
       push_state (&s, COMP_SUBROUTINE, gfc_new_block);
       accept_statement (st);
       parse_progunit (ST_NONE);
+      if (gfc_option.flag_whole_file)
+       goto prog_units;
       break;
 
     case ST_FUNCTION:
@@ -3623,6 +4555,8 @@ loop:
       push_state (&s, COMP_FUNCTION, gfc_new_block);
       accept_statement (st);
       parse_progunit (ST_NONE);
+      if (gfc_option.flag_whole_file)
+       goto prog_units;
       break;
 
     case ST_BLOCK_DATA:
@@ -3649,41 +4583,98 @@ loop:
       push_state (&s, COMP_PROGRAM, gfc_new_block);
       main_program_symbol (gfc_current_ns, "MAIN__");
       parse_progunit (st);
+      if (gfc_option.flag_whole_file)
+       goto prog_units;
       break;
     }
 
+  /* Handle the non-program units.  */
   gfc_current_ns->code = s.head;
 
   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);
   if (s.state == COMP_MODULE)
     {
       gfc_dump_module (s.sym->name, errors_before == errors);
-      if (errors == 0)
-       gfc_generate_module_code (gfc_current_ns);
+      if (!gfc_option.flag_whole_file)
+       {
+         if (errors == 0)
+           gfc_generate_module_code (gfc_current_ns);
+         pop_state ();
+         gfc_done_2 ();
+       }
+      else
+       {
+         gfc_current_ns->derived_types = gfc_derived_types;
+         gfc_derived_types = NULL;
+         goto prog_units;
+       }
     }
   else
     {
       if (errors == 0)
        gfc_generate_code (gfc_current_ns);
+      pop_state ();
+      gfc_done_2 ();
+    }
+
+  goto loop;
+
+prog_units:
+  /* The main program and non-contained procedures are put
+     in the global namespace list, so that they can be processed
+     later and all their interfaces resolved.  */
+  gfc_current_ns->code = s.head;
+  if (next)
+    {
+      for (; next->sibling; next = next->sibling)
+       ;
+      next->sibling = gfc_current_ns;
     }
+  else
+    gfc_global_ns_list = gfc_current_ns;
+
+  next = gfc_current_ns;
 
   pop_state ();
-  gfc_done_2 ();
   goto loop;
 
-done:
+  done:
+
+  if (!gfc_option.flag_whole_file)
+    goto termination;
+
+  /* Do the resolution.  */
+  resolve_all_program_units (gfc_global_ns_list);
+
+  /* Do the parse tree dump.  */ 
+  gfc_current_ns
+       = gfc_option.dump_fortran_original ? gfc_global_ns_list : NULL;
+
+  for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
+    if (!gfc_current_ns->proc_name
+       || gfc_current_ns->proc_name->attr.flavor != FL_MODULE)
+      {
+       gfc_dump_parse_tree (gfc_current_ns, stdout);
+       fputs ("------------------------------------------\n\n", stdout);
+      }
+
+  /* Do the translation.  */
+  translate_all_program_units (gfc_global_ns_list, seen_program);
+
+termination:
+
   gfc_end_source_files ();
   return SUCCESS;
 
 duplicate_main:
   /* If we see a duplicate main program, shut down.  If the second
-     instance is an implied main program, ie data decls or executable
+     instance is an implied main program, i.e. data decls or executable
      statements, we're in for lots of errors.  */
   gfc_error ("Two main PROGRAMs at %L and %C", &prog_locus);
   reject_statement ();