re PR fortran/44054 (Handle -Werror, -Werror=, -fdiagnostics-show-option, !GCC$ diagn...
[gcc.git] / gcc / fortran / parse.c
index 7b887bc1e39adc126036c925a61332977b189840..56c67826dbe27033468d4896565cbccfe3bf2782 100644 (file)
@@ -1,7 +1,5 @@
 /* Main parser.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-   2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2000-2015 Free Software Foundation, Inc.
    Contributed by Andy Vaught
 
 This file is part of GCC.
@@ -23,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include <setjmp.h>
+#include "coretypes.h"
+#include "flags.h"
 #include "gfortran.h"
 #include "match.h"
 #include "parse.h"
@@ -37,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);
@@ -74,16 +75,65 @@ match_word (const char *str, match (*subr) (void), locus *old_locus)
 }
 
 
+/* Like match_word, but if str is matched, set a flag that it
+   was matched.  */
+static match
+match_word_omp_simd (const char *str, match (*subr) (void), locus *old_locus,
+                    bool *simd_matched)
+{
+  match m;
+
+  if (str != NULL)
+    {
+      m = gfc_match (str);
+      if (m != MATCH_YES)
+       return m;
+      *simd_matched = true;
+    }
+
+  m = (*subr) ();
+
+  if (m != MATCH_YES)
+    {
+      gfc_current_locus = *old_locus;
+      reject_statement ();
+    }
+
+  return m;
+}
+
+
+/* Load symbols from all USE statements encountered in this scoping unit.  */
+
+static void
+use_modules (void)
+{
+  gfc_error_buffer old_error;
+
+  gfc_push_error (&old_error);
+  gfc_buffer_error (false);
+  gfc_use_modules ();
+  gfc_buffer_error (true);
+  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;
+  gfc_current_ns->old_data = gfc_current_ns->data;
+  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.  */
 
 #define match(keyword, subr, st)                               \
     do {                                                       \
-      if (match_word(keyword, subr, &old_locus) == MATCH_YES)  \
+      if (match_word (keyword, subr, &old_locus) == MATCH_YES) \
        return st;                                              \
       else                                                     \
-       undo_new_statement ();                            \
+       undo_new_statement ();                                  \
     } while (0);
 
 
@@ -108,8 +158,19 @@ 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 ()->result->ts.type != BT_DERIVED)
     goto end_of_block;
@@ -129,7 +190,7 @@ decode_specification_statement (void)
     case 'a':
       match ("abstract% interface", gfc_match_abstract_interface,
             ST_INTERFACE);
-      match ("allocatable", gfc_match_asynchronous, ST_ATTR_DECL);
+      match ("allocatable", gfc_match_allocatable, ST_ATTR_DECL);
       match ("asynchronous", gfc_match_asynchronous, ST_ATTR_DECL);
       break;
 
@@ -139,6 +200,7 @@ decode_specification_statement (void)
 
     case 'c':
       match ("codimension", gfc_match_codimension, ST_ATTR_DECL);
+      match ("contiguous", gfc_match_contiguous, ST_ATTR_DECL);
       break;
 
     case 'd':
@@ -219,7 +281,7 @@ decode_specification_statement (void)
 
 end_of_block:
   gfc_clear_error ();
-  gfc_buffer_error (0);
+  gfc_buffer_error (false);
   gfc_current_locus = old_locus;
 
   return ST_GET_FCN_CHARACTERISTICS;
@@ -230,14 +292,13 @@ end_of_block:
 static gfc_statement
 decode_statement (void)
 {
+  gfc_namespace *ns;
   gfc_statement st;
   locus old_locus;
   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.  */
@@ -253,6 +314,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.  */
@@ -317,14 +394,17 @@ decode_statement (void)
   match (NULL, gfc_match_associate, ST_ASSOCIATE);
   match (NULL, gfc_match_critical, ST_CRITICAL);
   match (NULL, gfc_match_select, ST_SELECT_CASE);
+
+  gfc_current_ns = gfc_build_block_ns (gfc_current_ns);
   match (NULL, gfc_match_select_type, ST_SELECT_TYPE);
+  ns = gfc_current_ns;
+  gfc_current_ns = gfc_current_ns->parent;
+  gfc_free_namespace (ns);
 
   /* 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':
@@ -346,6 +426,7 @@ 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);
@@ -398,8 +479,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;
 
@@ -449,7 +534,7 @@ decode_statement (void)
       break;
 
     case 'u':
-      match ("use", gfc_match_use, ST_USE);
+      match ("unlock", gfc_match_unlock, ST_UNLOCK);
       break;
 
     case 'v':
@@ -466,7 +551,7 @@ decode_statement (void)
   /* 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)
+  if (!gfc_error_check ())
     gfc_error_now ("Unclassifiable statement at %C");
 
   reject_statement ();
@@ -476,15 +561,123 @@ decode_statement (void)
   return ST_NONE;
 }
 
+/* Like match, but set a flag simd_matched if keyword matched.  */
+#define matchs(keyword, subr, st)                              \
+    do {                                                       \
+      if (match_word_omp_simd (keyword, subr, &old_locus,      \
+                              &simd_matched) == MATCH_YES)     \
+       return st;                                              \
+      else                                                     \
+       undo_new_statement ();                                  \
+    } while (0);
+
+/* Like match, but don't match anything if not -fopenmp.  */
+#define matcho(keyword, subr, st)                              \
+    do {                                                       \
+      if (!flag_openmp)                                                \
+       ;                                                       \
+      else if (match_word (keyword, subr, &old_locus)          \
+              == MATCH_YES)                                    \
+       return st;                                              \
+      else                                                     \
+       undo_new_statement ();                                  \
+    } while (0);
+
+static gfc_statement
+decode_oacc_directive (void)
+{
+  locus old_locus;
+  char c;
+
+  gfc_enforce_clean_symbol_state ();
+
+  gfc_clear_error ();   /* Clear any pending errors.  */
+  gfc_clear_warning (); /* Clear any pending warnings.  */
+
+  if (gfc_pure (NULL))
+    {
+      gfc_error_now ("OpenACC directives at %C may not appear in PURE "
+                    "procedures");
+      gfc_error_recovery ();
+      return ST_NONE;
+    }
+
+  gfc_unset_implicit_pure (NULL);
+
+  old_locus = gfc_current_locus;
+
+  /* General OpenACC directive 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 'c':
+      match ("cache", gfc_match_oacc_cache, ST_OACC_CACHE);
+      break;
+    case 'd':
+      match ("data", gfc_match_oacc_data, ST_OACC_DATA);
+      match ("declare", gfc_match_oacc_declare, ST_OACC_DECLARE);
+      break;
+    case 'e':
+      match ("end data", gfc_match_omp_eos, ST_OACC_END_DATA);
+      match ("end host_data", gfc_match_omp_eos, ST_OACC_END_HOST_DATA);
+      match ("end kernels loop", gfc_match_omp_eos, ST_OACC_END_KERNELS_LOOP);
+      match ("end kernels", gfc_match_omp_eos, ST_OACC_END_KERNELS);
+      match ("end loop", gfc_match_omp_eos, ST_OACC_END_LOOP);
+      match ("end parallel loop", gfc_match_omp_eos, ST_OACC_END_PARALLEL_LOOP);
+      match ("end parallel", gfc_match_omp_eos, ST_OACC_END_PARALLEL);
+      match ("enter data", gfc_match_oacc_enter_data, ST_OACC_ENTER_DATA);
+      match ("exit data", gfc_match_oacc_exit_data, ST_OACC_EXIT_DATA);
+      break;
+    case 'h':
+      match ("host_data", gfc_match_oacc_host_data, ST_OACC_HOST_DATA);
+      break;
+    case 'p':
+      match ("parallel loop", gfc_match_oacc_parallel_loop, ST_OACC_PARALLEL_LOOP);
+      match ("parallel", gfc_match_oacc_parallel, ST_OACC_PARALLEL);
+      break;
+    case 'k':
+      match ("kernels loop", gfc_match_oacc_kernels_loop, ST_OACC_KERNELS_LOOP);
+      match ("kernels", gfc_match_oacc_kernels, ST_OACC_KERNELS);
+      break;
+    case 'l':
+      match ("loop", gfc_match_oacc_loop, ST_OACC_LOOP);
+      break;
+    case 'r':
+      match ("routine", gfc_match_oacc_routine, ST_OACC_ROUTINE);
+      break;
+    case 'u':
+      match ("update", gfc_match_oacc_update, ST_OACC_UPDATE);
+      break;
+    case 'w':
+      match ("wait", gfc_match_oacc_wait, ST_OACC_WAIT);
+      break;
+    }
+
+  /* Directive not found or stored an error message.
+     Check and give up.  */
+
+  if (gfc_error_check () == 0)
+    gfc_error_now ("Unclassifiable OpenACC directive at %C");
+
+  reject_statement ();
+
+  gfc_error_recovery ();
+
+  return ST_NONE;
+}
+
 static gfc_statement
 decode_omp_directive (void)
 {
   locus old_locus;
   char c;
+  bool simd_matched = false;
 
-#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.  */
@@ -497,6 +690,8 @@ decode_omp_directive (void)
       return ST_NONE;
     }
 
+  gfc_unset_implicit_pure (NULL);
+
   old_locus = gfc_current_locus;
 
   /* General OpenMP directive matching: Instead of testing every possible
@@ -505,74 +700,167 @@ decode_omp_directive (void)
 
   c = gfc_peek_ascii_char ();
 
+  /* match is for directives that should be recognized only if
+     -fopenmp, matchs for directives that should be recognized
+     if either -fopenmp or -fopenmp-simd.  */
   switch (c)
     {
     case 'a':
-      match ("atomic", gfc_match_omp_atomic, ST_OMP_ATOMIC);
+      matcho ("atomic", gfc_match_omp_atomic, ST_OMP_ATOMIC);
       break;
     case 'b':
-      match ("barrier", gfc_match_omp_barrier, ST_OMP_BARRIER);
+      matcho ("barrier", gfc_match_omp_barrier, ST_OMP_BARRIER);
       break;
     case 'c':
-      match ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL);
+      matcho ("cancellation% point", gfc_match_omp_cancellation_point,
+             ST_OMP_CANCELLATION_POINT);
+      matcho ("cancel", gfc_match_omp_cancel, ST_OMP_CANCEL);
+      matcho ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL);
       break;
     case 'd':
-      match ("do", gfc_match_omp_do, ST_OMP_DO);
+      matchs ("declare reduction", gfc_match_omp_declare_reduction,
+             ST_OMP_DECLARE_REDUCTION);
+      matchs ("declare simd", gfc_match_omp_declare_simd,
+             ST_OMP_DECLARE_SIMD);
+      matcho ("declare target", gfc_match_omp_declare_target,
+             ST_OMP_DECLARE_TARGET);
+      matchs ("distribute parallel do simd",
+             gfc_match_omp_distribute_parallel_do_simd,
+             ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD);
+      matcho ("distribute parallel do", gfc_match_omp_distribute_parallel_do,
+             ST_OMP_DISTRIBUTE_PARALLEL_DO);
+      matchs ("distribute simd", gfc_match_omp_distribute_simd,
+             ST_OMP_DISTRIBUTE_SIMD);
+      matcho ("distribute", gfc_match_omp_distribute, ST_OMP_DISTRIBUTE);
+      matchs ("do simd", gfc_match_omp_do_simd, ST_OMP_DO_SIMD);
+      matcho ("do", gfc_match_omp_do, ST_OMP_DO);
       break;
     case 'e':
-      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);
-      match ("end ordered", gfc_match_omp_eos, ST_OMP_END_ORDERED);
-      match ("end parallel do", gfc_match_omp_eos, ST_OMP_END_PARALLEL_DO);
-      match ("end parallel sections", gfc_match_omp_eos,
-            ST_OMP_END_PARALLEL_SECTIONS);
-      match ("end parallel workshare", gfc_match_omp_eos,
-            ST_OMP_END_PARALLEL_WORKSHARE);
-      match ("end parallel", gfc_match_omp_eos, ST_OMP_END_PARALLEL);
-      match ("end sections", gfc_match_omp_end_nowait, ST_OMP_END_SECTIONS);
-      match ("end single", gfc_match_omp_end_single, ST_OMP_END_SINGLE);
-      match ("end task", gfc_match_omp_eos, ST_OMP_END_TASK);
-      match ("end workshare", gfc_match_omp_end_nowait,
-            ST_OMP_END_WORKSHARE);
+      matcho ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC);
+      matcho ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL);
+      matchs ("end distribute parallel do simd", gfc_match_omp_eos,
+             ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD);
+      matcho ("end distribute parallel do", gfc_match_omp_eos,
+             ST_OMP_END_DISTRIBUTE_PARALLEL_DO);
+      matchs ("end distribute simd", gfc_match_omp_eos,
+             ST_OMP_END_DISTRIBUTE_SIMD);
+      matcho ("end distribute", gfc_match_omp_eos, ST_OMP_END_DISTRIBUTE);
+      matchs ("end do simd", gfc_match_omp_end_nowait, ST_OMP_END_DO_SIMD);
+      matcho ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO);
+      matchs ("end simd", gfc_match_omp_eos, ST_OMP_END_SIMD);
+      matcho ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER);
+      matcho ("end ordered", gfc_match_omp_eos, ST_OMP_END_ORDERED);
+      matchs ("end parallel do simd", gfc_match_omp_eos,
+             ST_OMP_END_PARALLEL_DO_SIMD);
+      matcho ("end parallel do", gfc_match_omp_eos, ST_OMP_END_PARALLEL_DO);
+      matcho ("end parallel sections", gfc_match_omp_eos,
+             ST_OMP_END_PARALLEL_SECTIONS);
+      matcho ("end parallel workshare", gfc_match_omp_eos,
+             ST_OMP_END_PARALLEL_WORKSHARE);
+      matcho ("end parallel", gfc_match_omp_eos, ST_OMP_END_PARALLEL);
+      matcho ("end sections", gfc_match_omp_end_nowait, ST_OMP_END_SECTIONS);
+      matcho ("end single", gfc_match_omp_end_single, ST_OMP_END_SINGLE);
+      matcho ("end target data", gfc_match_omp_eos, ST_OMP_END_TARGET_DATA);
+      matchs ("end target teams distribute parallel do simd",
+             gfc_match_omp_eos,
+             ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
+      matcho ("end target teams distribute parallel do", gfc_match_omp_eos,
+             ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO);
+      matchs ("end target teams distribute simd", gfc_match_omp_eos,
+             ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD);
+      matcho ("end target teams distribute", gfc_match_omp_eos,
+             ST_OMP_END_TARGET_TEAMS_DISTRIBUTE);
+      matcho ("end target teams", gfc_match_omp_eos, ST_OMP_END_TARGET_TEAMS);
+      matcho ("end target", gfc_match_omp_eos, ST_OMP_END_TARGET);
+      matcho ("end taskgroup", gfc_match_omp_eos, ST_OMP_END_TASKGROUP);
+      matcho ("end task", gfc_match_omp_eos, ST_OMP_END_TASK);
+      matchs ("end teams distribute parallel do simd", gfc_match_omp_eos,
+             ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
+      matcho ("end teams distribute parallel do", gfc_match_omp_eos,
+             ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO);
+      matchs ("end teams distribute simd", gfc_match_omp_eos,
+             ST_OMP_END_TEAMS_DISTRIBUTE_SIMD);
+      matcho ("end teams distribute", gfc_match_omp_eos,
+             ST_OMP_END_TEAMS_DISTRIBUTE);
+      matcho ("end teams", gfc_match_omp_eos, ST_OMP_END_TEAMS);
+      matcho ("end workshare", gfc_match_omp_end_nowait,
+             ST_OMP_END_WORKSHARE);
       break;
     case 'f':
-      match ("flush", gfc_match_omp_flush, ST_OMP_FLUSH);
+      matcho ("flush", gfc_match_omp_flush, ST_OMP_FLUSH);
       break;
     case 'm':
-      match ("master", gfc_match_omp_master, ST_OMP_MASTER);
+      matcho ("master", gfc_match_omp_master, ST_OMP_MASTER);
       break;
     case 'o':
-      match ("ordered", gfc_match_omp_ordered, ST_OMP_ORDERED);
+      matcho ("ordered", gfc_match_omp_ordered, ST_OMP_ORDERED);
       break;
     case 'p':
-      match ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO);
-      match ("parallel sections", gfc_match_omp_parallel_sections,
-            ST_OMP_PARALLEL_SECTIONS);
-      match ("parallel workshare", gfc_match_omp_parallel_workshare,
-            ST_OMP_PARALLEL_WORKSHARE);
-      match ("parallel", gfc_match_omp_parallel, ST_OMP_PARALLEL);
+      matchs ("parallel do simd", gfc_match_omp_parallel_do_simd,
+             ST_OMP_PARALLEL_DO_SIMD);
+      matcho ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO);
+      matcho ("parallel sections", gfc_match_omp_parallel_sections,
+             ST_OMP_PARALLEL_SECTIONS);
+      matcho ("parallel workshare", gfc_match_omp_parallel_workshare,
+             ST_OMP_PARALLEL_WORKSHARE);
+      matcho ("parallel", gfc_match_omp_parallel, ST_OMP_PARALLEL);
       break;
     case 's':
-      match ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS);
-      match ("section", gfc_match_omp_eos, ST_OMP_SECTION);
-      match ("single", gfc_match_omp_single, ST_OMP_SINGLE);
+      matcho ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS);
+      matcho ("section", gfc_match_omp_eos, ST_OMP_SECTION);
+      matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD);
+      matcho ("single", gfc_match_omp_single, ST_OMP_SINGLE);
       break;
     case 't':
-      match ("task", gfc_match_omp_task, ST_OMP_TASK);
-      match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
-      match ("threadprivate", gfc_match_omp_threadprivate,
-            ST_OMP_THREADPRIVATE);
+      matcho ("target data", gfc_match_omp_target_data, ST_OMP_TARGET_DATA);
+      matchs ("target teams distribute parallel do simd",
+             gfc_match_omp_target_teams_distribute_parallel_do_simd,
+             ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
+      matcho ("target teams distribute parallel do",
+             gfc_match_omp_target_teams_distribute_parallel_do,
+             ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO);
+      matchs ("target teams distribute simd",
+             gfc_match_omp_target_teams_distribute_simd,
+             ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD);
+      matcho ("target teams distribute", gfc_match_omp_target_teams_distribute,
+             ST_OMP_TARGET_TEAMS_DISTRIBUTE);
+      matcho ("target teams", gfc_match_omp_target_teams, ST_OMP_TARGET_TEAMS);
+      matcho ("target update", gfc_match_omp_target_update,
+             ST_OMP_TARGET_UPDATE);
+      matcho ("target", gfc_match_omp_target, ST_OMP_TARGET);
+      matcho ("taskgroup", gfc_match_omp_taskgroup, ST_OMP_TASKGROUP);
+      matcho ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
+      matcho ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD);
+      matcho ("task", gfc_match_omp_task, ST_OMP_TASK);
+      matchs ("teams distribute parallel do simd",
+             gfc_match_omp_teams_distribute_parallel_do_simd,
+             ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD);
+      matcho ("teams distribute parallel do",
+             gfc_match_omp_teams_distribute_parallel_do,
+             ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO);
+      matchs ("teams distribute simd", gfc_match_omp_teams_distribute_simd,
+             ST_OMP_TEAMS_DISTRIBUTE_SIMD);
+      matcho ("teams distribute", gfc_match_omp_teams_distribute,
+             ST_OMP_TEAMS_DISTRIBUTE);
+      matcho ("teams", gfc_match_omp_teams, ST_OMP_TEAMS);
+      matcho ("threadprivate", gfc_match_omp_threadprivate,
+             ST_OMP_THREADPRIVATE);
+      break;
     case 'w':
-      match ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE);
+      matcho ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE);
       break;
     }
 
   /* All else has failed, so give up.  See if any of the matchers has
-     stored an error message of some sort.  */
+     stored an error message of some sort.  Don't error out if
+     not -fopenmp and simd_matched is false, i.e. if a directive other
+     than one marked with match has been seen.  */
 
-  if (gfc_error_check () == 0)
-    gfc_error_now ("Unclassifiable OpenMP directive at %C");
+  if (flag_openmp || simd_matched)
+    {
+      if (!gfc_error_check ())
+       gfc_error_now ("Unclassifiable OpenMP directive at %C");
+    }
 
   reject_statement ();
 
@@ -586,9 +874,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.  */
@@ -599,7 +885,7 @@ decode_gcc_attribute (void)
   /* 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)
+  if (!gfc_error_check ())
     gfc_error_now ("Unclassifiable GCC directive at %C");
 
   reject_statement ();
@@ -611,6 +897,23 @@ decode_gcc_attribute (void)
 
 #undef match
 
+/* Assert next length characters to be equal to token in free form.  */
+
+static void 
+verify_token_free (const char* token, int length, bool last_was_use_stmt)
+{
+  int i;
+  char c;
+
+  c = gfc_next_ascii_char ();
+  for (i = 0; i < length; i++, c = gfc_next_ascii_char ())
+    gcc_assert (c == token[i]);
+
+  gcc_assert (gfc_is_whitespace(c));
+  gfc_gobble_whitespace ();
+  if (last_was_use_stmt)
+    use_modules ();
+}
 
 /* Get the next statement in free form source.  */
 
@@ -669,7 +972,7 @@ next_free (void)
 
          if (gfc_match_eos () == MATCH_YES)
            {
-             gfc_warning_now ("Ignoring statement label in empty statement "
+             gfc_warning_now (0, "Ignoring statement label in empty statement "
                               "at %L", &label_locus);
              gfc_free_st_label (gfc_statement_label);
              gfc_statement_label = NULL;
@@ -680,7 +983,7 @@ next_free (void)
   else if (c == '!')
     {
       /* Comments have already been skipped by the time we get here,
-        except for GCC attributes and OpenMP directives.  */
+        except for GCC attributes and OpenMP/OpenACC directives.  */
 
       gfc_next_ascii_char (); /* Eat up the exclamation sign.  */
       c = gfc_peek_ascii_char ();
@@ -697,25 +1000,47 @@ next_free (void)
          return decode_gcc_attribute ();
 
        }
-      else if (c == '$' && gfc_option.flag_openmp)
+      else if (c == '$')
        {
-         int i;
-
-         c = gfc_next_ascii_char ();
-         for (i = 0; i < 4; i++, c = gfc_next_ascii_char ())
-           gcc_assert (c == "$omp"[i]);
+         /* Since both OpenMP and OpenACC directives starts with 
+            !$ character sequence, we must check all flags combinations */
+         if ((flag_openmp || flag_openmp_simd)
+             && !flag_openacc)
+           {
+             verify_token_free ("$omp", 4, last_was_use_stmt);
+             return decode_omp_directive ();
+           }
+         else if ((flag_openmp || flag_openmp_simd)
+                  && flag_openacc)
+           {
+             gfc_next_ascii_char (); /* Eat up dollar character */
+             c = gfc_peek_ascii_char ();
 
-         gcc_assert (c == ' ' || c == '\t');
-         gfc_gobble_whitespace ();
-         return decode_omp_directive ();
+             if (c == 'o')
+               {
+                 verify_token_free ("omp", 3, last_was_use_stmt);
+                 return decode_omp_directive ();
+               }
+             else if (c == 'a')
+               {
+                 verify_token_free ("acc", 3, last_was_use_stmt);
+                 return decode_oacc_directive ();
+               }
+           }
+         else if (flag_openacc)
+           {
+             verify_token_free ("$acc", 4, last_was_use_stmt);
+             return decode_oacc_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;
     }
@@ -723,6 +1048,28 @@ next_free (void)
   return decode_statement ();
 }
 
+/* Assert next length characters to be equal to token in fixed form.  */
+
+static bool
+verify_token_fixed (const char *token, int length, bool last_was_use_stmt)
+{
+  int i;
+  char c = gfc_next_char_literal (NONSTRING);
+
+  for (i = 0; i < length; i++, c = gfc_next_char_literal (NONSTRING))
+    gcc_assert ((char) gfc_wide_tolower (c) == token[i]);
+
+  if (c != ' ' && c != '0')
+    {
+      gfc_buffer_error (false);
+      gfc_error ("Bad continuation line at %C");
+      return false;
+    }
+  if (last_was_use_stmt)
+    use_modules ();
+
+  return true;
+}
 
 /* Get the next statement in fixed-form source.  */
 
@@ -747,7 +1094,7 @@ next_fixed (void)
 
   for (i = 0; i < 5; i++)
     {
-      c = gfc_next_char_literal (0);
+      c = gfc_next_char_literal (NONSTRING);
 
       switch (c)
        {
@@ -773,28 +1120,47 @@ 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 == '$')
            {
-             for (i = 0; i < 4; i++, c = gfc_next_char_literal (0))
-               gcc_assert ((char) gfc_wide_tolower (c) == "$omp"[i]);
-
-             if (c != ' ' && c != '0')
+             if ((flag_openmp || flag_openmp_simd)
+                 && !flag_openacc)
                {
-                 gfc_buffer_error (0);
-                 gfc_error ("Bad continuation line at %C");
-                 return ST_NONE;
+                 if (!verify_token_fixed ("omp", 3, last_was_use_stmt))
+                   return ST_NONE;
+                 return decode_omp_directive ();
+               }
+             else if ((flag_openmp || flag_openmp_simd)
+                      && flag_openacc)
+               {
+                 c = gfc_next_char_literal(NONSTRING);
+                 if (c == 'o' || c == 'O')
+                   {
+                     if (!verify_token_fixed ("mp", 2, last_was_use_stmt))
+                       return ST_NONE;
+                     return decode_omp_directive ();
+                   }
+                 else if (c == 'a' || c == 'A')
+                   {
+                     if (!verify_token_fixed ("cc", 2, last_was_use_stmt))
+                       return ST_NONE;
+                     return decode_oacc_directive ();
+                   }
+               }
+             else if (flag_openacc)
+               {
+                 if (!verify_token_fixed ("acc", 3, last_was_use_stmt))
+                   return ST_NONE;
+                 return decode_oacc_directive ();
                }
-
-             return decode_omp_directive ();
            }
          /* FALLTHROUGH */
 
@@ -802,7 +1168,7 @@ next_fixed (void)
             here so don't bother checking for them.  */
 
        default:
-         gfc_buffer_error (0);
+         gfc_buffer_error (false);
          gfc_error ("Non-numeric character in statement label at %C");
          return ST_NONE;
        }
@@ -811,7 +1177,7 @@ next_fixed (void)
   if (digit_flag)
     {
       if (label == 0)
-       gfc_warning_now ("Zero is not a valid statement label at %C");
+       gfc_warning_now (0, "Zero is not a valid statement label at %C");
       else
        {
          /* We've found a valid statement label.  */
@@ -823,13 +1189,13 @@ 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;
 
   if (c != ' ' && c != '0')
     {
-      gfc_buffer_error (0);
+      gfc_buffer_error (false);
       gfc_error ("Bad continuation line at %C");
       return ST_NONE;
     }
@@ -841,7 +1207,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));
 
@@ -851,7 +1217,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;
     }
 
@@ -863,7 +1233,7 @@ next_fixed (void)
 
 blank_line:
   if (digit_flag)
-    gfc_warning_now ("Ignoring statement label in empty statement at %L",
+    gfc_warning_now (0, "Ignoring statement label in empty statement at %L",
                     &label_locus);
     
   gfc_current_locus.lb->truncated = 0;
@@ -881,13 +1251,17 @@ 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;
+  gfc_current_ns->old_data = gfc_current_ns->data;
   for (;;)
     {
       gfc_statement_label = NULL;
-      gfc_buffer_error (1);
+      gfc_buffer_error (true);
 
       if (gfc_at_eol ())
        gfc_advance_line ();
@@ -911,7 +1285,7 @@ next_statement (void)
        break;
     }
 
-  gfc_buffer_error (0);
+  gfc_buffer_error (false);
 
   if (st == ST_GET_FCN_CHARACTERISTICS && gfc_statement_label != NULL)
     {
@@ -944,8 +1318,12 @@ 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_ERROR_STOP: \
-  case ST_SYNC_ALL: case ST_SYNC_IMAGES: case ST_SYNC_MEMORY
+  case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_OMP_TASKYIELD: \
+  case ST_OMP_CANCEL: case ST_OMP_CANCELLATION_POINT: \
+  case ST_OMP_TARGET_UPDATE: case ST_ERROR_STOP: case ST_SYNC_ALL: \
+  case ST_SYNC_IMAGES: case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK: \
+  case ST_OACC_UPDATE: case ST_OACC_WAIT: case ST_OACC_CACHE: \
+  case ST_OACC_ENTER_DATA: case ST_OACC_EXIT_DATA
 
 /* Statements that mark other executable statements.  */
 
@@ -957,14 +1335,30 @@ next_statement (void)
   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_CRITICAL
+  case ST_OMP_TASK: case ST_OMP_TASKGROUP: case ST_OMP_SIMD: \
+  case ST_OMP_DO_SIMD: case ST_OMP_PARALLEL_DO_SIMD: case ST_OMP_TARGET: \
+  case ST_OMP_TARGET_DATA: case ST_OMP_TARGET_TEAMS: \
+  case ST_OMP_TARGET_TEAMS_DISTRIBUTE: \
+  case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: \
+  case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: \
+  case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: \
+  case ST_OMP_TEAMS: case ST_OMP_TEAMS_DISTRIBUTE: \
+  case ST_OMP_TEAMS_DISTRIBUTE_SIMD: \
+  case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: \
+  case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case ST_OMP_DISTRIBUTE: \
+  case ST_OMP_DISTRIBUTE_SIMD: case ST_OMP_DISTRIBUTE_PARALLEL_DO: \
+  case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: \
+  case ST_CRITICAL: \
+  case ST_OACC_PARALLEL_LOOP: case ST_OACC_PARALLEL: case ST_OACC_KERNELS: \
+  case ST_OACC_DATA: case ST_OACC_HOST_DATA: case ST_OACC_LOOP: case ST_OACC_KERNELS_LOOP
 
 /* Declaration statements */
 
 #define case_decl case ST_ATTR_DECL: case ST_COMMON: case ST_DATA_DECL: \
   case ST_EQUIVALENCE: case ST_NAMELIST: case ST_STATEMENT_FUNCTION: \
   case ST_TYPE: case ST_INTERFACE: case ST_OMP_THREADPRIVATE: \
-  case ST_PROCEDURE
+  case ST_PROCEDURE: case ST_OMP_DECLARE_SIMD: case ST_OMP_DECLARE_REDUCTION: \
+  case ST_OMP_DECLARE_TARGET: case ST_OACC_ROUTINE
 
 /* Block end statements.  Errors associated with interchanging these
    are detected in gfc_match_end().  */
@@ -984,6 +1378,15 @@ 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 (p->state != COMP_DO && p->state != COMP_DO_CONCURRENT)
+    p->ext.oacc_declare_clauses = 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;
 }
 
@@ -998,7 +1401,7 @@ pop_state (void)
 
 /* Try to find the given state in the state stack.  */
 
-gfc_try
+bool
 gfc_find_state (gfc_compile_state state)
 {
   gfc_state_data *p;
@@ -1007,7 +1410,7 @@ gfc_find_state (gfc_compile_state state)
     if (p->state == state)
       break;
 
-  return (p == NULL) ? FAILURE : SUCCESS;
+  return (p == NULL) ? false : true;
 }
 
 
@@ -1018,7 +1421,7 @@ new_level (gfc_code *q)
 {
   gfc_code *p;
 
-  p = q->block = gfc_get_code ();
+  p = q->block = gfc_get_code (EXEC_NOP);
 
   gfc_state_stack->head = gfc_state_stack->tail = p;
 
@@ -1034,7 +1437,7 @@ add_statement (void)
 {
   gfc_code *p;
 
-  p = gfc_get_code ();
+  p = XCNEW (gfc_code);
   *p = new_st;
 
   p->loc = gfc_current_locus;
@@ -1092,9 +1495,14 @@ check_statement_label (gfc_statement st)
     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;
+      if (st == ST_ENDDO || st == ST_CONTINUE)
+       type = ST_LABEL_DO_TARGET;
+      else
+       type = ST_LABEL_TARGET;
       break;
 
     case ST_FORMAT:
@@ -1319,6 +1727,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;
@@ -1379,6 +1790,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_TYPE:
       p = "TYPE";
       break;
+    case ST_UNLOCK:
+      p = "UNLOCK";
+      break;
     case ST_USE:
       p = "USE";
       break;
@@ -1431,24 +1845,138 @@ gfc_ascii_statement (gfc_statement st)
     case ST_END_ENUM:
       p = "END ENUM";
       break;
+    case ST_OACC_PARALLEL_LOOP:
+      p = "!$ACC PARALLEL LOOP";
+      break;
+    case ST_OACC_END_PARALLEL_LOOP:
+      p = "!$ACC END PARALLEL LOOP";
+      break;
+    case ST_OACC_PARALLEL:
+      p = "!$ACC PARALLEL";
+      break;
+    case ST_OACC_END_PARALLEL:
+      p = "!$ACC END PARALLEL";
+      break;
+    case ST_OACC_KERNELS:
+      p = "!$ACC KERNELS";
+      break;
+    case ST_OACC_END_KERNELS:
+      p = "!$ACC END KERNELS";
+      break;
+    case ST_OACC_KERNELS_LOOP:
+      p = "!$ACC KERNELS LOOP";
+      break;
+    case ST_OACC_END_KERNELS_LOOP:
+      p = "!$ACC END KERNELS LOOP";
+      break;
+    case ST_OACC_DATA:
+      p = "!$ACC DATA";
+      break;
+    case ST_OACC_END_DATA:
+      p = "!$ACC END DATA";
+      break;
+    case ST_OACC_HOST_DATA:
+      p = "!$ACC HOST_DATA";
+      break;
+    case ST_OACC_END_HOST_DATA:
+      p = "!$ACC END HOST_DATA";
+      break;
+    case ST_OACC_LOOP:
+      p = "!$ACC LOOP";
+      break;
+    case ST_OACC_END_LOOP:
+      p = "!$ACC END LOOP";
+      break;
+    case ST_OACC_DECLARE:
+      p = "!$ACC DECLARE";
+      break;
+    case ST_OACC_UPDATE:
+      p = "!$ACC UPDATE";
+      break;
+    case ST_OACC_WAIT:
+      p = "!$ACC WAIT";
+      break;
+    case ST_OACC_CACHE:
+      p = "!$ACC CACHE";
+      break;
+    case ST_OACC_ENTER_DATA:
+      p = "!$ACC ENTER DATA";
+      break;
+    case ST_OACC_EXIT_DATA:
+      p = "!$ACC EXIT DATA";
+      break;
+    case ST_OACC_ROUTINE:
+      p = "!$ACC ROUTINE";
+      break;
     case ST_OMP_ATOMIC:
       p = "!$OMP ATOMIC";
       break;
     case ST_OMP_BARRIER:
       p = "!$OMP BARRIER";
       break;
+    case ST_OMP_CANCEL:
+      p = "!$OMP CANCEL";
+      break;
+    case ST_OMP_CANCELLATION_POINT:
+      p = "!$OMP CANCELLATION POINT";
+      break;
     case ST_OMP_CRITICAL:
       p = "!$OMP CRITICAL";
       break;
+    case ST_OMP_DECLARE_REDUCTION:
+      p = "!$OMP DECLARE REDUCTION";
+      break;
+    case ST_OMP_DECLARE_SIMD:
+      p = "!$OMP DECLARE SIMD";
+      break;
+    case ST_OMP_DECLARE_TARGET:
+      p = "!$OMP DECLARE TARGET";
+      break;
+    case ST_OMP_DISTRIBUTE:
+      p = "!$OMP DISTRIBUTE";
+      break;
+    case ST_OMP_DISTRIBUTE_PARALLEL_DO:
+      p = "!$OMP DISTRIBUTE PARALLEL DO";
+      break;
+    case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
+      p = "!$OMP DISTRIBUTE PARALLEL DO SIMD";
+      break;
+    case ST_OMP_DISTRIBUTE_SIMD:
+      p = "!$OMP DISTRIBUTE SIMD";
+      break;
     case ST_OMP_DO:
       p = "!$OMP DO";
       break;
+    case ST_OMP_DO_SIMD:
+      p = "!$OMP DO SIMD";
+      break;
+    case ST_OMP_END_ATOMIC:
+      p = "!$OMP END ATOMIC";
+      break;
     case ST_OMP_END_CRITICAL:
       p = "!$OMP END CRITICAL";
       break;
+    case ST_OMP_END_DISTRIBUTE:
+      p = "!$OMP END DISTRIBUTE";
+      break;
+    case ST_OMP_END_DISTRIBUTE_PARALLEL_DO:
+      p = "!$OMP END DISTRIBUTE PARALLEL DO";
+      break;
+    case ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD:
+      p = "!$OMP END DISTRIBUTE PARALLEL DO SIMD";
+      break;
+    case ST_OMP_END_DISTRIBUTE_SIMD:
+      p = "!$OMP END DISTRIBUTE SIMD";
+      break;
     case ST_OMP_END_DO:
       p = "!$OMP END DO";
       break;
+    case ST_OMP_END_DO_SIMD:
+      p = "!$OMP END DO SIMD";
+      break;
+    case ST_OMP_END_SIMD:
+      p = "!$OMP END SIMD";
+      break;
     case ST_OMP_END_MASTER:
       p = "!$OMP END MASTER";
       break;
@@ -1461,6 +1989,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_END_PARALLEL_DO:
       p = "!$OMP END PARALLEL DO";
       break;
+    case ST_OMP_END_PARALLEL_DO_SIMD:
+      p = "!$OMP END PARALLEL DO SIMD";
+      break;
     case ST_OMP_END_PARALLEL_SECTIONS:
       p = "!$OMP END PARALLEL SECTIONS";
       break;
@@ -1476,6 +2007,45 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_END_TASK:
       p = "!$OMP END TASK";
       break;
+    case ST_OMP_END_TARGET:
+      p = "!$OMP END TARGET";
+      break;
+    case ST_OMP_END_TARGET_DATA:
+      p = "!$OMP END TARGET DATA";
+      break;
+    case ST_OMP_END_TARGET_TEAMS:
+      p = "!$OMP END TARGET TEAMS";
+      break;
+    case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE:
+      p = "!$OMP END TARGET TEAMS DISTRIBUTE";
+      break;
+    case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      p = "!$OMP END TARGET TEAMS DISTRIBUTE PARALLEL DO";
+      break;
+    case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      p = "!$OMP END TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
+      break;
+    case ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD:
+      p = "!$OMP END TARGET TEAMS DISTRIBUTE SIMD";
+      break;
+    case ST_OMP_END_TASKGROUP:
+      p = "!$OMP END TASKGROUP";
+      break;
+    case ST_OMP_END_TEAMS:
+      p = "!$OMP END TEAMS";
+      break;
+    case ST_OMP_END_TEAMS_DISTRIBUTE:
+      p = "!$OMP END TEAMS DISTRIBUTE";
+      break;
+    case ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      p = "!$OMP END TEAMS DISTRIBUTE PARALLEL DO";
+      break;
+    case ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      p = "!$OMP END TEAMS DISTRIBUTE PARALLEL DO SIMD";
+      break;
+    case ST_OMP_END_TEAMS_DISTRIBUTE_SIMD:
+      p = "!$OMP END TEAMS DISTRIBUTE SIMD";
+      break;
     case ST_OMP_END_WORKSHARE:
       p = "!$OMP END WORKSHARE";
       break;
@@ -1494,6 +2064,9 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_PARALLEL_DO:
       p = "!$OMP PARALLEL DO";
       break;
+    case ST_OMP_PARALLEL_DO_SIMD:
+      p = "!$OMP PARALLEL DO SIMD";
+      break;
     case ST_OMP_PARALLEL_SECTIONS:
       p = "!$OMP PARALLEL SECTIONS";
       break;
@@ -1506,15 +2079,63 @@ gfc_ascii_statement (gfc_statement st)
     case ST_OMP_SECTION:
       p = "!$OMP SECTION";
       break;
+    case ST_OMP_SIMD:
+      p = "!$OMP SIMD";
+      break;
     case ST_OMP_SINGLE:
       p = "!$OMP SINGLE";
       break;
+    case ST_OMP_TARGET:
+      p = "!$OMP TARGET";
+      break;
+    case ST_OMP_TARGET_DATA:
+      p = "!$OMP TARGET DATA";
+      break;
+    case ST_OMP_TARGET_TEAMS:
+      p = "!$OMP TARGET TEAMS";
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
+      p = "!$OMP TARGET TEAMS DISTRIBUTE";
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      p = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO";
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      p = "!$OMP TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD";
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+      p = "!$OMP TARGET TEAMS DISTRIBUTE SIMD";
+      break;
+    case ST_OMP_TARGET_UPDATE:
+      p = "!$OMP TARGET UPDATE";
+      break;
     case ST_OMP_TASK:
       p = "!$OMP TASK";
       break;
+    case ST_OMP_TASKGROUP:
+      p = "!$OMP TASKGROUP";
+      break;
     case ST_OMP_TASKWAIT:
       p = "!$OMP TASKWAIT";
       break;
+    case ST_OMP_TASKYIELD:
+      p = "!$OMP TASKYIELD";
+      break;
+    case ST_OMP_TEAMS:
+      p = "!$OMP TEAMS";
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE:
+      p = "!$OMP TEAMS DISTRIBUTE";
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      p = "!$OMP TEAMS DISTRIBUTE PARALLEL DO";
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      p = "!$OMP TEAMS DISTRIBUTE PARALLEL DO SIMD";
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
+      p = "!$OMP TEAMS DISTRIBUTE SIMD";
+      break;
     case ST_OMP_THREADPRIVATE:
       p = "!$OMP THREADPRIVATE";
       break;
@@ -1558,14 +2179,7 @@ accept_statement (gfc_statement st)
 {
   switch (st)
     {
-    case ST_USE:
-      gfc_use_module ();
-      break;
-
     case ST_IMPLICIT_NONE:
-      gfc_set_implicit_none ();
-      break;
-
     case ST_IMPLICIT:
       break;
 
@@ -1590,6 +2204,18 @@ 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_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;
@@ -1643,6 +2269,11 @@ 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_reject_data (gfc_current_ns);
+
   gfc_new_block = NULL;
   gfc_undo_symbols ();
   gfc_clear_warning ();
@@ -1665,7 +2296,7 @@ unexpected_statement (gfc_statement st)
 /* Given the next statement seen by the matcher, make sure that it is
    in proper order with the last.  This subroutine is initialized by
    calling it with an argument of ST_NONE.  If there is a problem, we
-   issue an error and return FAILURE.  Otherwise we return SUCCESS.
+   issue an error and return false.  Otherwise we return true.
 
    Individual parsers need to verify that the statements seen are
    valid before calling here, i.e., ENTRY statements are not allowed in
@@ -1717,7 +2348,7 @@ typedef struct
 }
 st_state;
 
-static gfc_try
+static bool
 verify_st_order (st_state *p, gfc_statement st, bool silent)
 {
 
@@ -1740,7 +2371,7 @@ verify_st_order (st_state *p, gfc_statement st, bool silent)
       break;
 
     case ST_IMPLICIT_NONE:
-      if (p->state > ORDER_IMPLICIT_NONE)
+      if (p->state > ORDER_IMPLICIT)
        goto order;
 
       /* The '>' sign cannot be a '>=', because a FORMAT or ENTRY
@@ -1778,6 +2409,7 @@ verify_st_order (st_state *p, gfc_statement st, bool silent)
     case ST_PUBLIC:
     case ST_PRIVATE:
     case ST_DERIVED_DECL:
+    case ST_OACC_DECLARE:
     case_decl:
       if (p->state >= ORDER_EXEC)
        goto order;
@@ -1792,14 +2424,13 @@ verify_st_order (st_state *p, gfc_statement st, bool silent)
       break;
 
     default:
-      gfc_internal_error ("Unexpected %s statement in verify_st_order() at %C",
-                         gfc_ascii_statement (st));
+      return false;
     }
 
   /* All is well, record the statement in case we need it next time.  */
   p->where = gfc_current_locus;
   p->last_statement = st;
-  return SUCCESS;
+  return true;
 
 order:
   if (!silent)
@@ -1807,7 +2438,7 @@ order:
               gfc_ascii_statement (st),
               gfc_ascii_statement (p->last_statement), &p->where);
 
-  return FAILURE;
+  return false;
 }
 
 
@@ -1820,7 +2451,7 @@ unexpected_eof (void)
 {
   gfc_state_data *p;
 
-  gfc_error ("Unexpected end of file in '%s'", gfc_source_file);
+  gfc_error ("Unexpected end of file in %qs", gfc_source_file);
 
   /* Memory cleanup.  Move to "second to last".  */
   for (p = gfc_state_stack; p && p->previous && p->previous->previous;
@@ -1852,10 +2483,10 @@ parse_derived_contains (void)
   /* 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"
+    gfc_error ("Derived-type %qs 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"
+    gfc_error ("Derived-type %qs with BIND(C) must not have a CONTAINS"
               " section at %C", gfc_current_block ()->name);
 
   accept_statement (ST_CONTAINS);
@@ -1876,32 +2507,28 @@ 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;
+         if (!gfc_notify_std (GFC_STD_F2003, "Type-bound procedure at %C"))
+           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)
-           error_flag = true;
+         if (!gfc_notify_std (GFC_STD_F2003, "GENERIC binding at %C"))
+           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)
-           error_flag = true;
+         if (!gfc_notify_std (GFC_STD_F2003, "FINAL procedure declaration"
+                              " at %C"))
+           goto error;
 
          accept_statement (ST_FINAL);
          seen_comps = true;
@@ -1911,35 +2538,32 @@ parse_derived_contains (void)
          to_finish = true;
 
          if (!seen_comps
-             && (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Derived type "
-                                 "definition at %C with empty CONTAINS "
-                                 "section") == FAILURE))
-           error_flag = true;
+             && (!gfc_notify_std(GFC_STD_F2008, "Derived type definition "
+                                 "at %C with empty CONTAINS section")))
+           goto error;
 
          /* ST_END_TYPE is accepted by parse_derived after return.  */
          break;
 
        case ST_PRIVATE:
-         if (gfc_find_state (COMP_MODULE) == FAILURE)
+         if (!gfc_find_state (COMP_MODULE))
            {
              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);
@@ -1949,18 +2573,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 ();
@@ -1979,7 +2607,7 @@ parse_derived (void)
   gfc_statement st;
   gfc_state_data s;
   gfc_symbol *sym;
-  gfc_component *c;
+  gfc_component *c, *lock_comp = NULL;
 
   accept_statement (ST_DERIVED_DECL);
   push_state (&s, COMP_DERIVED, gfc_new_block);
@@ -2014,14 +2642,14 @@ endType:
          compiling_type = 0;
 
          if (!seen_component)
-           gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Derived type "
+           gfc_notify_std (GFC_STD_F2003, "Derived type "
                            "definition at %C without components");
 
          accept_statement (ST_END_TYPE);
          break;
 
        case ST_PRIVATE:
-         if (gfc_find_state (COMP_MODULE) == FAILURE)
+         if (!gfc_find_state (COMP_MODULE))
            {
              gfc_error ("PRIVATE statement in TYPE at %C must be inside "
                         "a MODULE");
@@ -2053,7 +2681,7 @@ endType:
            }
 
          if (gfc_current_block ()->attr.sequence)
-           gfc_warning ("SEQUENCE attribute at %C already specified in "
+           gfc_warning (0, "SEQUENCE attribute at %C already specified in "
                         "TYPE statement");
 
          if (seen_sequence)
@@ -2068,7 +2696,7 @@ endType:
 
        case ST_CONTAINS:
          gfc_notify_std (GFC_STD_F2003,
-                         "Fortran 2003:  CONTAINS block in derived type"
+                         "CONTAINS block in derived type"
                          " definition at %C");
 
          accept_statement (ST_CONTAINS);
@@ -2087,17 +2715,29 @@ endType:
   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->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;
+         || (c->ts.type == BT_CLASS && c->attr.class_ok
+             && CLASS_DATA (c)->attr.allocatable)
+         || (c->ts.type == BT_DERIVED && !c->attr.pointer
+             && c->ts.u.derived->attr.alloc_comp))
+       {
+         allocatable = true;
+         sym->attr.alloc_comp = 1;
+       }
 
       /* Look for pointer components.  */
       if (c->attr.pointer
-         || (c->ts.type == BT_CLASS && CLASS_DATA (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))
-       sym->attr.pointer_comp = 1;
+       {
+         pointer = true;
+         sym->attr.pointer_comp = 1;
+       }
 
       /* Look for procedure pointer components.  */
       if (c->attr.proc_pointer
@@ -2107,8 +2747,76 @@ endType:
 
       /* Looking for coarray components.  */
       if (c->attr.codimension
-         || (c->attr.coarray_comp && !c->attr.pointer && !c->attr.allocatable))
-       sym->attr.coarray_comp = 1;
+         || (c->ts.type == BT_CLASS && c->attr.class_ok
+             && CLASS_DATA (c)->attr.codimension))
+       {
+         coarray = true;
+         sym->attr.coarray_comp = 1;
+       }
+     
+      if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.coarray_comp
+         && !c->attr.pointer)
+       {
+         coarray = true;
+         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
@@ -2183,7 +2891,6 @@ parse_interface (void)
   gfc_interface_info save;
   gfc_state_data s1, s2;
   gfc_statement st;
-  locus proc_locus;
 
   accept_statement (ST_INTERFACE);
 
@@ -2217,8 +2924,8 @@ loop:
          gfc_new_block->attr.pointer = 0;
          gfc_new_block->attr.proc_pointer = 1;
        }
-      if (gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY,
-                                 gfc_new_block->formal, NULL) == FAILURE)
+      if (!gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY, 
+                                      gfc_new_block->formal, NULL))
        {
          reject_statement ();
          gfc_free_namespace (gfc_current_ns);
@@ -2247,39 +2954,23 @@ 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 && 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 && sym)
+       gfc_add_function (&sym->attr, sym->name, NULL);
+      else if (new_state == COMP_SUBROUTINE && sym)
+       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)
-               gfc_error ("FUNCTION at %C does not belong in a "
-                          "generic subroutine interface");
-           }
-       }
+      current_state = new_state;
     }
 
   if (current_interface.type == INTERFACE_ABSTRACT)
     {
       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 "
+       gfc_error ("Name %qs of ABSTRACT INTERFACE at %C "
                   "cannot be the same as an intrinsic type",
                   gfc_new_block->name);
     }
@@ -2288,7 +2979,9 @@ loop:
   accept_statement (st);
   prog_unit = gfc_new_block;
   prog_unit->formal_ns = gfc_current_ns;
-  proc_locus = gfc_current_locus;
+  if (prog_unit == prog_unit->formal_ns->proc_name
+      && prog_unit->ns != prog_unit->formal_ns)
+    prog_unit->refs++;
 
 decl:
   /* Read data declaration statements.  */
@@ -2328,8 +3021,9 @@ decl:
        && current_interface.ns->proc_name
        && strcmp (current_interface.ns->proc_name->name,
                   prog_unit->name) == 0)
-    gfc_error ("INTERFACE procedure '%s' at %L has the same name as the "
-              "enclosing procedure", prog_unit->name, &proc_locus);
+    gfc_error ("INTERFACE procedure %qs at %L has the same name as the "
+              "enclosing procedure", prog_unit->name,
+              &current_interface.ns->proc_name->declared_at);
 
   goto loop;
 
@@ -2353,9 +3047,9 @@ match_deferred_characteristics (gfc_typespec * ts)
   gfc_current_locus = gfc_current_block ()->declared_at;
 
   gfc_clear_error ();
-  gfc_buffer_error (1);
+  gfc_buffer_error (true);
   m = gfc_match_prefix (ts);
-  gfc_buffer_error (0);
+  gfc_buffer_error (false);
 
   if (ts->type == BT_DERIVED)
     {
@@ -2379,7 +3073,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;
@@ -2451,9 +3148,37 @@ 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:
+         break;
+      }
+  else if (gfc_current_state () == COMP_BLOCK_DATA)
+    /* Fortran 2008, C1116.  */
+    switch (st)
+      {
+        case ST_DATA_DECL:
+       case ST_COMMON:
+       case ST_DATA:
+       case ST_TYPE:
+       case ST_END_BLOCK_DATA:
+       case ST_ATTR_DECL:
+       case ST_EQUIVALENCE:
+       case ST_PARAMETER:
+       case ST_IMPLICIT:
+       case ST_IMPLICIT_NONE:
+       case ST_DERIVED_DECL:
+       case ST_USE:
          break;
 
+       case ST_NONE:
+         break;
+         
        default:
+         gfc_error ("%s statement is not allowed inside of BLOCK DATA at %C",
+                    gfc_ascii_statement (st));
+         reject_statement ();
          break;
       }
   
@@ -2473,7 +3198,7 @@ loop:
          verify_st_order (&dummyss, ST_NONE, false);
          verify_st_order (&dummyss, st, false);
 
-         if (verify_st_order (&dummyss, ST_IMPLICIT, true) == FAILURE)
+         if (!verify_st_order (&dummyss, ST_IMPLICIT, true))
            verify_now = true;
        }
 
@@ -2514,7 +3239,7 @@ loop:
     case ST_DERIVED_DECL:
     case_decl:
 declSt:
-      if (verify_st_order (&ss, st, false) == FAILURE)
+      if (!verify_st_order (&ss, st, false))
        {
          reject_statement ();
          st = next_statement ();
@@ -2537,6 +3262,7 @@ declSt:
            {
              gfc_error ("%s statement must appear in a MODULE",
                         gfc_ascii_statement (st));
+             reject_statement ();
              break;
            }
 
@@ -2544,6 +3270,7 @@ declSt:
            {
              gfc_error ("%s statement at %C follows another accessibility "
                         "specification", gfc_ascii_statement (st));
+             reject_statement ();
              break;
            }
 
@@ -2583,20 +3310,33 @@ declSt:
       st = next_statement ();
       goto loop;
 
+    case ST_OACC_DECLARE:
+      if (!verify_st_order(&ss, st, false))
+       {
+         reject_statement ();
+         st = next_statement ();
+         goto loop;
+       }
+      if (gfc_state_stack->ext.oacc_declare_clauses == NULL)
+       gfc_state_stack->ext.oacc_declare_clauses = new_st.ext.omp_clauses;
+      accept_statement (st);
+      st = next_statement ();
+      goto loop;
+
     default:
       break;
     }
 
-  /* If match_deferred_characteristics failed, then there is an error. */
+  /* If match_deferred_characteristics failed, then there is an error.  */
   if (bad_characteristic)
     {
       ts = &gfc_current_block ()->result->ts;
       if (ts->type != BT_DERIVED)
-       gfc_error ("Bad kind expression for function '%s' at %L",
+       gfc_error ("Bad kind expression for function %qs at %L",
                   gfc_current_block ()->name,
                   &gfc_current_block ()->declared_at);
       else
-       gfc_error ("The type for function '%s' at %L is not accessible",
+       gfc_error ("The type for function %qs at %L is not accessible",
                   gfc_current_block ()->name,
                   &gfc_current_block ()->declared_at);
 
@@ -2656,6 +3396,7 @@ parse_where_block (void)
            {
              gfc_error ("ELSEWHERE statement at %C follows previous "
                         "unmasked ELSEWHERE");
+             reject_statement ();
              break;
            }
 
@@ -2916,7 +3657,7 @@ select_type_pop (void)
 {
   gfc_select_type_stack *old = select_type_stack;
   select_type_stack = old->prev;
-  gfc_free (old);
+  free (old);
 }
 
 
@@ -3009,8 +3750,8 @@ gfc_check_do_variable (gfc_symtree *st)
   for (s=gfc_state_stack; s; s = s->previous)
     if (s->do_variable == st)
       {
-       gfc_error_now("Variable '%s' at %C cannot be redefined inside "
-                     "loop beginning at %L", st->name, &s->head->loc);
+       gfc_error_now ("Variable %qs at %C cannot be redefined inside "
+                      "loop beginning at %L", st->name, &s->head->loc);
        return 1;
       }
 
@@ -3031,7 +3772,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)
@@ -3049,7 +3790,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");
@@ -3071,9 +3813,15 @@ static void
 parse_critical_block (void)
 {
   gfc_code *top, *d;
-  gfc_state_data s;
+  gfc_state_data s, *sd;
   gfc_statement st;
 
+  for (sd = gfc_state_stack; sd; sd = sd->previous) 
+    if (sd->state == COMP_OMP_STRUCTURED_BLOCK)
+      gfc_error_now (is_oacc (sd)
+                    ? "CRITICAL block inside of OpenACC region at %C"
+                    : "CRITICAL block inside of OpenMP region at %C");
+
   s.ext.end_do_label = new_st.label1;
 
   accept_statement (ST_CRITICAL);
@@ -3099,7 +3847,7 @@ parse_critical_block (void)
            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");
+                            "match CRITICAL label");
 
            if (gfc_statement_label != NULL)
              {
@@ -3126,6 +3874,7 @@ 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;
@@ -3139,12 +3888,15 @@ gfc_build_block_ns (gfc_namespace *parent_ns)
     my_ns->proc_name = gfc_new_block;
   else
     {
-      gfc_try t;
+      bool t;
+      char buffer[20];  /* Enough to hold "block@2147483648\n".  */
 
-      gfc_get_symbol ("block@", my_ns, &my_ns->proc_name);
+      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);
+      gcc_assert (t);
+      gfc_commit_symbol (my_ns->proc_name);
     }
 
   if (parent_ns->proc_name)
@@ -3162,7 +3914,7 @@ parse_block_construct (void)
   gfc_namespace* my_ns;
   gfc_state_data s;
 
-  gfc_notify_std (GFC_STD_F2008, "Fortran 2008: BLOCK construct at %C");
+  gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C");
 
   my_ns = gfc_build_block_ns (gfc_current_ns);
 
@@ -3191,9 +3943,8 @@ parse_associate (void)
   gfc_state_data s;
   gfc_statement st;
   gfc_association_list* a;
-  gfc_code* assignTail;
 
-  gfc_notify_std (GFC_STD_F2003, "Fortran 2003: ASSOCIATE construct at %C");
+  gfc_notify_std (GFC_STD_F2003, "ASSOCIATE construct at %C");
 
   my_ns = gfc_build_block_ns (gfc_current_ns);
 
@@ -3201,46 +3952,29 @@ parse_associate (void)
   new_st.ext.block.ns = my_ns;
   gcc_assert (new_st.ext.block.assoc);
 
-  /* Add all associations to expressions as BLOCK variables, and create
-     assignments to them giving their values.  */
+  /* 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;
-  assignTail = NULL;
   for (a = new_st.ext.block.assoc; a; a = a->next)
-    if (!a->variable)
-      {
-       gfc_code* newAssign;
-
-       if (gfc_get_sym_tree (a->name, NULL, &a->st, false))
-         gcc_unreachable ();
-
-       /* Note that in certain cases, the target-expression's type is not yet
-          known and so we have to adapt the symbol's ts also during resolution
-          for these cases.  */
-       a->st->n.sym->ts = a->target->ts;
-       a->st->n.sym->attr.flavor = FL_VARIABLE;
-       a->st->n.sym->assoc = a;
-       gfc_set_sym_referenced (a->st->n.sym);
-
-       /* Create the assignment to calculate the expression and set it.  */
-       newAssign = gfc_get_code ();
-       newAssign->op = EXEC_ASSIGN;
-       newAssign->loc = gfc_current_locus;
-       newAssign->expr1 = gfc_get_variable_expr (a->st);
-       newAssign->expr2 = a->target;
-
-       /* Hang it in.  */
-       if (assignTail)
-         assignTail->next = newAssign;
-       else
-         gfc_current_ns->code = newAssign;
-       assignTail = newAssign;
-      }
-    else
-      {
-       gfc_error ("Association to variables is not yet supported at %C");
-       return;
-      }
-  gcc_assert (assignTail);
+    {
+      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 association to a derived-type.  */
+      sym->ts = a->target->ts;
+    }
 
   accept_statement (ST_ASSOCIATE);
   push_state (&s, COMP_ASSOCIATE, my_ns->proc_name);
@@ -3254,7 +3988,7 @@ loop:
 
     case_end:
       accept_statement (st);
-      assignTail->next = gfc_state_stack->head;
+      my_ns->code = gfc_state_stack->head;
       break;
 
     default:
@@ -3278,7 +4012,9 @@ parse_do_block (void)
   gfc_code *top;
   gfc_state_data s;
   gfc_symtree *stree;
+  gfc_exec_op do_op;
 
+  do_op = new_st.op;
   s.ext.end_do_label = new_st.label1;
 
   if (new_st.ext.iterator != NULL)
@@ -3289,7 +4025,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;
 
@@ -3387,7 +4124,53 @@ parse_omp_do (gfc_statement omp_st)
   pop_state ();
 
   st = next_statement ();
-  if (st == (omp_st == ST_OMP_DO ? ST_OMP_END_DO : ST_OMP_END_PARALLEL_DO))
+  gfc_statement omp_end_st = ST_OMP_END_DO;
+  switch (omp_st)
+    {
+    case ST_OMP_DISTRIBUTE: omp_end_st = ST_OMP_END_DISTRIBUTE; break;
+    case ST_OMP_DISTRIBUTE_PARALLEL_DO:
+      omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO;
+      break;
+    case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
+      omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD;
+      break;
+    case ST_OMP_DISTRIBUTE_SIMD:
+      omp_end_st = ST_OMP_END_DISTRIBUTE_SIMD;
+      break;
+    case ST_OMP_DO: omp_end_st = ST_OMP_END_DO; break;
+    case ST_OMP_DO_SIMD: omp_end_st = ST_OMP_END_DO_SIMD; break;
+    case ST_OMP_PARALLEL_DO: omp_end_st = ST_OMP_END_PARALLEL_DO; break;
+    case ST_OMP_PARALLEL_DO_SIMD:
+      omp_end_st = ST_OMP_END_PARALLEL_DO_SIMD;
+      break;
+    case ST_OMP_SIMD: omp_end_st = ST_OMP_END_SIMD; break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE;
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_SIMD;
+      break;
+    default: gcc_unreachable ();
+    }
+  if (st == omp_end_st)
     {
       if (new_st.op == EXEC_OMP_END_NOWAIT)
        cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
@@ -3404,12 +4187,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);
 
@@ -3418,21 +4202,159 @@ parse_omp_atomic (void)
   np = new_level (cp);
   np->op = cp->op;
   np->block = NULL;
+  count = 1 + ((cp->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+              == 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_MASK)
+          == GFC_OMP_ATOMIC_CAPTURE)
+    gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
+  return st;
+}
+
+
+/* Parse the statements of an OpenACC structured block.  */
+
+static void
+parse_oacc_structured_block (gfc_statement acc_st)
+{
+  gfc_statement st, acc_end_st;
+  gfc_code *cp, *np;
+  gfc_state_data s, *sd;
+
+  for (sd = gfc_state_stack; sd; sd = sd->previous) 
+    if (sd->state == COMP_CRITICAL)
+      gfc_error_now ("OpenACC directive inside of CRITICAL block at %C");
+
+  accept_statement (acc_st);
+
+  cp = gfc_state_stack->tail;
+  push_state (&s, COMP_OMP_STRUCTURED_BLOCK, NULL);
+  np = new_level (cp);
+  np->op = cp->op;
+  np->block = NULL;
+  switch (acc_st)
+    {
+    case ST_OACC_PARALLEL:
+      acc_end_st = ST_OACC_END_PARALLEL;
+      break;
+    case ST_OACC_KERNELS:
+      acc_end_st = ST_OACC_END_KERNELS;
+      break;
+    case ST_OACC_DATA:
+      acc_end_st = ST_OACC_END_DATA;
+      break;
+    case ST_OACC_HOST_DATA:
+      acc_end_st = ST_OACC_END_HOST_DATA;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  do
+    {
+      st = parse_executable (ST_NONE);
+      if (st == ST_NONE)
+       unexpected_eof ();
+      else if (st != acc_end_st)
+       gfc_error ("Expecting %s at %C", gfc_ascii_statement (acc_end_st));
+      reject_statement ();
+    }
+  while (st != acc_end_st);
+
+  gcc_assert (new_st.op == EXEC_NOP);
+
+  gfc_clear_new_st ();
+  gfc_commit_symbols ();
+  gfc_warning_check ();
+  pop_state ();
+}
+
+/* Parse the statements of OpenACC loop/parallel loop/kernels loop.  */
+
+static gfc_statement
+parse_oacc_loop (gfc_statement acc_st)
+{
+  gfc_statement st;
+  gfc_code *cp, *np;
+  gfc_state_data s, *sd;
+
+  for (sd = gfc_state_stack; sd; sd = sd->previous) 
+    if (sd->state == COMP_CRITICAL)
+      gfc_error_now ("OpenACC directive inside of CRITICAL block at %C");
+
+  accept_statement (acc_st);
+
+  cp = gfc_state_stack->tail;
+  push_state (&s, COMP_OMP_STRUCTURED_BLOCK, NULL);
+  np = new_level (cp);
+  np->op = cp->op;
+  np->block = NULL;
+
+  for (;;)
+    {
+      st = next_statement ();
+      if (st == ST_NONE)
+       unexpected_eof ();
+      else if (st == ST_DO)
+       break;
+      else
+       {
+         gfc_error ("Expected DO loop at %C");
+         reject_statement ();
+       }
+    }
+
+  parse_do_block ();
+  if (gfc_statement_label != NULL
+      && gfc_state_stack->previous != NULL
+      && gfc_state_stack->previous->state == COMP_DO
+      && gfc_state_stack->previous->ext.end_do_label == gfc_statement_label)
+    {
+      pop_state ();
+      return ST_IMPLIED_ENDDO;
+    }
 
+  check_do_closure ();
   pop_state ();
+
+  st = next_statement ();
+  if (st == ST_OACC_END_LOOP)
+    gfc_warning (0, "Redundant !$ACC END LOOP at %C");
+  if ((acc_st == ST_OACC_PARALLEL_LOOP && st == ST_OACC_END_PARALLEL_LOOP) ||
+      (acc_st == ST_OACC_KERNELS_LOOP && st == ST_OACC_END_KERNELS_LOOP) ||
+      (acc_st == ST_OACC_LOOP && st == ST_OACC_END_LOOP))
+    {
+      gcc_assert (new_st.op == EXEC_NOP);
+      gfc_clear_new_st ();
+      gfc_commit_symbols ();
+      gfc_warning_check ();
+      st = next_statement ();
+    }
+  return st;
 }
 
 
@@ -3476,9 +4398,60 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
     case ST_OMP_SINGLE:
       omp_end_st = ST_OMP_END_SINGLE;
       break;
+    case ST_OMP_TARGET:
+      omp_end_st = ST_OMP_END_TARGET;
+      break;
+    case ST_OMP_TARGET_DATA:
+      omp_end_st = ST_OMP_END_TARGET_DATA;
+      break;
+    case ST_OMP_TARGET_TEAMS:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS;
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE;
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO;
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
+      break;
+    case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+      omp_end_st = ST_OMP_END_TARGET_TEAMS_DISTRIBUTE_SIMD;
+      break;
     case ST_OMP_TASK:
       omp_end_st = ST_OMP_END_TASK;
       break;
+    case ST_OMP_TASKGROUP:
+      omp_end_st = ST_OMP_END_TASKGROUP;
+      break;
+    case ST_OMP_TEAMS:
+      omp_end_st = ST_OMP_END_TEAMS;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD;
+      break;
+    case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
+      omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_SIMD;
+      break;
+    case ST_OMP_DISTRIBUTE:
+      omp_end_st = ST_OMP_END_DISTRIBUTE;
+      break;
+    case ST_OMP_DISTRIBUTE_PARALLEL_DO:
+      omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO;
+      break;
+    case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
+      omp_end_st = ST_OMP_END_DISTRIBUTE_PARALLEL_DO_SIMD;
+      break;
+    case ST_OMP_DISTRIBUTE_SIMD:
+      omp_end_st = ST_OMP_END_DISTRIBUTE_SIMD;
+      break;
     case ST_OMP_WORKSHARE:
       omp_end_st = ST_OMP_END_WORKSHARE;
       break;
@@ -3538,12 +4511,13 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
                  break;
 
                case ST_OMP_PARALLEL_DO:
+               case ST_OMP_PARALLEL_DO_SIMD:
                  st = parse_omp_do (st);
                  continue;
 
                case ST_OMP_ATOMIC:
-                 parse_omp_atomic ();
-                 break;
+                 st = parse_omp_atomic ();
+                 continue;
 
                default:
                  cycle = false;
@@ -3584,7 +4558,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]
@@ -3652,8 +4626,12 @@ parse_executable (gfc_statement st)
        case ST_NONE:
          unexpected_eof ();
 
-       case ST_FORMAT:
        case ST_DATA:
+         gfc_notify_std (GFC_STD_F95_OBS, "DATA statement at %C after the "
+                         "first executable statement");
+         /* Fall through.  */
+
+       case ST_FORMAT:
        case ST_ENTRY:
        case_executable:
          accept_statement (st);
@@ -3699,6 +4677,21 @@ parse_executable (gfc_statement st)
          parse_forall_block ();
          break;
 
+       case ST_OACC_PARALLEL_LOOP:
+       case ST_OACC_KERNELS_LOOP:
+       case ST_OACC_LOOP:
+         st = parse_oacc_loop (st);
+         if (st == ST_IMPLIED_ENDDO)
+           return st;
+         continue;
+
+       case ST_OACC_PARALLEL:
+       case ST_OACC_KERNELS:
+       case ST_OACC_DATA:
+       case ST_OACC_HOST_DATA:
+         parse_oacc_structured_block (st);
+         break;
+
        case ST_OMP_PARALLEL:
        case ST_OMP_PARALLEL_SECTIONS:
        case ST_OMP_SECTIONS:
@@ -3706,7 +4699,12 @@ parse_executable (gfc_statement st)
        case ST_OMP_CRITICAL:
        case ST_OMP_MASTER:
        case ST_OMP_SINGLE:
+       case ST_OMP_TARGET:
+       case ST_OMP_TARGET_DATA:
+       case ST_OMP_TARGET_TEAMS:
+       case ST_OMP_TEAMS:
        case ST_OMP_TASK:
+       case ST_OMP_TASKGROUP:
          parse_omp_structured_block (st, false);
          break;
 
@@ -3715,16 +4713,31 @@ parse_executable (gfc_statement st)
          parse_omp_structured_block (st, true);
          break;
 
+       case ST_OMP_DISTRIBUTE:
+       case ST_OMP_DISTRIBUTE_PARALLEL_DO:
+       case ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
+       case ST_OMP_DISTRIBUTE_SIMD:
        case ST_OMP_DO:
+       case ST_OMP_DO_SIMD:
        case ST_OMP_PARALLEL_DO:
+       case ST_OMP_PARALLEL_DO_SIMD:
+       case ST_OMP_SIMD:
+       case ST_OMP_TARGET_TEAMS_DISTRIBUTE:
+       case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
+       case ST_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+       case ST_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
+       case ST_OMP_TEAMS_DISTRIBUTE:
+       case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
+       case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
+       case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
          st = parse_omp_do (st);
          if (st == ST_IMPLIED_ENDDO)
            return st;
          continue;
 
        case ST_OMP_ATOMIC:
-         parse_omp_atomic ();
-         break;
+         st = parse_omp_atomic ();
+         continue;
 
        default:
          return st;
@@ -3745,7 +4758,6 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
   gfc_symtree *st;
   gfc_symbol *old_sym;
 
-  sym->attr.referenced = 1;
   for (ns = siblings; ns; ns = ns->sibling)
     {
       st = gfc_find_symtree (ns->sym_root, sym->name);
@@ -3753,6 +4765,12 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
       if (!st || (st->n.sym->attr.dummy && ns == st->n.sym->ns))
        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
            && !old_sym->attr.contained
@@ -3774,16 +4792,14 @@ 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:
@@ -3838,13 +4854,13 @@ parse_contained (int module)
          if (!module)
            {
              if (gfc_get_symbol (gfc_new_block->name, parent_ns, &sym))
-               gfc_error ("Contained procedure '%s' at %C is already "
+               gfc_error ("Contained procedure %qs at %C is already "
                           "ambiguous", gfc_new_block->name);
              else
                {
-                 if (gfc_add_procedure (&sym->attr, PROC_INTERNAL, sym->name,
-                                        &gfc_new_block->declared_at) ==
-                     SUCCESS)
+                 if (gfc_add_procedure (&sym->attr, PROC_INTERNAL, 
+                                        sym->name, 
+                                        &gfc_new_block->declared_at))
                    {
                      if (st == ST_FUNCTION)
                        gfc_add_function (&sym->attr, sym->name,
@@ -3863,7 +4879,12 @@ parse_contained (int module)
          /* Mark this as a contained function, so it isn't replaced
             by other module functions.  */
          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);
 
@@ -3885,6 +4906,7 @@ parse_contained (int module)
        case ST_END_PROGRAM:
        case ST_END_SUBROUTINE:
          accept_statement (st);
+         gfc_current_ns->code = s1.head;
          break;
 
        default:
@@ -3912,7 +4934,7 @@ parse_contained (int module)
 
   pop_state ();
   if (!contains_statements)
-    gfc_notify_std (GFC_STD_F2008, "Fortran 2008: CONTAINS statement without "
+    gfc_notify_std (GFC_STD_F2008, "CONTAINS statement without "
                    "FUNCTION or SUBROUTINE statement at %C");
 }
 
@@ -3984,13 +5006,14 @@ contains:
     if (p->state == COMP_CONTAINS)
       n++;
 
-  if (gfc_find_state (COMP_MODULE) == SUCCESS)
+  if (gfc_find_state (COMP_MODULE) == true)
     n--;
 
   if (n > 0)
     {
       gfc_error ("CONTAINS statement at %C is already in a contained "
                 "program unit");
+      reject_statement ();
       st = next_statement ();
       goto loop;
     }
@@ -3999,6 +5022,13 @@ contains:
 
 done:
   gfc_current_ns->code = gfc_state_stack->head;
+  if (gfc_state_stack->state == COMP_PROGRAM
+      || gfc_state_stack->state == COMP_MODULE 
+      || gfc_state_stack->state == COMP_SUBROUTINE 
+      || gfc_state_stack->state == COMP_FUNCTION
+      || gfc_state_stack->state == COMP_BLOCK)
+    gfc_current_ns->oacc_declare_clauses 
+      = gfc_state_stack->ext.oacc_declare_clauses;
 }
 
 
@@ -4038,8 +5068,12 @@ gfc_global_used (gfc_gsymbol *sym, locus *where)
       name = NULL;
     }
 
-  gfc_error("Global name '%s' at %L is already being used as a %s at %L",
-             sym->name, where, name, &sym->where);
+  if (sym->binding_label)
+    gfc_error ("Global binding name %qs at %L is already being used as a %s "
+              "at %L", sym->binding_label, where, name, &sym->where);
+  else
+    gfc_error ("Global name %qs at %L is already being used as a %s at %L",
+              sym->name, where, name, &sym->where);
 }
 
 
@@ -4072,11 +5106,11 @@ parse_block_data (void)
       s = gfc_get_gsymbol (gfc_new_block->name);
       if (s->defined
          || (s->type != GSYM_UNKNOWN && s->type != GSYM_BLOCK_DATA))
-       gfc_global_used(s, NULL);
+       gfc_global_used (s, &gfc_new_block->declared_at);
       else
        {
         s->type = GSYM_BLOCK_DATA;
-        s->where = gfc_current_locus;
+        s->where = gfc_new_block->declared_at;
         s->defined = 1;
        }
     }
@@ -4100,19 +5134,21 @@ parse_module (void)
 {
   gfc_statement st;
   gfc_gsymbol *s;
+  bool error;
 
   s = gfc_get_gsymbol (gfc_new_block->name);
   if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_MODULE))
-    gfc_global_used(s, NULL);
+    gfc_global_used (s, &gfc_new_block->declared_at);
   else
     {
       s->type = GSYM_MODULE;
-      s->where = gfc_current_locus;
+      s->where = gfc_new_block->declared_at;
       s->defined = 1;
     }
 
   st = parse_spec (ST_NONE);
 
+  error = false;
 loop:
   switch (st)
     {
@@ -4131,34 +5167,73 @@ loop:
       gfc_error ("Unexpected %s statement in MODULE at %C",
                 gfc_ascii_statement (st));
 
+      error = true;
       reject_statement ();
       st = next_statement ();
       goto loop;
     }
 
-  s->ns = gfc_current_ns;
+  /* Make sure not to free the namespace twice on error.  */
+  if (!error)
+    s->ns = gfc_current_ns;
 }
 
 
 /* Add a procedure name to the global symbol table.  */
 
 static void
-add_global_procedure (int sub)
+add_global_procedure (bool sub)
 {
   gfc_gsymbol *s;
 
-  s = gfc_get_gsymbol(gfc_new_block->name);
+  /* Only in Fortran 2003: For procedures with a binding label also the Fortran
+     name is a global identifier.  */
+  if (!gfc_new_block->binding_label || gfc_notification_std (GFC_STD_F2008))
+    {
+      s = gfc_get_gsymbol (gfc_new_block->name);
 
-  if (s->defined
-      || (s->type != GSYM_UNKNOWN
-         && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
-    gfc_global_used(s, NULL);
-  else
+      if (s->defined
+         || (s->type != GSYM_UNKNOWN
+             && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
+       {
+         gfc_global_used (s, &gfc_new_block->declared_at);
+         /* Silence follow-up errors.  */
+         gfc_new_block->binding_label = NULL;
+       }
+      else
+       {
+         s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
+         s->sym_name = gfc_new_block->name;
+         s->where = gfc_new_block->declared_at;
+         s->defined = 1;
+         s->ns = gfc_current_ns;
+       }
+    }
+
+  /* Don't add the symbol multiple times.  */
+  if (gfc_new_block->binding_label
+      && (!gfc_notification_std (GFC_STD_F2008)
+          || strcmp (gfc_new_block->name, gfc_new_block->binding_label) != 0))
     {
-      s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
-      s->where = gfc_current_locus;
-      s->defined = 1;
-      s->ns = gfc_current_ns;
+      s = gfc_get_gsymbol (gfc_new_block->binding_label);
+
+      if (s->defined
+         || (s->type != GSYM_UNKNOWN
+             && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
+       {
+         gfc_global_used (s, &gfc_new_block->declared_at);
+         /* Silence follow-up errors.  */
+         gfc_new_block->binding_label = NULL;
+       }
+      else
+       {
+         s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
+         s->sym_name = gfc_new_block->name;
+         s->binding_label = gfc_new_block->binding_label;
+         s->where = gfc_new_block->declared_at;
+         s->defined = 1;
+         s->ns = gfc_current_ns;
+       }
     }
 }
 
@@ -4175,19 +5250,18 @@ add_global_program (void)
   s = gfc_get_gsymbol (gfc_new_block->name);
 
   if (s->defined || (s->type != GSYM_UNKNOWN && s->type != GSYM_PROGRAM))
-    gfc_global_used(s, NULL);
+    gfc_global_used (s, &gfc_new_block->declared_at);
   else
     {
       s->type = GSYM_PROGRAM;
-      s->where = gfc_current_locus;
+      s->where = gfc_new_block->declared_at;
       s->defined = 1;
       s->ns = gfc_current_ns;
     }
 }
 
 
-/* Resolve all the program units when whole file scope option
-   is active. */
+/* Resolve all the program units.  */
 static void
 resolve_all_program_units (gfc_namespace *gfc_global_ns_list)
 {
@@ -4195,7 +5269,12 @@ 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_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;
@@ -4223,9 +5302,8 @@ clean_up_modules (gfc_gsymbol *gsym)
 }
 
 
-/* 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.  */
+/* Translate all the program units. 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)
 {
@@ -4234,8 +5312,28 @@ translate_all_program_units (gfc_namespace *gfc_global_ns_list)
   gfc_current_ns = gfc_global_ns_list;
   gfc_get_errors (NULL, &errors);
 
+  /* 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);
@@ -4246,7 +5344,16 @@ translate_all_program_units (gfc_namespace *gfc_global_ns_list)
   gfc_current_ns = gfc_global_ns_list;
   for (;gfc_current_ns;)
     {
-      gfc_namespace *ns = gfc_current_ns->sibling;
+      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;
@@ -4258,7 +5365,7 @@ translate_all_program_units (gfc_namespace *gfc_global_ns_list)
 
 /* Top level parser.  */
 
-gfc_try
+bool
 gfc_parse_file (void)
 {
   int seen_program, errors_before, errors;
@@ -4282,13 +5389,14 @@ gfc_parse_file (void)
   gfc_statement_label = NULL;
 
   if (setjmp (eof_buf))
-    return FAILURE;    /* Come here on unexpected EOF */
+    return false;      /* Come here on unexpected EOF */
 
   /* Prepare the global namespace that will contain the
      program units.  */
   gfc_global_ns_list = next = NULL;
 
   seen_program = 0;
+  errors_before = 0;
 
   /* Exit early for empty files.  */
   if (gfc_at_eof ())
@@ -4314,26 +5422,23 @@ loop:
       accept_statement (st);
       add_global_program ();
       parse_progunit (ST_NONE);
-      if (gfc_option.flag_whole_file)
-       goto prog_units;
+      goto prog_units;
       break;
 
     case ST_SUBROUTINE:
-      add_global_procedure (1);
+      add_global_procedure (true);
       push_state (&s, COMP_SUBROUTINE, gfc_new_block);
       accept_statement (st);
       parse_progunit (ST_NONE);
-      if (gfc_option.flag_whole_file)
-       goto prog_units;
+      goto prog_units;
       break;
 
     case ST_FUNCTION:
-      add_global_procedure (0);
+      add_global_procedure (false);
       push_state (&s, COMP_FUNCTION, gfc_new_block);
       accept_statement (st);
       parse_progunit (ST_NONE);
-      if (gfc_option.flag_whole_file)
-       goto prog_units;
+      goto prog_units;
       break;
 
     case ST_BLOCK_DATA:
@@ -4360,8 +5465,7 @@ 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;
+      goto prog_units;
       break;
     }
 
@@ -4371,24 +5475,16 @@ loop:
   gfc_resolve (gfc_current_ns);
 
   /* Dump the parse tree if requested.  */
-  if (gfc_option.dump_parse_tree)
+  if (flag_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);
-      pop_state ();
-      if (!gfc_option.flag_whole_file)
-       gfc_done_2 ();
-      else
-       {
-         gfc_current_ns->derived_types = gfc_derived_types;
-         gfc_derived_types = NULL;
-         gfc_current_ns = NULL;
-       }
+      gfc_current_ns->derived_types = gfc_derived_types;
+      gfc_derived_types = NULL;
+      goto prog_units;
     }
   else
     {
@@ -4406,7 +5502,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;
 
@@ -4417,29 +5517,26 @@ prog_units:
 
   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_parse_tree ? gfc_global_ns_list : NULL;
+       = flag_dump_fortran_original ? gfc_global_ns_list : NULL;
 
   for (; gfc_current_ns; gfc_current_ns = gfc_current_ns->sibling)
-    {
-      gfc_dump_parse_tree (gfc_current_ns, stdout);
-      fputs ("------------------------------------------\n\n", stdout);
-    }
+    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);
 
-termination:
-
   gfc_end_source_files ();
-  return SUCCESS;
+  return true;
 
 duplicate_main:
   /* If we see a duplicate main program, shut down.  If the second
@@ -4448,5 +5545,30 @@ duplicate_main:
   gfc_error ("Two main PROGRAMs at %L and %C", &prog_locus);
   reject_statement ();
   gfc_done_2 ();
-  return SUCCESS;
+  return true;
+}
+
+/* Return true if this state data represents an OpenACC region.  */
+bool
+is_oacc (gfc_state_data *sd)
+{
+  switch (sd->construct->op)
+    {
+    case EXEC_OACC_PARALLEL_LOOP:
+    case EXEC_OACC_PARALLEL:
+    case EXEC_OACC_KERNELS_LOOP:
+    case EXEC_OACC_KERNELS:
+    case EXEC_OACC_DATA:
+    case EXEC_OACC_HOST_DATA:
+    case EXEC_OACC_LOOP:
+    case EXEC_OACC_UPDATE:
+    case EXEC_OACC_WAIT:
+    case EXEC_OACC_CACHE:
+    case EXEC_OACC_ENTER_DATA:
+    case EXEC_OACC_EXIT_DATA:
+      return true;
+
+    default:
+      return false;
+    }
 }