]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/parser.c
Wrap option names in gcc internal messages with %< and %>.
[thirdparty/gcc.git] / gcc / cp / parser.c
index 49d476b383fb37f38d9191ac9d50373b37331a7f..f95111169ed3ebfe1c6ac42c2f33882faed2ff49 100644 (file)
@@ -1,5 +1,5 @@
 /* -*- C++ -*- Parser.
-   Copyright (C) 2000-2018 Free Software Foundation, Inc.
+   Copyright (C) 2000-2019 Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -43,7 +43,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "context.h"
 #include "gcc-rich-location.h"
 #include "tree-iterator.h"
-#include "c-family/name-hint.h"
+#include "cp-name-hint.h"
+#include "memmodel.h"
 
 \f
 /* The lexer.  */
@@ -535,9 +536,12 @@ cp_debug_parser (FILE *file, cp_parser *parser)
                              parser->allow_non_integral_constant_expression_p);
   cp_debug_print_flag (file, "Seen non-constant expression",
                              parser->non_integral_constant_expression_p);
-  cp_debug_print_flag (file, "Local names and 'this' forbidden in "
-                             "current context",
-                             parser->local_variables_forbidden_p);
+  cp_debug_print_flag (file, "Local names forbidden in current context",
+                             (parser->local_variables_forbidden_p
+                              & LOCAL_VARS_FORBIDDEN));
+  cp_debug_print_flag (file, "'this' forbidden in current context",
+                             (parser->local_variables_forbidden_p
+                              & THIS_FORBIDDEN));
   cp_debug_print_flag (file, "In unbraced linkage specification",
                              parser->in_unbraced_linkage_specification_p);
   cp_debug_print_flag (file, "Parsing a declarator",
@@ -556,8 +560,6 @@ cp_debug_parser (FILE *file, cp_parser *parser)
                              parser->in_statement & IN_IF_STMT);
   cp_debug_print_flag (file, "Parsing a type-id in an expression "
                              "context", parser->in_type_id_in_expr_p);
-  cp_debug_print_flag (file, "Declarations are implicitly extern \"C\"",
-                             parser->implicit_extern_c);
   cp_debug_print_flag (file, "String expressions should be translated "
                              "to execution character set",
                              parser->translate_strings_p);
@@ -922,14 +924,6 @@ cp_lexer_nth_token_is_keyword (cp_lexer* lexer, size_t n, enum rid keyword)
   return cp_lexer_peek_nth_token (lexer, n)->keyword == keyword;
 }
 
-/* Return true if the next token is not the indicated KEYWORD.  */
-
-static inline bool
-cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword)
-{
-  return cp_lexer_peek_token (lexer)->keyword != keyword;
-}
-
 /* Return true if KEYWORD can start a decl-specifier.  */
 
 bool
@@ -954,6 +948,7 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
     case RID_TYPENAME:
       /* Simple type specifiers.  */
     case RID_CHAR:
+    case RID_CHAR8:
     case RID_CHAR16:
     case RID_CHAR32:
     case RID_WCHAR:
@@ -1462,7 +1457,7 @@ make_declarator (cp_declarator_kind kind)
 
 static cp_declarator *
 make_id_declarator (tree qualifying_scope, tree unqualified_name,
-                   special_function_kind sfk)
+                   special_function_kind sfk, location_t id_location)
 {
   cp_declarator *declarator;
 
@@ -1487,7 +1482,8 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name,
   declarator->u.id.qualifying_scope = qualifying_scope;
   declarator->u.id.unqualified_name = unqualified_name;
   declarator->u.id.sfk = sfk;
-  
+  declarator->id_loc = id_location;
+
   return declarator;
 }
 
@@ -1651,7 +1647,7 @@ declarator_can_be_parameter_pack (cp_declarator *declarator)
 
   /* Search for a declarator name, or any other declarator that goes
      after the point where the ellipsis could appear in a parameter
-     pack. If we find any of these, then this declarator can not be
+     pack. If we find any of these, then this declarator cannot be
      made into a parameter pack.  */
   bool found = false;
   while (declarator && !found)
@@ -1799,7 +1795,9 @@ enum
      constexpr.  */
   CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8,
   /* When parsing a decl-specifier-seq, only allow mutable or constexpr.  */
-  CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10
+  CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10,
+  /* When parsing a decl-specifier-seq, allow missing typename.  */
+  CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20
 };
 
 /* This type is used for parameters and variables which hold
@@ -2023,8 +2021,7 @@ static cp_expr cp_parser_userdef_numeric_literal
 
 /* Basic concepts [gram.basic]  */
 
-static bool cp_parser_translation_unit
-  (cp_parser *);
+static void cp_parser_translation_unit (cp_parser *);
 
 /* Expressions [gram.expr]  */
 
@@ -2057,6 +2054,8 @@ static cp_expr cp_parser_unary_expression
   (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false);
 static enum tree_code cp_parser_unary_operator
   (cp_token *);
+static tree cp_parser_has_attribute_expression
+  (cp_parser *);
 static tree cp_parser_new_expression
   (cp_parser *);
 static vec<tree, va_gc> *cp_parser_new_placement
@@ -2121,7 +2120,7 @@ static tree cp_parser_for
 static tree cp_parser_c_for
   (cp_parser *, tree, tree, bool, unsigned short);
 static tree cp_parser_range_for
-  (cp_parser *, tree, tree, tree, bool, unsigned short);
+  (cp_parser *, tree, tree, tree, bool, unsigned short, bool);
 static void do_range_for_auto_deduction
   (tree, tree);
 static tree cp_parser_perform_range_for_lookup
@@ -2144,6 +2143,8 @@ static void cp_parser_declaration_seq_opt
   (cp_parser *);
 static void cp_parser_declaration
   (cp_parser *);
+static void cp_parser_toplevel_declaration
+  (cp_parser *);
 static void cp_parser_block_declaration
   (cp_parser *, bool);
 static void cp_parser_simple_declaration
@@ -2161,8 +2162,6 @@ static tree cp_parser_simple_type_specifier
   (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
 static tree cp_parser_type_name
   (cp_parser *, bool);
-static tree cp_parser_type_name
-  (cp_parser *);
 static tree cp_parser_nonclass_name 
   (cp_parser* parser);
 static tree cp_parser_elaborated_type_specifier
@@ -2203,12 +2202,15 @@ static tree cp_parser_decomposition_declaration
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *,
-   bool, bool, int, bool *, tree *, location_t *, tree *);
+  (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *,
+   vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *,
+   location_t *, tree *);
 static cp_declarator *cp_parser_declarator
-  (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool);
+  (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool *,
+   bool, bool, bool);
 static cp_declarator *cp_parser_direct_declarator
-  (cp_parser *, cp_parser_declarator_kind, int *, bool, bool);
+  (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool, bool,
+   bool);
 static enum tree_code cp_parser_ptr_operator
   (cp_parser *, tree *, cp_cv_quals *, tree *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
@@ -2224,20 +2226,20 @@ static tree cp_parser_late_return_type_opt
 static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
-  (cp_parser *);
+  (cp_parser *, cp_parser_flags = CP_PARSER_FLAGS_NONE, location_t * = NULL);
 static tree cp_parser_template_type_arg
   (cp_parser *);
 static tree cp_parser_trailing_type_id (cp_parser *);
 static tree cp_parser_type_id_1
-  (cp_parser *, bool, bool);
+  (cp_parser *, cp_parser_flags, bool, bool, location_t *);
 static void cp_parser_type_specifier_seq
-  (cp_parser *, bool, bool, cp_decl_specifier_seq *);
+  (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *);
 static tree cp_parser_parameter_declaration_clause
-  (cp_parser *);
+  (cp_parser *, cp_parser_flags);
 static tree cp_parser_parameter_declaration_list
-  (cp_parser *);
+  (cp_parser *, cp_parser_flags);
 static cp_parameter_declarator *cp_parser_parameter_declaration
-  (cp_parser *, bool, bool *);
+  (cp_parser *, cp_parser_flags, bool, bool *);
 static tree cp_parser_default_argument 
   (cp_parser *, bool);
 static void cp_parser_function_body
@@ -2249,7 +2251,7 @@ static cp_expr cp_parser_initializer_clause
 static cp_expr cp_parser_braced_list
   (cp_parser*, bool*);
 static vec<constructor_elt, va_gc> *cp_parser_initializer_list
-  (cp_parser *, bool *);
+  (cp_parser *, bool *, bool *);
 
 static void cp_parser_ctor_initializer_opt_and_function_body
   (cp_parser *, bool);
@@ -2317,7 +2319,7 @@ static tree cp_parser_mem_initializer_id
 static cp_expr cp_parser_operator_function_id
   (cp_parser *);
 static cp_expr cp_parser_operator
-  (cp_parser *);
+  (cp_parser *, location_t);
 
 /* Templates [gram.temp] */
 
@@ -2388,7 +2390,7 @@ static tree cp_parser_attributes_opt
 static tree cp_parser_gnu_attributes_opt
   (cp_parser *);
 static tree cp_parser_gnu_attribute_list
-  (cp_parser *);
+  (cp_parser *, bool = false);
 static tree cp_parser_std_attribute
   (cp_parser *, tree);
 static tree cp_parser_std_attribute_spec
@@ -3286,7 +3288,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
                decl);
       if (DECL_CLASS_TEMPLATE_P (decl) && cxx_dialect < cxx17)
        inform (location, "class template argument deduction is only available "
-               "with -std=c++17 or -std=gnu++17");
+               "with %<-std=c++17%> or %<-std=gnu++17%>");
       inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
     }
   else if (TREE_CODE (id) == BIT_NOT_EXPR)
@@ -3301,13 +3303,13 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
       name_hint hint;
       if (TREE_CODE (id) == IDENTIFIER_NODE)
        hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME, location);
-      if (hint)
+      if (const char *suggestion = hint.suggestion ())
        {
          gcc_rich_location richloc (location);
-         richloc.add_fixit_replace (hint.suggestion ());
+         richloc.add_fixit_replace (suggestion);
          error_at (&richloc,
                    "%qE does not name a type; did you mean %qs?",
-                   id, hint.suggestion ());
+                   id, suggestion);
        }
       else
        error_at (location, "%qE does not name a type", id);
@@ -3320,17 +3322,17 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
         The user should have said "typename A<T>::X".  */
       if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_CONSTEXPR])
        inform (location, "C++11 %<constexpr%> only available with "
-               "-std=c++11 or -std=gnu++11");
+               "%<-std=c++11%> or %<-std=gnu++11%>");
       else if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_NOEXCEPT])
        inform (location, "C++11 %<noexcept%> only available with "
-               "-std=c++11 or -std=gnu++11");
+               "%<-std=c++11%> or %<-std=gnu++11%>");
       else if (cxx_dialect < cxx11
               && TREE_CODE (id) == IDENTIFIER_NODE
               && id_equal (id, "thread_local"))
        inform (location, "C++11 %<thread_local%> only available with "
-               "-std=c++11 or -std=gnu++11");
+               "%<-std=c++11%> or %<-std=gnu++11%>");
       else if (!flag_concepts && id == ridpointers[(int)RID_CONCEPT])
-       inform (location, "%<concept%> only available with -fconcepts");
+       inform (location, "%<concept%> only available with %<-fconcepts%>");
       else if (processing_template_decl && current_class_type
               && TYPE_BINFO (current_class_type))
        {
@@ -3373,23 +3375,53 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
        {
          auto_diagnostic_group d;
+         name_hint hint;
+         if (decl == error_mark_node)
+           hint = suggest_alternative_in_explicit_scope (location, id,
+                                                         parser->scope);
+         const char *suggestion = hint.suggestion ();
+         gcc_rich_location richloc (location_of (id));
+         if (suggestion)
+           richloc.add_fixit_replace (suggestion);
          if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
-           error_at (location_of (id),
-                     "%qE in namespace %qE does not name a template type",
-                     id, parser->scope);
+           {
+             if (suggestion)
+               error_at (&richloc,
+                         "%qE in namespace %qE does not name a template"
+                         " type; did you mean %qs?",
+                         id, parser->scope, suggestion);
+             else
+               error_at (&richloc,
+                         "%qE in namespace %qE does not name a template type",
+                         id, parser->scope);
+           }
          else if (TREE_CODE (id) == TEMPLATE_ID_EXPR)
-           error_at (location_of (id),
-                     "%qE in namespace %qE does not name a template type",
-                     TREE_OPERAND (id, 0), parser->scope);
+           {
+             if (suggestion)
+               error_at (&richloc,
+                         "%qE in namespace %qE does not name a template"
+                         " type; did you mean %qs?",
+                         TREE_OPERAND (id, 0), parser->scope, suggestion);
+             else
+               error_at (&richloc,
+                         "%qE in namespace %qE does not name a template"
+                         " type",
+                         TREE_OPERAND (id, 0), parser->scope);
+           }
          else
-           error_at (location_of (id),
-                     "%qE in namespace %qE does not name a type",
-                     id, parser->scope);
+           {
+             if (suggestion)
+               error_at (&richloc,
+                         "%qE in namespace %qE does not name a type"
+                         "; did you mean %qs?",
+                         id, parser->scope, suggestion);
+             else
+               error_at (&richloc,
+                         "%qE in namespace %qE does not name a type",
+                         id, parser->scope);
+           }
          if (DECL_P (decl))
            inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
-         else if (decl == error_mark_node)
-           suggest_alternative_in_explicit_scope (location, id,
-                                                  parser->scope);
        }
       else if (CLASS_TYPE_P (parser->scope)
               && constructor_name_p (id, parser->scope))
@@ -3405,8 +3437,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
       else if (TYPE_P (parser->scope)
               && dependent_scope_p (parser->scope))
        {
+         gcc_rich_location richloc (location);
+         richloc.add_fixit_insert_before ("typename ");
          if (TREE_CODE (parser->scope) == TYPENAME_TYPE)
-           error_at (location,
+           error_at (&richloc,
                      "need %<typename%> before %<%T::%D::%E%> because "
                      "%<%T::%D%> is a dependent scope",
                      TYPE_CONTEXT (parser->scope),
@@ -3415,7 +3449,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
                      TYPE_CONTEXT (parser->scope),
                      TYPENAME_TYPE_FULLNAME (parser->scope));
          else
-           error_at (location, "need %<typename%> before %<%T::%E%> because "
+           error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
                      "%qT is a dependent scope",
                      parser->scope, id, parser->scope);
        }
@@ -3529,8 +3563,11 @@ cp_parser_skip_to_closing_parenthesis_1 (cp_parser *parser,
 
       switch (token->type)
        {
-       case CPP_EOF:
        case CPP_PRAGMA_EOL:
+         if (!parser->lexer->in_pragma)
+           break;
+         /* FALLTHRU */
+       case CPP_EOF:
          /* If we've run out of tokens, then there is no closing `)'.  */
          return 0;
 
@@ -3625,8 +3662,11 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
 
       switch (token->type)
        {
-       case CPP_EOF:
        case CPP_PRAGMA_EOL:
+         if (!parser->lexer->in_pragma)
+           break;
+         /* FALLTHRU */
+       case CPP_EOF:
          /* If we've run out of tokens, stop.  */
          return;
 
@@ -3715,8 +3755,11 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
 
       switch (token->type)
        {
-       case CPP_EOF:
        case CPP_PRAGMA_EOL:
+         if (!parser->lexer->in_pragma)
+           break;
+         /* FALLTHRU */
+       case CPP_EOF:
          /* If we've run out of tokens, stop.  */
          return;
 
@@ -3765,8 +3808,11 @@ cp_parser_skip_to_closing_brace (cp_parser *parser)
 
       switch (token->type)
        {
-       case CPP_EOF:
        case CPP_PRAGMA_EOL:
+         if (!parser->lexer->in_pragma)
+           break;
+         /* FALLTHRU */
+       case CPP_EOF:
          /* If we've run out of tokens, stop.  */
          return false;
 
@@ -3910,7 +3956,7 @@ cp_parser_new (void)
   parser->non_integral_constant_expression_p = false;
 
   /* Local variable names are not forbidden.  */
-  parser->local_variables_forbidden_p = false;
+  parser->local_variables_forbidden_p = 0;
 
   /* We are not processing an `extern "C"' declaration.  */
   parser->in_unbraced_linkage_specification_p = false;
@@ -3930,9 +3976,6 @@ cp_parser_new (void)
   /* We are not parsing a type-id inside an expression.  */
   parser->in_type_id_in_expr_p = false;
 
-  /* Declarations aren't implicitly extern "C".  */
-  parser->implicit_extern_c = false;
-
   /* String literals should be translated to the execution character set.  */
   parser->translate_strings_p = true;
 
@@ -4040,6 +4083,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
   tree value;
   size_t count;
   struct obstack str_ob;
+  struct obstack loc_ob;
   cpp_string str, istr, *strs;
   cp_token *tok;
   enum cpp_ttype type, curr_type;
@@ -4096,6 +4140,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
     {
       location_t last_tok_loc = tok->location;
       gcc_obstack_init (&str_ob);
+      gcc_obstack_init (&loc_ob);
       count = 0;
 
       do
@@ -4133,7 +4178,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
              else if (curr_type != CPP_STRING)
                {
                  rich_location rich_loc (line_table, tok->location);
-                 rich_loc.add_range (last_tok_loc, false);
+                 rich_loc.add_range (last_tok_loc);
                  error_at (&rich_loc,
                            "unsupported non-standard concatenation "
                            "of string literals");
@@ -4141,6 +4186,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
            }
 
          obstack_grow (&str_ob, &str, sizeof (cpp_string));
+         obstack_grow (&loc_ob, &tok->location, sizeof (location_t));
 
          last_tok_loc = tok->location;
 
@@ -4179,14 +4225,25 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
     {
       value = build_string (istr.len, (const char *)istr.text);
       free (CONST_CAST (unsigned char *, istr.text));
+      if (count > 1)
+       {
+         location_t *locs = (location_t *)obstack_finish (&loc_ob);
+         gcc_assert (g_string_concat_db);
+         g_string_concat_db->record_string_concatenation (count, locs);
+       }
 
       switch (type)
        {
        default:
        case CPP_STRING:
-       case CPP_UTF8STRING:
          TREE_TYPE (value) = char_array_type_node;
          break;
+       case CPP_UTF8STRING:
+         if (flag_char8_t)
+           TREE_TYPE (value) = char8_array_type_node;
+         else
+           TREE_TYPE (value) = char_array_type_node;
+         break;
        case CPP_STRING16:
          TREE_TYPE (value) = char16_array_type_node;
          break;
@@ -4215,7 +4272,10 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
     value = error_mark_node;
 
   if (count > 1)
-    obstack_free (&str_ob, 0);
+    {
+      obstack_free (&str_ob, 0);
+      obstack_free (&loc_ob, 0);
+    }
 
   return cp_expr (value, loc);
 }
@@ -4225,20 +4285,21 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
 static tree
 lookup_literal_operator (tree name, vec<tree, va_gc> *args)
 {
-  tree decl;
-  decl = lookup_name (name);
+  tree decl = lookup_name (name);
   if (!decl || !is_overloaded_fn (decl))
     return error_mark_node;
 
   for (lkp_iterator iter (decl); iter; ++iter)
     {
-      unsigned int ix;
-      bool found = true;
       tree fn = *iter;
-      tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
-      if (parmtypes != NULL_TREE)
+
+      if (tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (fn)))
        {
-         for (ix = 0; ix < vec_safe_length (args) && parmtypes != NULL_TREE;
+         unsigned int ix;
+         bool found = true;
+
+         for (ix = 0;
+              found && ix < vec_safe_length (args) && parmtypes != NULL_TREE;
               ++ix, parmtypes = TREE_CHAIN (parmtypes))
            {
              tree tparm = TREE_VALUE (parmtypes);
@@ -4251,6 +4312,7 @@ lookup_literal_operator (tree name, vec<tree, va_gc> *args)
                                       TREE_TYPE (targ))))
                found = false;
            }
+
          if (found
              && ix == vec_safe_length (args)
              /* May be this should be sufficient_parms_p instead,
@@ -4489,7 +4551,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
                "GNU built-in suffix");
     }
   else if (!ext)
-    inform (token->location, "use -fext-numeric-literals "
+    inform (token->location, "use %<-fext-numeric-literals%> "
            "to enable more built-in suffixes");
 
   if (kind == DK_ERROR)
@@ -4533,40 +4595,47 @@ cp_parser_userdef_string_literal (tree literal)
   tree value = USERDEF_LITERAL_VALUE (literal);
   int len = TREE_STRING_LENGTH (value)
        / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1;
-  tree decl, result;
-  vec<tree, va_gc> *args;
+  tree decl;
 
   /* Build up a call to the user-defined operator.  */
   /* Lookup the name we got back from the id-expression.  */
-  args = make_tree_vector ();
+  releasing_vec rargs;
+  vec<tree, va_gc> *&args = rargs.get_ref();
   vec_safe_push (args, value);
   vec_safe_push (args, build_int_cst (size_type_node, len));
   decl = lookup_literal_operator (name, args);
 
   if (decl && decl != error_mark_node)
-    {
-      result = finish_call_expr (decl, &args, false, true,
-                                tf_warning_or_error);
-      release_tree_vector (args);
-      return result;
-    }
-  release_tree_vector (args);
+    return finish_call_expr (decl, &args, false, true,
+                            tf_warning_or_error);
 
-  /* Look for a template function with typename parameter CharT
-     and parameter pack CharT...  Call the function with
-     template parameter characters representing the string.  */
-  args = make_tree_vector ();
+  /* Look for a suitable template function, either (C++20) with a single
+     parameter of class type, or (N3599) with typename parameter CharT and
+     parameter pack CharT...  */
+  args->truncate (0);
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
-      tree tmpl_args = make_string_pack (value);
+      /* Use resolve_nondeduced_context to try to choose one form of template
+        or the other.  */
+      tree tmpl_args = make_tree_vec (1);
+      TREE_VEC_ELT (tmpl_args, 0) = value;
       decl = lookup_template_function (decl, tmpl_args);
-      result = finish_call_expr (decl, &args, false, true,
-                                tf_warning_or_error);
-      release_tree_vector (args);
-      return result;
+      tree res = resolve_nondeduced_context (decl, tf_none);
+      if (DECL_P (res))
+       decl = res;
+      else
+       {
+         TREE_OPERAND (decl, 1) = make_string_pack (value);
+         res = resolve_nondeduced_context (decl, tf_none);
+         if (DECL_P (res))
+           decl = res;
+       }
+      if (!DECL_P (decl) && cxx_dialect > cxx17)
+       TREE_OPERAND (decl, 1) = tmpl_args;
+      return finish_call_expr (decl, &args, false, true,
+                              tf_warning_or_error);
     }
-  release_tree_vector (args);
 
   error ("unable to find string literal operator %qD with %qT, %qT arguments",
         name, TREE_TYPE (value), size_type_node);
@@ -4579,66 +4648,66 @@ cp_parser_userdef_string_literal (tree literal)
 /* Parse a translation-unit.
 
    translation-unit:
-     declaration-seq [opt]
-
-   Returns TRUE if all went well.  */
+     declaration-seq [opt]  */
 
-static bool
+static void
 cp_parser_translation_unit (cp_parser* parser)
 {
-  /* The address of the first non-permanent object on the declarator
-     obstack.  */
-  static void *declarator_obstack_base;
-
-  bool success;
+  gcc_checking_assert (!cp_error_declarator);
+  
+  /* Create the declarator obstack.  */
+  gcc_obstack_init (&declarator_obstack);
+  /* Create the error declarator.  */
+  cp_error_declarator = make_declarator (cdk_error);
+  /* Create the empty parameter list.  */
+  no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE,
+                                            UNKNOWN_LOCATION);
+  /* Remember where the base of the declarator obstack lies.  */
+  void *declarator_obstack_base = obstack_next_free (&declarator_obstack);
+
+  bool implicit_extern_c = false;
 
-  /* Create the declarator obstack, if necessary.  */
-  if (!cp_error_declarator)
+  for (;;)
     {
-      gcc_obstack_init (&declarator_obstack);
-      /* Create the error declarator.  */
-      cp_error_declarator = make_declarator (cdk_error);
-      /* Create the empty parameter list.  */
-      no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE,
-                                                UNKNOWN_LOCATION);
-      /* Remember where the base of the declarator obstack lies.  */
-      declarator_obstack_base = obstack_next_free (&declarator_obstack);
-    }
-
-  cp_parser_declaration_seq_opt (parser);
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      
+      /* If we're entering or exiting a region that's implicitly
+        extern "C", modify the lang context appropriately.  */
+      if (implicit_extern_c
+         != cp_lexer_peek_token (parser->lexer)->implicit_extern_c)
+       {
+         implicit_extern_c = !implicit_extern_c;
+         if (implicit_extern_c)
+           push_lang_context (lang_name_c);
+         else
+           pop_lang_context ();
+       }
 
-  /* If there are no tokens left then all went well.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
-    {
-      /* Get rid of the token array; we don't need it any more.  */
-      cp_lexer_destroy (parser->lexer);
-      parser->lexer = NULL;
+      if (token->type == CPP_EOF)
+       break;
 
-      /* This file might have been a context that's implicitly extern
-        "C".  If so, pop the lang context.  (Only relevant for PCH.) */
-      if (parser->implicit_extern_c)
+      if (token->type == CPP_CLOSE_BRACE)
        {
-         pop_lang_context ();
-         parser->implicit_extern_c = false;
+         cp_parser_error (parser, "expected declaration");
+         cp_lexer_consume_token (parser->lexer);
+         /* If the next token is now a `;', consume it.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+           cp_lexer_consume_token (parser->lexer);
        }
+      else
+       cp_parser_toplevel_declaration (parser);
+    }
 
-      /* Finish up.  */
-      finish_translation_unit ();
+  /* Get rid of the token array; we don't need it any more.  */
+  cp_lexer_destroy (parser->lexer);
+  parser->lexer = NULL;
 
-      success = true;
-    }
-  else
-    {
-      cp_parser_error (parser, "expected declaration");
-      success = false;
-    }
+  /* The EOF should have reset this. */
+  gcc_checking_assert (!implicit_extern_c);
 
   /* Make sure the declarator obstack was fully cleaned up.  */
   gcc_assert (obstack_next_free (&declarator_obstack)
              == declarator_obstack_base);
-
-  /* All went well.  */
-  return success;
 }
 
 /* Return the appropriate tsubst flags for parsing, possibly in N3276
@@ -5173,7 +5242,8 @@ cp_parser_primary_expression (cp_parser *parser,
          if (!cast_p)
            cp_parser_non_integral_constant_expression (parser, NIC_FLOAT);
        }
-      return cp_expr (token->u.value, token->location);
+      return (cp_expr (token->u.value, token->location)
+             .maybe_add_location_wrapper ());
 
     case CPP_CHAR_USERDEF:
     case CPP_CHAR16_USERDEF:
@@ -5195,9 +5265,10 @@ cp_parser_primary_expression (cp_parser *parser,
       /* ??? Should wide strings be allowed when parser->translate_strings_p
         is false (i.e. in attributes)?  If not, we can kill the third
         argument to cp_parser_string_literal.  */
-      return cp_parser_string_literal (parser,
-                                      parser->translate_strings_p,
-                                      true);
+      return (cp_parser_string_literal (parser,
+                                       parser->translate_strings_p,
+                                       true)
+             .maybe_add_location_wrapper ());
 
     case CPP_OPEN_PAREN:
       /* If we see `( { ' then we are looking at the beginning of
@@ -5260,7 +5331,7 @@ cp_parser_primary_expression (cp_parser *parser,
                && cxx_dialect < cxx17
                && !in_system_header_at (input_location))
              pedwarn (input_location, 0, "fold-expressions only available "
-                      "with -std=c++17 or -std=gnu++17");
+                      "with %<-std=c++17%> or %<-std=gnu++17%>");
          }
        else
          /* Let the front end know that this expression was
@@ -5344,7 +5415,7 @@ cp_parser_primary_expression (cp_parser *parser,
          /* Recognize the `this' keyword.  */
        case RID_THIS:
          cp_lexer_consume_token (parser->lexer);
-         if (parser->local_variables_forbidden_p)
+         if (parser->local_variables_forbidden_p & THIS_FORBIDDEN)
            {
              error_at (token->location,
                        "%<this%> may not be used in this context");
@@ -5401,7 +5472,7 @@ cp_parser_primary_expression (cp_parser *parser,
          {
            tree expression;
            tree type;
-           source_location type_location;
+           location_t type_location;
            location_t start_loc
              = cp_lexer_peek_token (parser->lexer)->location;
            /* The `__builtin_va_arg' construct is used to handle
@@ -5559,7 +5630,7 @@ cp_parser_primary_expression (cp_parser *parser,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
                                          &ambiguous_decls,
-                                         id_expr_token->location);
+                                         id_expression.get_location ());
            /* If the lookup was ambiguous, an error will already have
               been issued.  */
            if (ambiguous_decls)
@@ -5620,31 +5691,23 @@ cp_parser_primary_expression (cp_parser *parser,
                      template <int N> struct A {
                        int a[B<N>::i];
                      };
-                    
+
                   is accepted.  At template-instantiation time, we
                   will check that B<N>::i is actually a constant.  */
                return decl;
              }
            /* Check to see if DECL is a local variable in a context
               where that is forbidden.  */
-           if (parser->local_variables_forbidden_p
+           if ((parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN)
                && local_variable_p (decl))
              {
-               error_at (id_expr_token->location,
+               error_at (id_expression.get_location (),
                          "local variable %qD may not appear in this context",
                          decl.get_value ());
                return error_mark_node;
              }
          }
 
-       if (processing_template_decl)
-         if (tree fns = maybe_get_fns (decl))
-           /* It's too difficult to mark ths in all the places where
-              we know for sure we need to keep the lookup, so do it
-              now.  The cost is extra GC to recycle the lookups
-              resolved at parse time.  */
-           lookup_keep (fns);
-
        decl = (finish_id_expression
                (id_expression, decl, parser->scope,
                 idk,
@@ -5657,7 +5720,21 @@ cp_parser_primary_expression (cp_parser *parser,
                 id_expression.get_location ()));
        if (error_msg)
          cp_parser_error (parser, error_msg);
-       decl.set_location (id_expr_token->location);
+       /* Build a location for an id-expression of the form:
+            ::ns::id
+             ~~~~~~^~
+         or:
+            id
+            ^~
+          i.e. from the start of the first token to the end of the final
+          token, with the caret at the start of the unqualified-id.  */
+       location_t caret_loc = get_pure_location (id_expression.get_location ());
+       location_t start_loc = get_start (id_expr_token->location);
+       location_t finish_loc = get_finish (id_expression.get_location ());
+       location_t combined_loc
+         = make_location (caret_loc, start_loc, finish_loc);
+
+       decl.set_location (combined_loc);
        return decl;
       }
 
@@ -5899,6 +5976,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        tree object_scope;
        tree scope;
        bool done;
+       location_t tilde_loc = token->location;
 
        /* Consume the `~' token.  */
        cp_lexer_consume_token (parser->lexer);
@@ -5961,9 +6039,18 @@ cp_parser_unqualified_id (cp_parser* parser,
          }
        gcc_assert (!scope || TYPE_P (scope));
 
+       token = cp_lexer_peek_token (parser->lexer);
+
+       /* Create a location with caret == start at the tilde,
+          finishing at the end of the peeked token, e.g:
+          ~token
+          ^~~~~~.  */
+       location_t loc
+         = make_location (tilde_loc, tilde_loc, token->location);
+
        /* If the name is of the form "X::~X" it's OK even if X is a
           typedef.  */
-       token = cp_lexer_peek_token (parser->lexer);
+
        if (scope
            && token->type == CPP_NAME
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
@@ -5973,18 +6060,18 @@ cp_parser_unqualified_id (cp_parser* parser,
                    && constructor_name_p (token->u.value, scope))))
          {
            cp_lexer_consume_token (parser->lexer);
-           return build_nt (BIT_NOT_EXPR, scope);
+           return cp_expr (build_nt (BIT_NOT_EXPR, scope), loc);
          }
 
        /* ~auto means the destructor of whatever the object is.  */
        if (cp_parser_is_keyword (token, RID_AUTO))
          {
            if (cxx_dialect < cxx14)
-             pedwarn (input_location, 0,
+             pedwarn (loc, 0,
                       "%<~auto%> only available with "
-                      "-std=c++14 or -std=gnu++14");
+                      "%<-std=c++14%> or %<-std=gnu++14%>");
            cp_lexer_consume_token (parser->lexer);
-           return build_nt (BIT_NOT_EXPR, make_auto ());
+           return cp_expr (build_nt (BIT_NOT_EXPR, make_auto (), loc));
          }
 
        /* If there was an explicit qualification (S::~T), first look
@@ -6075,7 +6162,7 @@ cp_parser_unqualified_id (cp_parser* parser,
                type_decl = cp_parser_identifier (parser);
                if (type_decl != error_mark_node)
                  type_decl = build_nt (BIT_NOT_EXPR, type_decl);
-               return type_decl;
+               return cp_expr (type_decl, loc);
              }
          }
        /* If an error occurred, assume that the name of the
@@ -6091,7 +6178,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        if (declarator_p && scope && !check_dtor_name (scope, type_decl))
          {
            if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-             error_at (token->location,
+             error_at (loc,
                        "declaration of %<~%T%> as member of %qT",
                        type_decl, scope);
            cp_parser_simulate_error (parser);
@@ -6106,11 +6193,11 @@ cp_parser_unqualified_id (cp_parser* parser,
            && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
            && !DECL_SELF_REFERENCE_P (type_decl)
            && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-         error_at (token->location,
+         error_at (loc,
                    "typedef-name %qD used as destructor declarator",
                    type_decl);
 
-       return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+       return cp_expr (build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl), loc));
       }
 
     case CPP_KEYWORD:
@@ -6751,7 +6838,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        /* Parse the type to which we are casting.  */
        saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
        parser->in_type_id_in_expr_p = true;
-       type = cp_parser_type_id (parser);
+       type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                                 NULL);
        parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
        /* Look for the closing `>'.  */
        cp_parser_require (parser, CPP_GREATER, RT_GREATER);
@@ -6963,6 +7051,32 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        break;
       }
 
+    case RID_BUILTIN_CONVERTVECTOR:
+      {
+       tree expression;
+       tree type;
+       /* Consume the `__builtin_convertvector' token.  */
+       cp_lexer_consume_token (parser->lexer);
+       /* Look for the opening `('.  */
+       matching_parens parens;
+       parens.require_open (parser);
+       /* Now, parse the assignment-expression.  */
+       expression = cp_parser_assignment_expression (parser);
+       /* Look for the `,'.  */
+       cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+       location_t type_location
+         = cp_lexer_peek_token (parser->lexer)->location;
+       /* Parse the type-id.  */
+       {
+         type_id_in_expr_sentinel s (parser);
+         type = cp_parser_type_id (parser);
+       }
+       /* Look for the closing `)'.  */
+       parens.require_close (parser);
+       return cp_build_vec_convert (expression, type_location, type,
+                                    tf_warning_or_error);
+      }
+
     default:
       {
        tree type;
@@ -7116,8 +7230,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
             is_member_access = false;
 
+           tree stripped_expression
+             = tree_strip_any_location_wrapper (postfix_expression);
            is_builtin_constant_p
-             = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
+             = DECL_IS_BUILTIN_CONSTANT_P (stripped_expression);
            if (is_builtin_constant_p)
              {
                /* The whole point of __builtin_constant_p is to allow
@@ -7163,7 +7279,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            if (idk == CP_ID_KIND_UNQUALIFIED
                || idk == CP_ID_KIND_TEMPLATE_ID)
              {
-               if (identifier_p (postfix_expression))
+               if (identifier_p (postfix_expression)
+                   /* In C++2A, we may need to perform ADL for a template
+                      name.  */
+                   || (TREE_CODE (postfix_expression) == TEMPLATE_ID_EXPR
+                       && identifier_p (TREE_OPERAND (postfix_expression, 0))))
                  {
                    if (!args->is_empty ())
                      {
@@ -7183,14 +7303,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                else if (!args->is_empty ()
                         && is_overloaded_fn (postfix_expression))
                  {
+                   /* We only need to look at the first function,
+                      because all the fns share the attribute we're
+                      concerned with (all member fns or all local
+                      fns).  */
                    tree fn = get_first_fn (postfix_expression);
                    fn = STRIP_TEMPLATE (fn);
 
                    /* Do not do argument dependent lookup if regular
                       lookup finds a member function or a block-scope
                       function declaration.  [basic.lookup.argdep]/3  */
-                   if (!DECL_FUNCTION_MEMBER_P (fn)
-                       && !DECL_LOCAL_FUNCTION_P (fn))
+                   if (!((TREE_CODE (fn) == USING_DECL && DECL_DEPENDENT_P (fn))
+                         || DECL_FUNCTION_MEMBER_P (fn)
+                         || DECL_LOCAL_FUNCTION_P (fn)))
                      {
                        koenig_p = true;
                        if (!any_type_dependent_arguments_p (args))
@@ -7878,7 +8003,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
       if (cxx_dialect < cxx14)
        pedwarn (input_location, 0,
                 "%<~auto%> only available with "
-                "-std=c++14 or -std=gnu++14");
+                "%<-std=c++14%> or %<-std=gnu++14%>");
       cp_lexer_consume_token (parser->lexer);
       cp_lexer_consume_token (parser->lexer);
       *scope = NULL_TREE;
@@ -8071,6 +8196,9 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
            return ret_expr;
          }
 
+       case RID_BUILTIN_HAS_ATTRIBUTE:
+         return cp_parser_has_attribute_expression (parser);
+
        case RID_NEW:
          return cp_parser_new_expression (parser);
 
@@ -8298,18 +8426,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
        case NEGATE_EXPR:
          /* Immediately fold negation of a constant, unless the constant is 0
             (since -0 == 0) or it would overflow.  */
-         if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER
-             && CONSTANT_CLASS_P (cast_expression)
-             && !integer_zerop (cast_expression)
-             && !TREE_OVERFLOW (cast_expression))
+         if (unary_operator == NEGATE_EXPR && op_ttype == CPP_NUMBER)
            {
-             tree folded = fold_build1 (unary_operator,
-                                        TREE_TYPE (cast_expression),
-                                        cast_expression);
-             if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+             tree stripped_expr
+               = tree_strip_any_location_wrapper (cast_expression);
+             if (CONSTANT_CLASS_P (stripped_expr)
+                 && !integer_zerop (stripped_expr)
+                 && !TREE_OVERFLOW (stripped_expr))
                {
-                 expression = cp_expr (folded, loc);
-                 break;
+                 tree folded = fold_build1 (unary_operator,
+                                            TREE_TYPE (stripped_expr),
+                                            stripped_expr);
+                 if (CONSTANT_CLASS_P (folded) && !TREE_OVERFLOW (folded))
+                   {
+                     expression = maybe_wrap_with_location (folded, loc);
+                     break;
+                   }
                }
            }
          /* Fall through.  */
@@ -8368,6 +8500,123 @@ cp_parser_unary_operator (cp_token* token)
     }
 }
 
+/* Parse a __builtin_has_attribute([expr|type], attribute-spec) expression.
+   Returns a representation of the expression.  */
+
+static tree
+cp_parser_has_attribute_expression (cp_parser *parser)
+{
+  location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  /* Consume the __builtin_has_attribute token.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return error_mark_node;
+
+  /* Types cannot be defined in a `sizeof' expression.  Save away the
+     old message.  */
+  const char *saved_message = parser->type_definition_forbidden_message;
+  /* And create the new one.  */
+  const int kwd = RID_BUILTIN_HAS_ATTRIBUTE;
+  char *tmp = concat ("types may not be defined in %<",
+                     IDENTIFIER_POINTER (ridpointers[kwd]),
+                     "%> expressions", NULL);
+  parser->type_definition_forbidden_message = tmp;
+
+  /* The restrictions on constant-expressions do not apply inside
+     sizeof expressions.  */
+  bool saved_integral_constant_expression_p
+    = parser->integral_constant_expression_p;
+  bool saved_non_integral_constant_expression_p
+    = parser->non_integral_constant_expression_p;
+  parser->integral_constant_expression_p = false;
+
+  /* Do not actually evaluate the expression.  */
+  ++cp_unevaluated_operand;
+  ++c_inhibit_evaluation_warnings;
+
+  tree oper = NULL_TREE;
+
+  /* We can't be sure yet whether we're looking at a type-id or an
+     expression.  */
+  cp_parser_parse_tentatively (parser);
+
+  bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+  parser->in_type_id_in_expr_p = true;
+  /* Look for the type-id.  */
+  oper = cp_parser_type_id (parser);
+  parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
+
+  cp_parser_parse_definitely (parser);
+
+  /* If the type-id production did not work out, then we must be
+     looking at the unary-expression production.  */
+  if (!oper || oper == error_mark_node)
+    oper = cp_parser_unary_expression (parser);
+
+  STRIP_ANY_LOCATION_WRAPPER (oper);
+
+  /* Go back to evaluating expressions.  */
+  --cp_unevaluated_operand;
+  --c_inhibit_evaluation_warnings;
+
+  /* Free the message we created.  */
+  free (tmp);
+  /* And restore the old one.  */
+  parser->type_definition_forbidden_message = saved_message;
+  parser->integral_constant_expression_p
+    = saved_integral_constant_expression_p;
+  parser->non_integral_constant_expression_p
+    = saved_non_integral_constant_expression_p;
+
+  /* Consume the comma if it's there.  */
+  if (!cp_parser_require (parser, CPP_COMMA, RT_COMMA))
+    {
+      cp_parser_skip_to_closing_parenthesis (parser, false, false,
+                                            /*consume_paren=*/true);
+      return error_mark_node;
+    }
+
+  /* Parse the attribute specification.  */
+  bool ret = false;
+  location_t atloc = cp_lexer_peek_token (parser->lexer)->location;
+  if (tree attr = cp_parser_gnu_attribute_list (parser, /*exactly_one=*/true))
+    {
+      if (oper != error_mark_node)
+       {
+         /* Fold constant expressions used in attributes first.  */
+         cp_check_const_attributes (attr);
+
+         /* Finally, see if OPER has been declared with ATTR.  */
+         ret = has_attribute (atloc, oper, attr, default_conversion);
+       }
+
+      parens.require_close (parser);
+    }
+  else
+    {
+      error_at (atloc, "expected identifier");
+      cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+    }
+
+  /* Construct a location e.g. :
+     __builtin_has_attribute (oper, attr)
+     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+     with start == caret at the start of the built-in token,
+     and with the endpoint at the final closing paren.  */
+  location_t finish_loc
+    = cp_lexer_previous_token (parser->lexer)->location;
+  location_t compound_loc
+    = make_location (start_loc, start_loc, finish_loc);
+
+  cp_expr ret_expr (ret ? boolean_true_node : boolean_false_node);
+  ret_expr.set_location (compound_loc);
+  ret_expr = ret_expr.maybe_add_location_wrapper ();
+  return ret_expr;
+}
+
 /* Parse a new-expression.
 
    new-expression:
@@ -8550,7 +8799,8 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
   parser->type_definition_forbidden_message
     = G_("types may not be defined in a new-type-id");
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+  cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                               /*is_declaration=*/false,
                                /*is_trailing_return=*/false,
                                &type_specifier_seq);
   /* Restore the old message.  */
@@ -9327,7 +9577,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
                      || (TREE_CODE (TREE_TYPE (TREE_OPERAND (current.lhs, 0)))
                          != BOOLEAN_TYPE))))
          /* Avoid warning for !!b == y where b is boolean.  */
-         && (!DECL_P (current.lhs)
+         && (!DECL_P (tree_strip_any_location_wrapper (current.lhs))
              || TREE_TYPE (current.lhs) == NULL_TREE
              || TREE_CODE (TREE_TYPE (current.lhs)) != BOOLEAN_TYPE))
        warn_logical_not_parentheses (current.loc, current.tree_type,
@@ -9365,7 +9615,8 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
        }
       else
         {
-          current.lhs = build_x_binary_op (combined_loc, current.tree_type,
+         op_location_t op_loc (current.loc, combined_loc);
+         current.lhs = build_x_binary_op (op_loc, current.tree_type,
                                            current.lhs, current.lhs_type,
                                            rhs, rhs_type, &overload,
                                            complain_flags (decltype_p));
@@ -9849,7 +10100,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   {
     const char *saved_message = parser->type_definition_forbidden_message;
     parser->type_definition_forbidden_message
-      = G_("types may not be defined within __builtin_offsetof");
+      = G_("types may not be defined within %<__builtin_offsetof%>");
     type = cp_parser_type_id (parser);
     parser->type_definition_forbidden_message = saved_message;
   }
@@ -10131,12 +10382,15 @@ cp_parser_lambda_expression (cp_parser* parser)
 
   LAMBDA_EXPR_LOCATION (lambda_expr) = token->location;
 
-  if (cp_unevaluated_operand)
+  if (cxx_dialect >= cxx2a)
+    /* C++20 allows lambdas in unevaluated context.  */;
+  else if (cp_unevaluated_operand)
     {
       if (!token->error_reported)
        {
          error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
-                   "lambda-expression in unevaluated context");
+                   "lambda-expression in unevaluated context"
+                   " only available with %<-std=c++2a%> or %<-std=gnu++2a%>");
          token->error_reported = true;
        }
       ok = false;
@@ -10145,7 +10399,8 @@ cp_parser_lambda_expression (cp_parser* parser)
     {
       if (!token->error_reported)
        {
-         error_at (token->location, "lambda-expression in template-argument");
+         error_at (token->location, "lambda-expression in template-argument"
+                   " only available with %<-std=c++2a%> or %<-std=gnu++2a%>");
          token->error_reported = true;
        }
       ok = false;
@@ -10156,6 +10411,8 @@ cp_parser_lambda_expression (cp_parser* parser)
   push_deferring_access_checks (dk_no_deferred);
 
   cp_parser_lambda_introducer (parser, lambda_expr);
+  if (cp_parser_error_occurred (parser))
+    return error_mark_node;
 
   type = begin_lambda_type (lambda_expr);
   if (type == error_mark_node)
@@ -10194,6 +10451,9 @@ cp_parser_lambda_expression (cp_parser* parser)
     /* By virtue of defining a local class, a lambda expression has access to
        the private variables of enclosing classes.  */
 
+    if (cp_parser_start_tentative_firewall (parser))
+      start = token;
+
     ok &= cp_parser_lambda_declarator_opt (parser, lambda_expr);
 
     if (ok && cp_parser_error_occurred (parser))
@@ -10201,9 +10461,6 @@ cp_parser_lambda_expression (cp_parser* parser)
 
     if (ok)
       {
-       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)
-           && cp_parser_start_tentative_firewall (parser))
-         start = token;
        cp_parser_lambda_body (parser, lambda_expr);
       }
     else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
@@ -10340,7 +10597,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
          location_t loc = cp_lexer_peek_token (parser->lexer)->location;
          if (cxx_dialect < cxx17)
            pedwarn (loc, 0, "%<*this%> capture only available with "
-                            "-std=c++17 or -std=gnu++17");
+                            "%<-std=c++17%> or %<-std=gnu++17%>");
          cp_lexer_consume_token (parser->lexer);
          cp_lexer_consume_token (parser->lexer);
          add_capture (lambda_expr,
@@ -10351,6 +10608,17 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
          continue;
        }
 
+      bool init_pack_expansion = false;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+       {
+         location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+         if (cxx_dialect < cxx2a)
+           pedwarn (loc, 0, "pack init-capture only available with "
+                            "%<-std=c++2a%> or %<-std=gnu++2a%>");
+         cp_lexer_consume_token (parser->lexer);
+         init_pack_expansion = true;
+       }
+
       /* Remember whether we want to capture as a reference or not.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_AND))
        {
@@ -10385,7 +10653,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
          if (cxx_dialect < cxx14)
            pedwarn (input_location, 0,
                     "lambda capture initializers "
-                    "only available with -std=c++14 or -std=gnu++14");
+                    "only available with %<-std=c++14%> or %<-std=gnu++14%>");
          capture_init_expr = cp_parser_initializer (parser, &direct,
                                                     &non_constant, true);
          explicit_init_p = true;
@@ -10394,6 +10662,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
              error ("empty initializer for lambda init-capture");
              capture_init_expr = error_mark_node;
            }
+         if (init_pack_expansion)
+           capture_init_expr = make_pack_expansion (capture_init_expr);
        }
       else
        {
@@ -10521,11 +10791,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       if (cxx_dialect < cxx14)
        pedwarn (parser->lexer->next_token->location, 0,
                 "lambda templates are only available with "
-                "-std=c++14 or -std=gnu++14");
+                "%<-std=c++14%> or %<-std=gnu++14%>");
       else if (cxx_dialect < cxx2a)
        pedwarn (parser->lexer->next_token->location, OPT_Wpedantic,
                 "lambda templates are only available with "
-                "-std=c++2a or -std=gnu++2a");
+                "%<-std=c++2a%> or %<-std=gnu++2a%>");
 
       cp_lexer_consume_token (parser->lexer);
 
@@ -10548,7 +10818,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
 
       /* Parse parameters.  */
-      param_list = cp_parser_parameter_declaration_clause (parser);
+      param_list
+       = cp_parser_parameter_declaration_clause
+           (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL);
 
       /* Default arguments shall not be specified in the
         parameter-declaration-clause of a lambda-declarator.  */
@@ -10560,8 +10832,6 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
 
       parens.require_close (parser);
 
-      attributes = cp_parser_attributes_opt (parser);
-
       /* In the decl-specifier-seq of the lambda-declarator, each
         decl-specifier shall either be mutable or constexpr.  */
       int declares_class_or_enum;
@@ -10582,6 +10852,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       /* Parse optional exception specification.  */
       exception_spec = cp_parser_exception_specification_opt (parser);
 
+      attributes = cp_parser_std_attribute_spec_seq (parser);
+
       /* Parse optional trailing return type.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
         {
@@ -10618,12 +10890,14 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
            = lambda_specs.locations[ds_constexpr];
        else
          error_at (lambda_specs.locations[ds_constexpr], "%<constexpr%> "
-                   "lambda only available with -std=c++17 or -std=gnu++17");
+                   "lambda only available with %<-std=c++17%> or "
+                   "%<-std=gnu++17%>");
       }
 
     p = obstack_alloc (&declarator_obstack, 0);
 
-    declarator = make_id_declarator (NULL_TREE, call_op_identifier, sfk_none);
+    declarator = make_id_declarator (NULL_TREE, call_op_identifier, sfk_none,
+                                    LAMBDA_EXPR_LOCATION (lambda_expr));
 
     quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
             ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
@@ -10632,21 +10906,20 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
                                        REF_QUAL_NONE,
                                       tx_qual,
                                       exception_spec,
-                                       /*late_return_type=*/NULL_TREE,
+                                       return_type,
                                        /*requires_clause*/NULL_TREE);
-    declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
-    if (return_type)
-      declarator->u.function.late_return_type = return_type;
+    declarator->std_attributes = attributes;
 
     fco = grokmethod (&return_type_specs,
                      declarator,
-                     attributes);
+                     NULL_TREE);
     if (fco != error_mark_node)
       {
        DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
        DECL_ARTIFICIAL (fco) = 1;
        /* Give the object parameter a different name.  */
        DECL_NAME (DECL_ARGUMENTS (fco)) = closure_identifier;
+       DECL_LAMBDA_FUNCTION (fco) = 1;
       }
     if (template_param_list)
       {
@@ -10676,9 +10949,14 @@ static void
 cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
 {
   bool nested = (current_function_decl != NULL_TREE);
-  bool local_variables_forbidden_p = parser->local_variables_forbidden_p;
+  unsigned char local_variables_forbidden_p
+    = parser->local_variables_forbidden_p;
   bool in_function_body = parser->in_function_body;
 
+  /* The body of a lambda-expression is not a subexpression of the enclosing
+     expression.  */
+  cp_evaluated ev;
+
   if (nested)
     push_function_context ();
   else
@@ -10689,7 +10967,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
   vec<tree> omp_privatization_save;
   save_omp_privatization_clauses (omp_privatization_save);
   /* Clear this in case we're in the middle of a default argument.  */
-  parser->local_variables_forbidden_p = false;
+  parser->local_variables_forbidden_p = 0;
   parser->in_function_body = true;
 
   {
@@ -10793,7 +11071,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 {
   tree statement, std_attrs = NULL_TREE;
   cp_token *token;
-  location_t statement_location, attrs_location;
+  location_t statement_location, attrs_loc;
 
  restart:
   if (if_p != NULL)
@@ -10802,13 +11080,19 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
   statement = NULL_TREE;
 
   saved_token_sentinel saved_tokens (parser->lexer);
-  attrs_location = cp_lexer_peek_token (parser->lexer)->location;
+  attrs_loc = cp_lexer_peek_token (parser->lexer)->location;
   if (c_dialect_objc ())
     /* In obj-c++, seeing '[[' might be the either the beginning of
        c++11 attributes, or a nested objc-message-expression.  So
        let's parse the c++11 attributes tentatively.  */
     cp_parser_parse_tentatively (parser);
   std_attrs = cp_parser_std_attribute_spec_seq (parser);
+  if (std_attrs)
+    {
+      location_t end_loc
+       = cp_lexer_previous_token (parser->lexer)->location;
+      attrs_loc = make_location (attrs_loc, attrs_loc, end_loc);
+    }
   if (c_dialect_objc ())
     {
       if (!cp_parser_parse_definitely (parser))
@@ -10818,6 +11102,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* Remember the location of the first token in the statement.  */
+  cp_token *statement_token = token;
   statement_location = token->location;
   add_debug_begin_stmt (statement_location);
   /* If this is a keyword, then that will often determine what kind of
@@ -10839,12 +11124,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
        case RID_IF:
        case RID_SWITCH:
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_selection_statement (parser, if_p, chain);
          break;
 
        case RID_WHILE:
        case RID_DO:
        case RID_FOR:
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_iteration_statement (parser, if_p, false, 0);
          break;
 
@@ -10852,6 +11139,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        case RID_CONTINUE:
        case RID_RETURN:
        case RID_GOTO:
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_jump_statement (parser);
          break;
 
@@ -10861,15 +11149,24 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        case RID_AT_FINALLY:
        case RID_AT_SYNCHRONIZED:
        case RID_AT_THROW:
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_objc_statement (parser);
          break;
 
        case RID_TRY:
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_try_block (parser);
          break;
 
        case RID_NAMESPACE:
          /* This must be a namespace alias definition.  */
+         if (std_attrs != NULL_TREE)
+           {
+             /*  Attributes should be parsed as part of the the
+                 declaration, so let's un-parse them.  */
+             saved_tokens.rollback();
+             std_attrs = NULL_TREE;
+           }
          cp_parser_declaration_statement (parser);
          return;
          
@@ -10878,9 +11175,11 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        case RID_SYNCHRONIZED:
        case RID_ATOMIC_NOEXCEPT:
        case RID_ATOMIC_CANCEL:
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_transaction (parser, token);
          break;
        case RID_TRANSACTION_CANCEL:
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_transaction_cancel (parser);
          break;
 
@@ -10939,12 +11238,9 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
        {
          if (std_attrs != NULL_TREE)
-           {
-             /*  Attributes should be parsed as part of the the
-                 declaration, so let's un-parse them.  */
-             saved_tokens.rollback();
-             std_attrs = NULL_TREE;
-           }
+           /* Attributes should be parsed as part of the declaration,
+              so let's un-parse them.  */
+           saved_tokens.rollback();
 
          cp_parser_parse_tentatively (parser);
          /* Try to parse the declaration-statement.  */
@@ -10952,11 +11248,16 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
          /* If that worked, we're done.  */
          if (cp_parser_parse_definitely (parser))
            return;
+         /* It didn't work, restore the post-attribute position.  */
+         if (std_attrs)
+           cp_lexer_set_token_position (parser->lexer, statement_token);
        }
       /* All preceding labels have been parsed at this point.  */
       if (loc_after_labels != NULL)
        *loc_after_labels = statement_location;
 
+      std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
+
       /* Look for an expression-statement instead.  */
       statement = cp_parser_expression_statement (parser, in_statement_expr);
 
@@ -10985,7 +11286,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
   /* Allow "[[fallthrough]];", but warn otherwise.  */
   if (std_attrs != NULL_TREE)
-    warning_at (attrs_location,
+    warning_at (attrs_loc,
                OPT_Wattributes,
                "attributes at the beginning of statement are ignored");
 }
@@ -11069,7 +11370,10 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
          {
            tree l = finish_case_label (token->location, expr, expr_hi);
            if (l && TREE_CODE (l) == CASE_LABEL_EXPR)
-             FALLTHROUGH_LABEL_P (CASE_LABEL (l)) = fallthrough_p;
+             {
+               label = CASE_LABEL (l);
+               FALLTHROUGH_LABEL_P (label) = fallthrough_p;
+             }
          }
        else
          error_at (token->location,
@@ -11086,7 +11390,10 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
        {
          tree l = finish_case_label (token->location, NULL_TREE, NULL_TREE);
          if (l && TREE_CODE (l) == CASE_LABEL_EXPR)
-           FALLTHROUGH_LABEL_P (CASE_LABEL (l)) = fallthrough_p;
+             {
+               label = CASE_LABEL (l);
+               FALLTHROUGH_LABEL_P (label) = fallthrough_p;
+             }
        }
       else
        error_at (token->location, "case label not within a switch statement");
@@ -11116,6 +11423,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
       cp_parser_parse_tentatively (parser);
       attrs = cp_parser_gnu_attributes_opt (parser);
       if (attrs == NULL_TREE
+         /* And fallthrough always binds to the expression-statement.  */
+         || attribute_fallthrough_p (attrs)
          || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
        cp_parser_abort_tentative_parse (parser);
       else if (!cp_parser_parse_definitely (parser))
@@ -11406,7 +11715,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
            cp_token *tok = cp_lexer_consume_token (parser->lexer);
            if (cxx_dialect < cxx17 && !in_system_header_at (tok->location))
              pedwarn (tok->location, 0, "%<if constexpr%> only available "
-                      "with -std=c++17 or -std=gnu++17");
+                      "with %<-std=c++17%> or %<-std=gnu++17%>");
          }
 
        /* Look for the `('.  */
@@ -11433,7 +11742,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
            if (cxx_dialect < cxx17)
              pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0,
                       "init-statement in selection statements only available "
-                      "with -std=c++17 or -std=gnu++17");
+                      "with %<-std=c++17%> or %<-std=gnu++17%>");
            cp_parser_init_statement (parser, &decl);
          }
 
@@ -11705,10 +12014,12 @@ cp_parser_condition (cp_parser* parser)
 
       /* Parse the declarator.  */
       declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                                        CP_PARSER_FLAGS_NONE,
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         /*parenthesized_p=*/NULL,
                                         /*member_p=*/false,
-                                        /*friend_p=*/false);
+                                        /*friend_p=*/false,
+                                        /*static_p=*/false);
       /* Parse the attributes.  */
       attributes = cp_parser_attributes_opt (parser);
       /* Parse the asm-specification.  */
@@ -11800,7 +12111,8 @@ cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll)
   is_range_for = cp_parser_init_statement (parser, &decl);
 
   if (is_range_for)
-    return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll);
+    return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll,
+                               false);
   else
     return cp_parser_c_for (parser, scope, init, ivdep, unroll);
 }
@@ -11858,7 +12170,7 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep,
 
 static tree
 cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
-                    bool ivdep, unsigned short unroll)
+                    bool ivdep, unsigned short unroll, bool is_omp)
 {
   tree stmt, range_expr;
   auto_vec <cxx_binding *, 16> bindings;
@@ -11918,6 +12230,11 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
       IDENTIFIER_BINDING (names[i]) = binding;
     }
 
+  /* finish_omp_for has its own code for the following, so just
+     return the range_expr instead.  */
+  if (is_omp)
+    return range_expr;
+
   /* If in template, STMT is converted to a normal for-statement
      at instantiation. If not, it is done just ahead. */
   if (processing_template_decl)
@@ -12412,7 +12729,7 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
            {
              pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0,
                       "range-based %<for%> loops with initializer only "
-                      "available with -std=c++2a or -std=gnu++2a");
+                      "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
              *decl = error_mark_node;
            }
        }
@@ -12436,7 +12753,7 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
          if (cxx_dialect < cxx11)
            pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0,
                     "range-based %<for%> loops only available with "
-                    "-std=c++11 or -std=gnu++11");
+                    "%<-std=c++11%> or %<-std=gnu++11%>");
        }
       else
        /* The ';' is not consumed yet because we told
@@ -12740,50 +13057,13 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
 {
   while (true)
     {
-      cp_token *token;
-
-      token = cp_lexer_peek_token (parser->lexer);
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
 
       if (token->type == CPP_CLOSE_BRACE
-         || token->type == CPP_EOF
-         || token->type == CPP_PRAGMA_EOL)
+         || token->type == CPP_EOF)
        break;
-
-      if (token->type == CPP_SEMICOLON)
-       {
-         /* A declaration consisting of a single semicolon is
-            invalid.  Allow it unless we're being pedantic.  */
-         cp_lexer_consume_token (parser->lexer);
-         if (!in_system_header_at (input_location))
-           pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");
-         continue;
-       }
-
-      /* If we're entering or exiting a region that's implicitly
-        extern "C", modify the lang context appropriately.  */
-      if (!parser->implicit_extern_c && token->implicit_extern_c)
-       {
-         push_lang_context (lang_name_c);
-         parser->implicit_extern_c = true;
-       }
-      else if (parser->implicit_extern_c && !token->implicit_extern_c)
-       {
-         pop_lang_context ();
-         parser->implicit_extern_c = false;
-       }
-
-      if (token->type == CPP_PRAGMA)
-       {
-         /* A top-level declaration can consist solely of a #pragma.
-            A nested declaration cannot, so this is done here and not
-            in cp_parser_declaration.  (A #pragma at block scope is
-            handled in cp_parser_statement.)  */
-         cp_parser_pragma (parser, pragma_external, NULL);
-         continue;
-       }
-
-      /* Parse the declaration itself.  */
-      cp_parser_declaration (parser);
+      else
+       cp_parser_toplevel_declaration (parser);
     }
 }
 
@@ -12913,6 +13193,32 @@ cp_parser_declaration (cp_parser* parser)
   obstack_free (&declarator_obstack, p);
 }
 
+/* Parse a namespace-scope declaration.  */
+
+static void
+cp_parser_toplevel_declaration (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->type == CPP_PRAGMA)
+    /* A top-level declaration can consist solely of a #pragma.  A
+       nested declaration cannot, so this is done here and not in
+       cp_parser_declaration.  (A #pragma at block scope is
+       handled in cp_parser_statement.)  */
+    cp_parser_pragma (parser, pragma_external, NULL);
+  else if (token->type == CPP_SEMICOLON)
+    {
+      /* A declaration consisting of a single semicolon is
+        invalid.  Allow it unless we're being pedantic.  */
+      cp_lexer_consume_token (parser->lexer);
+      if (!in_system_header_at (input_location))
+       pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");
+    }
+  else
+    /* Parse the declaration itself.  */
+    cp_parser_declaration (parser);
+}
+
 /* Parse a block-declaration.
 
    block-declaration:
@@ -13184,7 +13490,9 @@ cp_parser_simple_declaration (cp_parser* parser,
        saw_declarator = true;
 
       /* Parse the init-declarator.  */
-      decl = cp_parser_init_declarator (parser, &decl_specifiers,
+      decl = cp_parser_init_declarator (parser,
+                                       CP_PARSER_FLAGS_NONE,
+                                       &decl_specifiers,
                                        /*checks=*/NULL,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
@@ -13387,7 +13695,7 @@ cp_parser_decomposition_declaration (cp_parser *parser,
 
   if (cxx_dialect < cxx17)
     pedwarn (loc, 0, "structured bindings only available with "
-                    "-std=c++17 or -std=gnu++17");
+                    "%<-std=c++17%> or %<-std=gnu++17%>");
 
   tree pushed_scope;
   cp_declarator *declarator = make_declarator (cdk_decomp);
@@ -13411,10 +13719,13 @@ cp_parser_decomposition_declaration (cp_parser *parser,
   FOR_EACH_VEC_ELT (v, i, e)
     {
       if (i == 0)
-       declarator = make_id_declarator (NULL_TREE, e.get_value (), sfk_none);
+       declarator = make_id_declarator (NULL_TREE, e.get_value (),
+                                        sfk_none, e.get_location ());
       else
-       declarator->u.id.unqualified_name = e.get_value ();
-      declarator->id_loc = e.get_location ();
+       {
+         declarator->u.id.unqualified_name = e.get_value ();
+         declarator->id_loc = e.get_location ();
+       }
       tree elt_pushed_scope;
       tree decl2 = start_decl (declarator, &decl_specs, SD_INITIALIZED,
                               NULL_TREE, NULL_TREE, &elt_pushed_scope);
@@ -13875,6 +14186,9 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
      virtual
      explicit
 
+   C++2A Extension:
+     explicit(constant-expression)
+
    Returns an IDENTIFIER_NODE corresponding to the keyword used.
    Updates DECL_SPECS, if it is non-NULL.  */
 
@@ -13901,8 +14215,53 @@ cp_parser_function_specifier_opt (cp_parser* parser,
       break;
 
     case RID_EXPLICIT:
-      set_and_check_decl_spec_loc (decl_specs, ds_explicit, token);
-      break;
+      {
+       tree id = cp_lexer_consume_token (parser->lexer)->u.value;
+       /* If we see '(', it's C++20 explicit(bool).  */
+       tree expr;
+       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+         {
+           matching_parens parens;
+           parens.consume_open (parser);
+
+           /* New types are not allowed in an explicit-specifier.  */
+           const char *saved_message
+             = parser->type_definition_forbidden_message;
+           parser->type_definition_forbidden_message
+             = G_("types may not be defined in explicit-specifier");
+
+           if (cxx_dialect < cxx2a)
+             pedwarn (token->location, 0,
+                      "%<explicit(bool)%> only available with %<-std=c++2a%> "
+                      "or %<-std=gnu++2a%>");
+
+           /* Parse the constant-expression.  */
+           expr = cp_parser_constant_expression (parser);
+
+           /* Restore the saved message.  */
+           parser->type_definition_forbidden_message = saved_message;
+           parens.require_close (parser);
+         }
+       else
+         /* The explicit-specifier explicit without a constant-expression is
+            equivalent to the explicit-specifier explicit(true).  */
+         expr = boolean_true_node;
+
+       /* [dcl.fct.spec]
+          "the constant-expression, if supplied, shall be a contextually
+          converted constant expression of type bool."  */
+       expr = build_explicit_specifier (expr, tf_warning_or_error);
+       /* We could evaluate it -- mark the decl as appropriate.  */
+       if (expr == boolean_true_node)
+         set_and_check_decl_spec_loc (decl_specs, ds_explicit, token);
+       else if (expr == boolean_false_node)
+         /* Don't mark the decl as explicit.  */;
+       else if (decl_specs)
+         /* The expression was value-dependent.  Remember it so that we can
+            substitute it later.  */
+         decl_specs->explicit_specifier = expr;
+       return id;
+      }
 
     default:
       return NULL_TREE;
@@ -13970,7 +14329,7 @@ cp_parser_linkage_specification (cp_parser* parser)
 
       /* Consume the `{' token.  */
       matching_braces braces;
-      braces.consume_open (parser)->location;
+      braces.consume_open (parser);
       /* Parse the declarations.  */
       cp_parser_declaration_seq_opt (parser);
       /* Look for the closing `}'.  */
@@ -14042,7 +14401,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
       if (cxx_dialect < cxx17)
        pedwarn (input_location, OPT_Wpedantic,
                 "static_assert without a message "
-                "only available with -std=c++17 or -std=gnu++17");
+                "only available with %<-std=c++17%> or %<-std=gnu++17%>");
       /* Eat the ')'  */
       cp_lexer_consume_token (parser->lexer);
       message = build_string (1, "");
@@ -14266,6 +14625,7 @@ cp_parser_decltype (cp_parser *parser)
       ++c_inhibit_evaluation_warnings;
 
       expr = cp_parser_decltype_expr (parser, id_expression_or_member_access_p);
+      STRIP_ANY_LOCATION_WRAPPER (expr);
 
       /* Go back to evaluating expressions.  */
       --cp_unevaluated_operand;
@@ -14399,7 +14759,8 @@ cp_parser_conversion_type_id (cp_parser* parser)
     = G_("types may not be defined in a conversion-type-id");
 
   /* Parse the type-specifiers.  */
-  cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+  cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+                               /*is_declaration=*/false,
                                /*is_trailing_return=*/false,
                                &type_specifiers);
 
@@ -14642,7 +15003,9 @@ cp_parser_mem_initializer (cp_parser* parser)
       vec = cp_parser_parenthesized_expression_list (parser, non_attr,
                                                     /*cast_p=*/false,
                                                     /*allow_expansion_p=*/true,
-                                                    /*non_constant_p=*/NULL);
+                                                    /*non_constant_p=*/NULL,
+                                                    /*close_paren_loc=*/NULL,
+                                                    /*wrap_locations_p=*/true);
       if (vec == NULL)
        return error_mark_node;
       expression_list = build_tree_list_vec (vec);
@@ -14758,11 +15121,12 @@ cp_parser_mem_initializer_id (cp_parser* parser)
 static cp_expr
 cp_parser_operator_function_id (cp_parser* parser)
 {
+  location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
   /* Look for the `operator' keyword.  */
   if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR))
     return error_mark_node;
   /* And then the name of the operator itself.  */
-  return cp_parser_operator (parser);
+  return cp_parser_operator (parser, start_loc);
 }
 
 /* Return an identifier node for a user-defined literal operator.
@@ -14796,7 +15160,7 @@ cp_literal_operator_id (const char* name)
    human-readable spelling of the identifier, e.g., `operator +'.  */
 
 static cp_expr
-cp_parser_operator (cp_parser* parser)
+cp_parser_operator (cp_parser* parser, location_t start_loc)
 {
   tree id = NULL_TREE;
   cp_token *token;
@@ -14805,7 +15169,7 @@ cp_parser_operator (cp_parser* parser)
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
-  location_t start_loc = token->location;
+  location_t end_loc = token->location;
 
   /* Figure out which operator we have.  */
   enum tree_code op = ERROR_MARK;
@@ -14824,7 +15188,7 @@ cp_parser_operator (cp_parser* parser)
          break;
 
        /* Consume the `new' or `delete' token.  */
-       location_t end_loc = cp_lexer_consume_token (parser->lexer)->location;
+       end_loc = cp_lexer_consume_token (parser->lexer)->location;
 
        /* Peek at the next token.  */
        token = cp_lexer_peek_token (parser->lexer);
@@ -14840,7 +15204,6 @@ cp_parser_operator (cp_parser* parser)
              end_loc = close_token->location;
            op = op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR;
          }
-       start_loc = make_location (start_loc, start_loc, end_loc);
        consumed = true;
        break;
       }
@@ -15006,7 +15369,9 @@ cp_parser_operator (cp_parser* parser)
         matching_parens parens;
         parens.consume_open (parser);
         /* Look for the matching `)'.  */
-        parens.require_close (parser);
+        token = parens.require_close (parser);
+        if (token)
+         end_loc = token->location;
        op = CALL_EXPR;
        consumed = true;
        break;
@@ -15016,7 +15381,9 @@ cp_parser_operator (cp_parser* parser)
       /* Consume the `['.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `]'.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+      token = cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+      if (token)
+       end_loc = token->location;
       op = ARRAY_REF;
       consumed = true;
       break;
@@ -15034,7 +15401,8 @@ cp_parser_operator (cp_parser* parser)
     case CPP_STRING16_USERDEF:
     case CPP_STRING32_USERDEF:
       {
-       tree str, string_tree;
+       cp_expr str;
+       tree string_tree;
        int sz, len;
 
        if (cxx_dialect == cxx98)
@@ -15047,8 +15415,9 @@ cp_parser_operator (cp_parser* parser)
          return error_mark_node;
        else if (TREE_CODE (str) == USERDEF_LITERAL)
          {
-           string_tree = USERDEF_LITERAL_VALUE (str);
-           id = USERDEF_LITERAL_SUFFIX_ID (str);
+           string_tree = USERDEF_LITERAL_VALUE (str.get_value ());
+           id = USERDEF_LITERAL_SUFFIX_ID (str.get_value ());
+           end_loc = str.get_location ();
          }
        else
          {
@@ -15056,7 +15425,10 @@ cp_parser_operator (cp_parser* parser)
            /* Look for the suffix identifier.  */
            token = cp_lexer_peek_token (parser->lexer);
            if (token->type == CPP_NAME)
-             id = cp_parser_identifier (parser);
+             {
+               id = cp_parser_identifier (parser);
+               end_loc = token->location;
+             }
            else if (token->type == CPP_KEYWORD)
              {
                error ("unexpected keyword;"
@@ -15088,7 +15460,16 @@ cp_parser_operator (cp_parser* parser)
            const char *name = IDENTIFIER_POINTER (id);
            id = cp_literal_operator_id (name);
          }
-       return id;
+       /* Generate a location of the form:
+            "" _suffix_identifier
+            ^~~~~~~~~~~~~~~~~~~~~
+          with caret == start at the start token, finish at the end of the
+          suffix identifier.  */
+       location_t finish_loc
+         = get_finish (cp_lexer_previous_token (parser->lexer)->location);
+       location_t combined_loc
+         = make_location (start_loc, start_loc, finish_loc);
+       return cp_expr (id, combined_loc);
       }
 
     default:
@@ -15111,6 +15492,7 @@ cp_parser_operator (cp_parser* parser)
       id = error_mark_node;
     }
 
+  start_loc = make_location (start_loc, start_loc, get_finish (end_loc));
   return cp_expr (id, start_loc);
 }
 
@@ -15172,6 +15554,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
 {
   tree parameter_list = NULL_TREE;
 
+  /* Don't create wrapper nodes within a template-parameter-list,
+     since we don't want to have different types based on the
+     spelling location of constants and decls within them.  */
+  auto_suppress_location_wrappers sentinel;
+
   begin_template_parm_list ();
 
   /* The loop below parses the template parms.  We first need to know
@@ -15240,11 +15627,15 @@ cp_parser_introduction_list (cp_parser *parser)
       if (is_pack)
        cp_lexer_consume_token (parser->lexer);
 
+      tree identifier = cp_parser_identifier (parser);
+      if (identifier == error_mark_node)
+       break;
+
       /* Build placeholder. */
       tree parm = build_nt (WILDCARD_DECL);
       DECL_SOURCE_LOCATION (parm)
        = cp_lexer_peek_token (parser->lexer)->location;
-      DECL_NAME (parm) = cp_parser_identifier (parser);
+      DECL_NAME (parm) = identifier;
       WILDCARD_PACK_P (parm) = is_pack;
       vec_safe_push (introduction_vec, parm);
 
@@ -15473,7 +15864,9 @@ cp_parser_default_type_template_argument (cp_parser *parser)
 
   /* Parse the default-argument.  */
   push_deferring_access_checks (dk_no_deferred);
-  tree default_argument = cp_parser_type_id (parser);
+  tree default_argument = cp_parser_type_id (parser,
+                                            CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                                            NULL);
   pop_deferring_access_checks ();
 
   if (flag_concepts && type_uses_auto (default_argument))
@@ -15600,7 +15993,9 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
      of the template parameter-list rather than a greater-than
      operator.  */
   parameter_declarator
-     = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
+     = cp_parser_parameter_declaration (parser,
+                                       CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                                       /*template_parm_p=*/true,
                                        /*parenthesized_p=*/NULL);
 
   if (!parameter_declarator)
@@ -15887,16 +16282,18 @@ cp_parser_template_id (cp_parser *parser,
                                   is_declaration,
                                   tag_type,
                                   &is_identifier);
+
+  /* Push any access checks inside the firewall we're about to create.  */
+  vec<deferred_access_check, va_gc> *checks = get_deferred_access_checks ();
+  pop_deferring_access_checks ();
   if (templ == error_mark_node || is_identifier)
-    {
-      pop_deferring_access_checks ();
-      return templ;
-    }
+    return templ;
 
   /* Since we're going to preserve any side-effects from this parse, set up a
      firewall to protect our callers from cp_parser_commit_to_tentative_parse
      in the template arguments.  */
   tentative_firewall firewall (parser);
+  reopen_deferring_access_checks (checks);
 
   /* If we find the sequence `[:' after a template-name, it's probably
      a digraph-typo for `< ::'. Substitute the tokens and check if we can
@@ -15955,6 +16352,37 @@ cp_parser_template_id (cp_parser *parser,
        }
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
+
+      if ((cxx_dialect > cxx17)
+         && (TREE_CODE (templ) == FUNCTION_DECL || identifier_p (templ))
+         && !template_keyword_p
+         && (cp_parser_error_occurred (parser)
+             || cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)))
+       {
+         /* This didn't go well.  */
+         if (TREE_CODE (templ) == FUNCTION_DECL)
+           {
+             /* C++2A says that "function-name < a;" is now ill-formed.  */
+             if (cp_parser_error_occurred (parser))
+               {
+                 error_at (token->location, "invalid template-argument-list");
+                 inform (token->location, "function name as the left hand "
+                         "operand of %<<%> is ill-formed in C++2a; wrap the "
+                         "function name in %<()%>");
+               }
+             else
+               /* We expect "f<targs>" to be followed by "(args)".  */
+               error_at (cp_lexer_peek_token (parser->lexer)->location,
+                         "expected %<(%> after template-argument-list");
+             if (start_of_id)
+               /* Purge all subsequent tokens.  */
+               cp_lexer_purge_tokens_after (parser->lexer, start_of_id);
+           }
+         else
+           cp_parser_simulate_error (parser);
+         pop_deferring_access_checks ();
+         return error_mark_node;
+       }
     }
 
   /* Set the location to be of the form:
@@ -16011,6 +16439,7 @@ cp_parser_template_id (cp_parser *parser,
         a function-template.  */
       gcc_assert ((DECL_FUNCTION_TEMPLATE_P (templ)
                   || TREE_CODE (templ) == OVERLOAD
+                  || TREE_CODE (templ) == FUNCTION_DECL
                   || BASELINK_P (templ)));
 
       template_id = lookup_template_function (templ, arguments);
@@ -16213,6 +16642,10 @@ cp_parser_template_name (cp_parser* parser,
        }
     }
 
+  /* cp_parser_lookup_name clears OBJECT_TYPE.  */
+  const bool scoped_p = ((parser->scope ? parser->scope
+                         : parser->context->object_type) != NULL_TREE);
+
   /* Look up the name.  */
   decl = cp_parser_lookup_name (parser, identifier,
                                tag_type,
@@ -16245,6 +16678,28 @@ cp_parser_template_name (cp_parser* parser,
        if (TREE_CODE (*iter) == TEMPLATE_DECL)
          found = true;
 
+      if (!found
+         && (cxx_dialect > cxx17)
+         && !scoped_p
+         && cp_lexer_next_token_is (parser->lexer, CPP_LESS)
+         && tag_type == none_type)
+       {
+         /* [temp.names] says "A name is also considered to refer to a template
+            if it is an unqualified-id followed by a < and name lookup finds
+            either one or more functions or finds nothing."  */
+
+         /* The "more functions" case.  Just use the OVERLOAD as normally.
+            We don't use is_overloaded_fn here to avoid considering
+            BASELINKs.  */
+         if (TREE_CODE (decl) == OVERLOAD
+             /* Name lookup found one function.  */
+             || TREE_CODE (decl) == FUNCTION_DECL)
+           found = true;
+         /* Name lookup found nothing.  */
+         else if (decl == error_mark_node)
+           return identifier;
+       }
+
       if (!found)
        {
          /* The name does not name a template.  */
@@ -16253,15 +16708,6 @@ cp_parser_template_name (cp_parser* parser,
        }
     }
 
-  /* If DECL is dependent, and refers to a function, then just return
-     its name; we will look it up again during template instantiation.  */
-  if (DECL_FUNCTION_TEMPLATE_P (decl) || !DECL_P (decl))
-    {
-      tree scope = ovl_scope (decl);
-      if (TYPE_P (scope) && dependent_type_p (scope))
-       return identifier;
-    }
-
   return decl;
 }
 
@@ -16285,6 +16731,9 @@ cp_parser_template_argument_list (cp_parser* parser)
   bool saved_ice_p;
   bool saved_non_ice_p;
 
+  /* Don't create location wrapper nodes within a template-argument-list.  */
+  auto_suppress_location_wrappers sentinel;
+
   saved_in_template_argument_list_p = parser->in_template_argument_list_p;
   parser->in_template_argument_list_p = true;
   /* Even if the template-id appears in an integral
@@ -16600,6 +17049,14 @@ cp_parser_template_argument (cp_parser* parser)
     argument = cp_parser_constant_expression (parser);
   else
     {
+      /* In C++20, we can encounter a braced-init-list.  */
+      if (cxx_dialect >= cxx2a
+         && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+       {
+         bool expr_non_constant_p;
+         return cp_parser_braced_list (parser, &expr_non_constant_p);
+       }
+
       /* With C++17 generalized non-type template arguments we need to handle
         lvalue constant expressions, too.  */
       argument = cp_parser_assignment_expression (parser);
@@ -16699,10 +17156,12 @@ cp_parser_explicit_instantiation (cp_parser* parser)
       /* Parse the declarator.  */
       declarator
        = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                               CP_PARSER_FLAGS_NONE,
                                /*ctor_dtor_or_conv_p=*/NULL,
                                /*parenthesized_p=*/NULL,
                                /*member_p=*/false,
-                               /*friend_p=*/false);
+                               /*friend_p=*/false,
+                               /*static_p=*/false);
       if (declares_class_or_enum & 2)
        cp_parser_check_for_definition_in_return_type (declarator,
                                                       decl_specifiers.type,
@@ -17068,6 +17527,9 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        decl_specs->explicit_char_p = true;
       type = char_type_node;
       break;
+    case RID_CHAR8:
+      type = char8_type_node;
+      break;
     case RID_CHAR16:
       type = char16_type_node;
       break;
@@ -17181,17 +17643,17 @@ cp_parser_simple_type_specifier (cp_parser* parser,
                error_at (token->location,
                         "use of %<auto%> in lambda parameter declaration "
                         "only available with "
-                        "-std=c++14 or -std=gnu++14");
+                        "%<-std=c++14%> or %<-std=gnu++14%>");
            }
          else if (cxx_dialect < cxx14)
            error_at (token->location,
                     "use of %<auto%> in parameter declaration "
                     "only available with "
-                    "-std=c++14 or -std=gnu++14");
+                    "%<-std=c++14%> or %<-std=gnu++14%>");
          else if (!flag_concepts)
            pedwarn (token->location, 0,
                     "use of %<auto%> in parameter declaration "
-                    "only available with -fconcepts");
+                    "only available with %<-fconcepts%>");
        }
       else
        type = make_auto ();
@@ -17299,6 +17761,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
     {
       bool qualified_p;
       bool global_p;
+      const bool typename_p = (cxx_dialect >= cxx2a
+                              && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL));
 
       /* Don't gobble tokens or issue error messages if this is an
         optional type-specifier.  */
@@ -17335,13 +17799,21 @@ cp_parser_simple_type_specifier (cp_parser* parser,
             luck.  */
          if (TREE_CODE (type) != TYPE_DECL)
            {
-             cp_parser_error (parser, "expected template-id for type");
-             type = NULL_TREE;
+             /* ...unless we pretend we have seen 'typename'.  */
+             if (typename_p)
+               type = cp_parser_make_typename_type (parser, type,
+                                                    token->location);
+             else
+               {
+                 cp_parser_error (parser, "expected template-id for type");
+                 type = NULL_TREE;
+               }
            }
        }
       /* Otherwise, look for a type-name.  */
       else
-       type = cp_parser_type_name (parser);
+       type = cp_parser_type_name (parser, (qualified_p && typename_p));
+
       /* Keep track of all name-lookups performed in class scopes.  */
       if (type
          && !global_p
@@ -17466,13 +17938,6 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
    Returns a TYPE_DECL for the type.  */
 
-static tree
-cp_parser_type_name (cp_parser* parser)
-{
-  return cp_parser_type_name (parser, /*typename_keyword_p=*/false);
-}
-
-/* See above. */
 static tree
 cp_parser_type_name (cp_parser* parser, bool typename_keyword_p)
 {
@@ -17755,7 +18220,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
          || cp_parser_is_keyword (token, RID_STRUCT))
        {
          gcc_rich_location richloc (token->location);
-         richloc.add_range (input_location, false);
+         richloc.add_range (input_location);
          richloc.add_fixit_remove ();
          pedwarn (&richloc, 0, "elaborated-type-specifier for "
                   "a scoped enum must not use the %qD keyword",
@@ -17824,6 +18289,14 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
         template-id or not.  */
       if (!template_p)
        cp_parser_parse_tentatively (parser);
+      /* The `template' keyword must follow a nested-name-specifier.  */
+      else if (!nested_name_specifier)
+       {
+         cp_parser_error (parser, "%<template%> must follow a nested-"
+                          "name-specifier");
+         return error_mark_node;
+       }
+
       /* Parse the template-id.  */
       token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_template_id (parser, template_p,
@@ -18252,7 +18725,8 @@ cp_parser_enum_specifier (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
 
       /* Parse the type-specifier-seq.  */
-      cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+      cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+                                   /*is_declaration=*/false,
                                    /*is_trailing_return=*/false,
                                     &type_specifiers);
 
@@ -18624,13 +19098,26 @@ cp_parser_namespace_name (cp_parser* parser)
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
        {
          auto_diagnostic_group d;
-         error_at (token->location, "%qD is not a namespace-name", identifier);
+         name_hint hint;
          if (namespace_decl == error_mark_node
              && parser->scope && TREE_CODE (parser->scope) == NAMESPACE_DECL)
-           suggest_alternative_in_explicit_scope (token->location, identifier,
-                                                  parser->scope);
+           hint = suggest_alternative_in_explicit_scope (token->location,
+                                                         identifier,
+                                                         parser->scope);
+         if (const char *suggestion = hint.suggestion ())
+           {
+             gcc_rich_location richloc (token->location);
+             richloc.add_fixit_replace (suggestion);
+             error_at (&richloc,
+                       "%qD is not a namespace-name; did you mean %qs?",
+                       identifier, suggestion);
+           }
+         else
+           error_at (token->location, "%qD is not a namespace-name",
+                     identifier);
        }
-      cp_parser_error (parser, "expected namespace-name");
+      else
+       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
 
@@ -18666,6 +19153,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   cp_ensure_no_oacc_routine (parser);
 
   bool is_inline = cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE);
+  const bool topmost_inline_p = is_inline;
 
   if (is_inline)
     {
@@ -18684,6 +19172,17 @@ cp_parser_namespace_definition (cp_parser* parser)
     {
       identifier = NULL_TREE;
       
+      bool nested_inline_p = cp_lexer_next_token_is_keyword (parser->lexer,
+                                                            RID_INLINE);
+      if (nested_inline_p && nested_definition_count != 0)
+       {
+         if (cxx_dialect < cxx2a)
+           pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+                    OPT_Wpedantic, "nested inline namespace definitions only "
+                    "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
+         cp_lexer_consume_token (parser->lexer);
+       }
+
       if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
        {
          identifier = cp_parser_identifier (parser);
@@ -18698,16 +19197,25 @@ cp_parser_namespace_definition (cp_parser* parser)
        }
 
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
-       break;
+       {
+         /* Don't forget that the innermost namespace might have been
+            marked as inline.  Use |= because we cannot overwrite
+            IS_INLINE in case the outermost namespace is inline, but
+            there are no nested inlines.  */
+         is_inline |= nested_inline_p;
+         break;
+       }
   
       if (!nested_definition_count && cxx_dialect < cxx17)
         pedwarn (input_location, OPT_Wpedantic,
-                 "nested namespace definitions only available with "
-                 "-std=c++17 or -std=gnu++17");
+                "nested namespace definitions only available with "
+                "%<-std=c++17%> or %<-std=gnu++17%>");
 
       /* Nested namespace names can create new namespaces (unlike
         other qualified-ids).  */
-      if (int count = identifier ? push_namespace (identifier) : 0)
+      if (int count = (identifier
+                      ? push_namespace (identifier, nested_inline_p)
+                      : 0))
        nested_definition_count += count;
       else
        cp_parser_error (parser, "nested namespace name required");
@@ -18720,7 +19228,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   if (nested_definition_count && attribs)
     error_at (token->location,
              "a nested namespace definition cannot have attributes");
-  if (nested_definition_count && is_inline)
+  if (nested_definition_count && topmost_inline_p)
     error_at (token->location,
              "a nested namespace definition cannot be inline");
 
@@ -18729,7 +19237,7 @@ cp_parser_namespace_definition (cp_parser* parser)
 
   bool has_visibility = handle_namespace_attrs (current_namespace, attribs);
 
-  warning  (OPT_Wnamespaces, "namespace %qD entered", current_namespace);
+  warning (OPT_Wnamespaces, "namespace %qD entered", current_namespace);
 
   /* Look for the `{' to validate starting the namespace.  */
   matching_braces braces;
@@ -18905,7 +19413,8 @@ cp_parser_using_declaration (cp_parser* parser,
                                                  /*is_declaration=*/true);
   if (!qscope)
     qscope = global_namespace;
-  else if (UNSCOPED_ENUM_P (qscope))
+  else if (UNSCOPED_ENUM_P (qscope)
+          && !TYPE_FUNCTION_SCOPE_P (qscope))
     qscope = CP_TYPE_CONTEXT (qscope);
 
   if (access_declaration_p && cp_parser_error_occurred (parser))
@@ -18936,7 +19445,7 @@ cp_parser_using_declaration (cp_parser* parser,
          && !in_system_header_at (ell->location))
        pedwarn (ell->location, 0,
                 "pack expansion in using-declaration only available "
-                "with -std=c++17 or -std=gnu++17");
+                "with %<-std=c++17%> or %<-std=gnu++17%>");
       qscope = make_pack_expansion (qscope);
     }
 
@@ -18998,7 +19507,7 @@ cp_parser_using_declaration (cp_parser* parser,
       if (cxx_dialect < cxx17)
        pedwarn (comma->location, 0,
                 "comma-separated list in using-declaration only available "
-                "with -std=c++17 or -std=gnu++17");
+                "with %<-std=c++17%> or %<-std=gnu++17%>");
       goto again;
     }
 
@@ -19023,7 +19532,7 @@ static tree
 cp_parser_alias_declaration (cp_parser* parser)
 {
   tree id, type, decl, pushed_scope = NULL_TREE, attributes;
-  location_t id_location;
+  location_t id_location, type_location;
   cp_declarator *declarator;
   cp_decl_specifier_seq decl_specs;
   bool member_p;
@@ -19075,7 +19584,8 @@ cp_parser_alias_declaration (cp_parser* parser)
        G_("types may not be defined in alias template declarations");
     }
 
-  type = cp_parser_type_id (parser);
+  type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                           &type_location);
 
   /* Restore the error message if need be.  */
   if (parser->num_template_parameter_lists)
@@ -19109,6 +19619,7 @@ cp_parser_alias_declaration (cp_parser* parser)
   set_and_check_decl_spec_loc (&decl_specs,
                               ds_alias,
                               using_token);
+  decl_specs.locations[ds_type_spec] = type_location;
 
   if (parser->num_template_parameter_lists
       && !cp_parser_check_template_parameters (parser,
@@ -19118,8 +19629,7 @@ cp_parser_alias_declaration (cp_parser* parser)
                                               /*declarator=*/NULL))
     return error_mark_node;
 
-  declarator = make_id_declarator (NULL_TREE, id, sfk_none);
-  declarator->id_loc = id_location;
+  declarator = make_id_declarator (NULL_TREE, id, sfk_none, id_location);
 
   member_p = at_class_scope_p ();
   if (member_p)
@@ -19199,22 +19709,35 @@ cp_parser_using_directive (cp_parser* parser)
 
 /* Parse an asm-definition.
 
+  asm-qualifier:
+    volatile
+    inline
+    goto
+
+  asm-qualifier-list:
+    asm-qualifier
+    asm-qualifier-list asm-qualifier
+
    asm-definition:
      asm ( string-literal ) ;
 
    GNU Extension:
 
    asm-definition:
-     asm volatile [opt] ( string-literal ) ;
-     asm volatile [opt] ( string-literal : asm-operand-list [opt] ) ;
-     asm volatile [opt] ( string-literal : asm-operand-list [opt]
-                         : asm-operand-list [opt] ) ;
-     asm volatile [opt] ( string-literal : asm-operand-list [opt]
-                         : asm-operand-list [opt]
+     asm asm-qualifier-list [opt] ( string-literal ) ;
+     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] ) ;
+     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt]
+                                   : asm-operand-list [opt] ) ;
+     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt]
+                                   : asm-operand-list [opt]
                          : asm-clobber-list [opt] ) ;
-     asm volatile [opt] goto ( string-literal : : asm-operand-list [opt]
-                              : asm-clobber-list [opt]
-                              : asm-goto-list ) ;  */
+     asm asm-qualifier-list [opt] ( string-literal : : asm-operand-list [opt]
+                                   : asm-clobber-list [opt]
+                                   : asm-goto-list ) ;
+
+  The form with asm-goto-list is valid if and only if the asm-qualifier-list
+  contains goto, and is the only allowed form in that case.  No duplicates are
+  allowed in an asm-qualifier-list.  */
 
 static void
 cp_parser_asm_definition (cp_parser* parser)
@@ -19225,11 +19748,9 @@ cp_parser_asm_definition (cp_parser* parser)
   tree clobbers = NULL_TREE;
   tree labels = NULL_TREE;
   tree asm_stmt;
-  bool volatile_p = false;
   bool extended_p = false;
   bool invalid_inputs_p = false;
   bool invalid_outputs_p = false;
-  bool goto_p = false;
   required_token missing = RT_NONE;
 
   /* Look for the `asm' keyword.  */
@@ -19242,24 +19763,83 @@ cp_parser_asm_definition (cp_parser* parser)
       cp_function_chain->invalid_constexpr = true;
     }
 
-  /* See if the next token is `volatile'.  */
-  if (cp_parser_allow_gnu_extensions_p (parser)
-      && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
-    {
-      /* Remember that we saw the `volatile' keyword.  */
-      volatile_p = true;
-      /* Consume the token.  */
-      cp_lexer_consume_token (parser->lexer);
-    }
-  if (cp_parser_allow_gnu_extensions_p (parser)
-      && parser->in_function_body
-      && cp_lexer_next_token_is_keyword (parser->lexer, RID_GOTO))
+  /* Handle the asm-qualifier-list.  */
+  location_t volatile_loc = UNKNOWN_LOCATION;
+  location_t inline_loc = UNKNOWN_LOCATION;
+  location_t goto_loc = UNKNOWN_LOCATION;
+  location_t first_loc = UNKNOWN_LOCATION;
+
+  if (cp_parser_allow_gnu_extensions_p (parser))
+    for (;;)
+      {
+       cp_token *token = cp_lexer_peek_token (parser->lexer);
+       location_t loc = token->location;
+       switch (cp_lexer_peek_token (parser->lexer)->keyword)
+         {
+         case RID_VOLATILE:
+           if (volatile_loc)
+             {
+               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               inform (volatile_loc, "first seen here");
+             }
+           else
+             {
+               if (!parser->in_function_body)
+                 warning_at (loc, 0, "asm qualifier %qT ignored outside of "
+                                     "function body", token->u.value);
+               volatile_loc = loc;
+             }
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         case RID_INLINE:
+           if (inline_loc)
+             {
+               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               inform (inline_loc, "first seen here");
+             }
+           else
+             inline_loc = loc;
+           if (!first_loc)
+             first_loc = loc;
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         case RID_GOTO:
+           if (goto_loc)
+             {
+               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               inform (goto_loc, "first seen here");
+             }
+           else
+             goto_loc = loc;
+           if (!first_loc)
+             first_loc = loc;
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         case RID_CONST:
+         case RID_RESTRICT:
+           error_at (loc, "%qT is not an asm qualifier", token->u.value);
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         default:
+           break;
+         }
+       break;
+      }
+
+  bool volatile_p = (volatile_loc != UNKNOWN_LOCATION);
+  bool inline_p = (inline_loc != UNKNOWN_LOCATION);
+  bool goto_p = (goto_loc != UNKNOWN_LOCATION);
+
+  if (!parser->in_function_body && (inline_p || goto_p))
     {
-      /* Remember that we saw the `goto' keyword.  */
-      goto_p = true;
-      /* Consume the token.  */
-      cp_lexer_consume_token (parser->lexer);
+      error_at (first_loc, "asm qualifier outside of function body");
+      inline_p = goto_p = false;
     }
+
   /* Look for the opening `('.  */
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return;
@@ -19351,8 +19931,7 @@ cp_parser_asm_definition (cp_parser* parser)
                                             CPP_CLOSE_PAREN))
            clobbers = cp_parser_asm_clobber_list (parser);
        }
-      else if (goto_p
-              && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
+      else if (goto_p && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
        /* The labels are coming next.  */
        labels_p = true;
 
@@ -19386,7 +19965,7 @@ cp_parser_asm_definition (cp_parser* parser)
       if (parser->in_function_body)
        {
          asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
-                                     inputs, clobbers, labels);
+                                     inputs, clobbers, labels, inline_p);
          /* If the extended syntax was not used, mark the ASM_EXPR.  */
          if (!extended_p)
            {
@@ -19455,6 +20034,8 @@ strip_declarator_types (tree type, cp_declarator *declarator)
    function-definition:
      decl-specifier-seq [opt] declarator function-transaction-block
 
+   The parser flags FLAGS is used to control type-specifier parsing.
+
    The DECL_SPECIFIERS apply to this declarator.  Returns a
    representation of the entity declared.  If MEMBER_P is TRUE, then
    this declarator appears in a class scope.  The new DECL created by
@@ -19486,6 +20067,7 @@ strip_declarator_types (tree type, cp_declarator *declarator)
 
 static tree
 cp_parser_init_declarator (cp_parser* parser,
+                          cp_parser_flags flags,
                           cp_decl_specifier_seq *decl_specifiers,
                           vec<deferred_access_check, va_gc> *checks,
                           bool function_definition_allowed_p,
@@ -19542,9 +20124,9 @@ cp_parser_init_declarator (cp_parser* parser,
   /* Parse the declarator.  */
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
-                           &ctor_dtor_or_conv_p,
+                           flags, &ctor_dtor_or_conv_p,
                            /*parenthesized_p=*/NULL,
-                           member_p, friend_p);
+                           member_p, friend_p, /*static_p=*/false);
   /* Gather up the deferred checks.  */
   stop_deferring_access_checks ();
 
@@ -19941,6 +20523,8 @@ cp_parser_init_declarator (cp_parser* parser,
      attributes [opt] ptr-operator abstract-declarator [opt]
      attributes [opt] direct-abstract-declarator
 
+   The parser flags FLAGS is used to control type-specifier parsing.
+
    If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
    detect constructors, destructors, deduction guides, or conversion operators.
    It is set to -1 if the declarator is a name, and +1 if it is a
@@ -19960,14 +20544,17 @@ cp_parser_init_declarator (cp_parser* parser,
 
    MEMBER_P is true iff this declarator is a member-declarator.
 
-   FRIEND_P is true iff this declarator is a friend.  */
+   FRIEND_P is true iff this declarator is a friend.
+
+   STATIC_P is true iff the keyword static was seen.  */
 
 static cp_declarator *
 cp_parser_declarator (cp_parser* parser,
                      cp_parser_declarator_kind dcl_kind,
+                     cp_parser_flags flags,
                      int* ctor_dtor_or_conv_p,
                      bool* parenthesized_p,
-                     bool member_p, bool friend_p)
+                     bool member_p, bool friend_p, bool static_p)
 {
   cp_declarator *declarator;
   enum tree_code code;
@@ -20005,10 +20592,11 @@ cp_parser_declarator (cp_parser* parser,
 
       /* Parse the dependent declarator.  */
       declarator = cp_parser_declarator (parser, dcl_kind,
+                                        CP_PARSER_FLAGS_NONE,
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         /*parenthesized_p=*/NULL,
                                         /*member_p=*/false,
-                                        friend_p);
+                                        friend_p, /*static_p=*/false);
 
       /* If we are parsing an abstract-declarator, we must handle the
         case where the dependent declarator is absent.  */
@@ -20026,8 +20614,8 @@ cp_parser_declarator (cp_parser* parser,
        *parenthesized_p = cp_lexer_next_token_is (parser->lexer,
                                                   CPP_OPEN_PAREN);
       declarator = cp_parser_direct_declarator (parser, dcl_kind,
-                                               ctor_dtor_or_conv_p,
-                                               member_p, friend_p);
+                                               flags, ctor_dtor_or_conv_p,
+                                               member_p, friend_p, static_p);
     }
 
   if (gnu_attributes && declarator && declarator != cp_error_declarator)
@@ -20061,14 +20649,17 @@ cp_parser_declarator (cp_parser* parser,
    we are parsing a direct-declarator.  It is
    CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
    of ambiguity we prefer an abstract declarator, as per
-   [dcl.ambig.res].  CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are
+   [dcl.ambig.res].
+   The parser flags FLAGS is used to control type-specifier parsing.
+   CTOR_DTOR_OR_CONV_P, MEMBER_P, FRIEND_P, and STATIC_P are
    as for cp_parser_declarator.  */
 
 static cp_declarator *
 cp_parser_direct_declarator (cp_parser* parser,
                             cp_parser_declarator_kind dcl_kind,
+                            cp_parser_flags flags,
                             int* ctor_dtor_or_conv_p,
-                            bool member_p, bool friend_p)
+                            bool member_p, bool friend_p, bool static_p)
 {
   cp_token *token;
   cp_declarator *declarator = NULL;
@@ -20153,7 +20744,8 @@ cp_parser_direct_declarator (cp_parser* parser,
              begin_scope (sk_function_parms, NULL_TREE);
 
              /* Parse the parameter-declaration-clause.  */
-             params = cp_parser_parameter_declaration_clause (parser);
+             params
+               = cp_parser_parameter_declaration_clause (parser, flags);
 
              /* Consume the `)'.  */
              parens.require_close (parser);
@@ -20170,6 +20762,11 @@ cp_parser_direct_declarator (cp_parser* parser,
                  tree attrs;
                  bool memfn = (member_p || (pushed_scope
                                             && CLASS_TYPE_P (pushed_scope)));
+                 unsigned char local_variables_forbidden_p
+                   = parser->local_variables_forbidden_p;
+                 /* 'this' is not allowed in static member functions.  */
+                 if (static_p || friend_p)
+                   parser->local_variables_forbidden_p |= THIS_FORBIDDEN;
 
                  is_declarator = true;
 
@@ -20217,6 +20814,10 @@ cp_parser_direct_declarator (cp_parser* parser,
                     return type, so are not those of the declared
                     function.  */
                  parser->default_arg_ok_p = false;
+
+                 /* Restore the state of local_variables_forbidden_p.  */
+                 parser->local_variables_forbidden_p
+                   = local_variables_forbidden_p;
                }
 
              /* Remove the function parms from scope.  */
@@ -20244,9 +20845,11 @@ cp_parser_direct_declarator (cp_parser* parser,
              saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
              parser->in_type_id_in_expr_p = true;
              declarator
-               = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
+               = cp_parser_declarator (parser, dcl_kind, flags,
+                                       ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL,
-                                       member_p, friend_p);
+                                       member_p, friend_p,
+                                       /*static_p=*/false);
              parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
              first = false;
              /* Expect a `)'.  */
@@ -20523,13 +21126,44 @@ cp_parser_direct_declarator (cp_parser* parser,
              }
            declarator = make_id_declarator (qualifying_scope,
                                             unqualified_name,
-                                            sfk);
+                                            sfk, token->location);
            declarator->std_attributes = attrs;
-           declarator->id_loc = token->location;
            declarator->parameter_pack_p = pack_expansion_p;
 
            if (pack_expansion_p)
              maybe_warn_variadic_templates ();
+
+           /* We're looking for this case in [temp.res]:
+              A qualified-id is assumed to name a type if [...]
+              - it is a decl-specifier of the decl-specifier-seq of a
+                parameter-declaration in a declarator of a function or
+                function template declaration, ... */
+           if (cxx_dialect >= cxx2a
+               && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL)
+               && declarator->kind == cdk_id
+               && !at_class_scope_p ()
+               && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+             {
+               /* ...whose declarator-id is qualified.  If it isn't, never
+                  assume the parameters to refer to types.  */
+               if (qualifying_scope == NULL_TREE)
+                 flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+               else
+                 {
+                   /* Now we have something like
+                      template <typename T> int C::x(S::p);
+                      which can be a function template declaration or a
+                      variable template definition.  If name lookup for
+                      the declarator-id C::x finds one or more function
+                      templates, assume S::p to name a type.  Otherwise,
+                      don't.  */
+                   tree decl
+                     = cp_parser_lookup_name_simple (parser, unqualified_name,
+                                                     token->location);
+                   if (!is_overloaded_fn (decl))
+                     flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+                 }
+             }
          }
 
        handle_declarator:;
@@ -21095,19 +21729,31 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
    type-id:
      type-specifier-seq abstract-declarator [opt]
 
+   The parser flags FLAGS is used to control type-specifier parsing.
+
+   If IS_TEMPLATE_ARG is true, we are parsing a template argument.
+
+   If IS_TRAILING_RETURN is true, we are in a trailing-return-type,
+   i.e. we've just seen "->".
+
    Returns the TYPE specified.  */
 
 static tree
-cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
-                    bool is_trailing_return)
+cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
+                    bool is_template_arg, bool is_trailing_return,
+                    location_t *type_location)
 {
   cp_decl_specifier_seq type_specifier_seq;
   cp_declarator *abstract_declarator;
 
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+  cp_parser_type_specifier_seq (parser, flags,
+                               /*is_declaration=*/false,
                                is_trailing_return,
                                &type_specifier_seq);
+  if (type_location)
+    *type_location = type_specifier_seq.locations[ds_type_spec];
+
   if (is_template_arg && type_specifier_seq.type
       && TREE_CODE (type_specifier_seq.type) == TEMPLATE_TYPE_PARM
       && CLASS_PLACEHOLDER_TEMPLATE (type_specifier_seq.type))
@@ -21125,10 +21771,12 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
   cp_parser_parse_tentatively (parser);
   /* Look for the declarator.  */
   abstract_declarator
-    = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
+    = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT,
+                           CP_PARSER_FLAGS_NONE, NULL,
                            /*parenthesized_p=*/NULL,
                            /*member_p=*/false,
-                           /*friend_p=*/false);
+                           /*friend_p=*/false,
+                           /*static_p=*/false);
   /* Check to see if there really was a declarator.  */
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
@@ -21172,12 +21820,17 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
                       is_template_arg);
 }
 
+/* Wrapper for cp_parser_type_id_1.  */
+
 static tree
-cp_parser_type_id (cp_parser *parser)
+cp_parser_type_id (cp_parser *parser, cp_parser_flags flags,
+                  location_t *type_location)
 {
-  return cp_parser_type_id_1 (parser, false, false);
+  return cp_parser_type_id_1 (parser, flags, false, false, type_location);
 }
 
+/* Wrapper for cp_parser_type_id_1.  */
+
 static tree
 cp_parser_template_type_arg (cp_parser *parser)
 {
@@ -21185,7 +21838,7 @@ cp_parser_template_type_arg (cp_parser *parser)
   const char *saved_message = parser->type_definition_forbidden_message;
   parser->type_definition_forbidden_message
     = G_("types may not be defined in template arguments");
-  r = cp_parser_type_id_1 (parser, true, false);
+  r = cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_NONE, true, false, NULL);
   parser->type_definition_forbidden_message = saved_message;
   if (cxx_dialect >= cxx14 && !flag_concepts && type_uses_auto (r))
     {
@@ -21195,10 +21848,13 @@ cp_parser_template_type_arg (cp_parser *parser)
   return r;
 }
 
+/* Wrapper for cp_parser_type_id_1.  */
+
 static tree
 cp_parser_trailing_type_id (cp_parser *parser)
 {
-  return cp_parser_type_id_1 (parser, false, true);
+  return cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                             false, true, NULL);
 }
 
 /* Parse a type-specifier-seq.
@@ -21211,6 +21867,8 @@ cp_parser_trailing_type_id (cp_parser *parser)
    type-specifier-seq:
      attributes type-specifier-seq [opt]
 
+   The parser flags FLAGS is used to control type-specifier parsing.
+
    If IS_DECLARATION is true, we are at the start of a "condition" or
    exception-declaration, so we might be followed by a declarator-id.
 
@@ -21221,17 +21879,18 @@ cp_parser_trailing_type_id (cp_parser *parser)
 
 static void
 cp_parser_type_specifier_seq (cp_parser* parser,
+                             cp_parser_flags flags,
                              bool is_declaration,
                              bool is_trailing_return,
                              cp_decl_specifier_seq *type_specifier_seq)
 {
   bool seen_type_specifier = false;
-  cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
   cp_token *start_token = NULL;
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
 
+  flags |= CP_PARSER_FLAGS_OPTIONAL;
   /* In the context of a trailing return type, enum E { } is an
      elaborated-type-specifier followed by a function-body, not an
      enum-specifier.  */
@@ -21337,12 +21996,15 @@ function_being_declared_is_template_p (cp_parser* parser)
      parameter-declaration-list [opt] ... [opt]
      parameter-declaration-list , ...
 
+   The parser flags FLAGS is used to control type-specifier parsing.
+
    Returns a representation for the parameter declarations.  A return
    value of NULL indicates a parameter-declaration-clause consisting
    only of an ellipsis.  */
 
 static tree
-cp_parser_parameter_declaration_clause (cp_parser* parser)
+cp_parser_parameter_declaration_clause (cp_parser* parser,
+                                       cp_parser_flags flags)
 {
   tree parameters;
   cp_token *token;
@@ -21372,16 +22034,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     }
   else if (token->type == CPP_CLOSE_PAREN)
     /* There are no parameters.  */
-    {
-#ifdef SYSTEM_IMPLICIT_EXTERN_C
-      if (in_system_header_at (input_location)
-         && current_class_type == NULL
-         && current_lang_name == lang_name_c)
-       return NULL_TREE;
-      else
-#endif
-       return void_list_node;
-    }
+    return void_list_node;
   /* Check for `(void)', too, which is a special case.  */
   else if (token->keyword == RID_VOID
           && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
@@ -21394,7 +22047,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     }
 
   /* Parse the parameter-declaration-list.  */
-  parameters = cp_parser_parameter_declaration_list (parser);
+  parameters = cp_parser_parameter_declaration_list (parser, flags);
   /* If a parse error occurred while parsing the
      parameter-declaration-list, then the entire
      parameter-declaration-clause is erroneous.  */
@@ -21437,12 +22090,14 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
      parameter-declaration
      parameter-declaration-list , parameter-declaration
 
+   The parser flags FLAGS is used to control type-specifier parsing.
+
    Returns a representation of the parameter-declaration-list, as for
    cp_parser_parameter_declaration_clause.  However, the
    `void_list_node' is never appended to the list.  */
 
 static tree
-cp_parser_parameter_declaration_list (cp_parser* parser)
+cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags)
 {
   tree parameters = NULL_TREE;
   tree *tail = &parameters;
@@ -21465,7 +22120,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
 
       /* Parse the parameter.  */
       parameter
-       = cp_parser_parameter_declaration (parser,
+       = cp_parser_parameter_declaration (parser, flags,
                                           /*template_parm_p=*/false,
                                           &parenthesized_p);
 
@@ -21597,6 +22252,8 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
      decl-specifier-seq ... [opt] abstract-declarator [opt]
      decl-specifier-seq abstract-declarator [opt] = assignment-expression
 
+   The parser flags FLAGS is used to control type-specifier parsing.
+
    If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
    declares a template parameter.  (In that case, a non-nested `>'
    token encountered during the parsing of the assignment-expression
@@ -21608,6 +22265,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
 
 static cp_parameter_declarator *
 cp_parser_parameter_declaration (cp_parser *parser,
+                                cp_parser_flags flags,
                                 bool template_parm_p,
                                 bool *parenthesized_p)
 {
@@ -21640,7 +22298,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
   /* Parse the declaration-specifiers.  */
   cp_token *decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
-                               CP_PARSER_FLAGS_NONE,
+                               flags,
                                &decl_specifiers,
                                &declares_class_or_enum);
 
@@ -21699,10 +22357,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
       declarator_token_start = token;
       declarator = cp_parser_declarator (parser,
                                         CP_PARSER_DECLARATOR_EITHER,
+                                        CP_PARSER_FLAGS_NONE,
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         parenthesized_p,
                                         /*member_p=*/false,
-                                        /*friend_p=*/false);
+                                        /*friend_p=*/false,
+                                        /*static_p=*/false);
       parser->default_arg_ok_p = saved_default_arg_ok_p;
       /* After the declarator, allow more attributes.  */
       decl_specifiers.attributes
@@ -21841,6 +22501,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
   else
     default_argument = NULL_TREE;
 
+  if (default_argument)
+    STRIP_ANY_LOCATION_WRAPPER (default_argument);
+
   /* Generate a location for the parameter, ranging from the start of the
      initial token to the end of the final token (using input_location for
      the latter, set up by cp_lexer_set_source_position_from_token when
@@ -21880,7 +22543,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
 {
   tree default_argument = NULL_TREE;
   bool saved_greater_than_is_operator_p;
-  bool saved_local_variables_forbidden_p;
+  unsigned char saved_local_variables_forbidden_p;
   bool non_constant_p, is_direct_init;
 
   /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
@@ -21890,7 +22553,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
   /* Local variable names (and the `this' keyword) may not
      appear in a default argument.  */
   saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
-  parser->local_variables_forbidden_p = true;
+  parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN;
   /* Parse the assignment-expression.  */
   if (template_parm_p)
     push_deferring_access_checks (dk_no_deferred);
@@ -21944,11 +22607,25 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
                                                  bool in_function_try_block)
 {
   tree body, list;
-  const bool check_body_p =
-     DECL_CONSTRUCTOR_P (current_function_decl)
-     && DECL_DECLARED_CONSTEXPR_P (current_function_decl);
+  const bool check_body_p
+     = (DECL_CONSTRUCTOR_P (current_function_decl)
+       && DECL_DECLARED_CONSTEXPR_P (current_function_decl));
   tree last = NULL;
 
+  if (in_function_try_block
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && cxx_dialect < cxx2a)
+    {
+      if (DECL_CONSTRUCTOR_P (current_function_decl))
+       pedwarn (input_location, 0,
+                "function-try-block body of %<constexpr%> constructor only "
+                "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
+      else
+       pedwarn (input_location, 0,
+                "function-try-block body of %<constexpr%> function only "
+                "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
+    }
+
   /* Begin the function body.  */
   body = begin_function_body ();
   /* Parse the optional ctor-initializer.  */
@@ -22108,9 +22785,11 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
   /* If it's not a `}', then there is a non-trivial initializer.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
     {
+      bool designated;
       /* Parse the initializer list.  */
       CONSTRUCTOR_ELTS (initializer)
-       = cp_parser_initializer_list (parser, non_constant_p);
+       = cp_parser_initializer_list (parser, non_constant_p, &designated);
+      CONSTRUCTOR_IS_DESIGNATED_INIT (initializer) = designated;
       /* A trailing `,' token is allowed.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
        cp_lexer_consume_token (parser->lexer);
@@ -22146,8 +22825,11 @@ cp_parser_skip_to_closing_square_bracket (cp_parser *parser)
 
       switch (token->type)
        {
-       case CPP_EOF:
        case CPP_PRAGMA_EOL:
+         if (!parser->lexer->in_pragma)
+           break;
+         /* FALLTHRU */
+       case CPP_EOF:
          /* If we've run out of tokens, then there is no closing `]'.  */
          return false;
 
@@ -22227,10 +22909,12 @@ cp_parser_array_designator_p (cp_parser *parser)
    Returns a vec of constructor_elt.  The VALUE of each elt is an expression
    for the initializer.  If the INDEX of the elt is non-NULL, it is the
    IDENTIFIER_NODE naming the field to initialize.  NON_CONSTANT_P is
-   as for cp_parser_initializer.  */
+   as for cp_parser_initializer.  Set *DESIGNATED to a boolean whether there
+   are any designators.  */
 
 static vec<constructor_elt, va_gc> *
-cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
+cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p,
+                           bool *designated)
 {
   vec<constructor_elt, va_gc> *v = NULL;
   bool first_p = true;
@@ -22260,7 +22944,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          if (cxx_dialect < cxx2a)
            pedwarn (loc, OPT_Wpedantic,
                     "C++ designated initializers only available with "
-                    "-std=c++2a or -std=gnu++2a");
+                    "%<-std=c++2a%> or %<-std=gnu++2a%>");
          /* Consume the `.'.  */
          cp_lexer_consume_token (parser->lexer);
          /* Consume the identifier.  */
@@ -22397,7 +23081,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
                          "%<.%s%> designator used multiple times in "
                          "the same initializer list",
                          IDENTIFIER_POINTER (designator));
-               (*v)[i].index = NULL_TREE;
+               (*v)[i].index = error_mark_node;
              }
            else
              IDENTIFIER_MARKED (designator) = 1;
@@ -22407,6 +23091,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          IDENTIFIER_MARKED (designator) = 0;
     }
 
+  *designated = first_designator != NULL_TREE;
   return v;
 }
 
@@ -22535,7 +23220,9 @@ cp_parser_class_name (cp_parser *parser,
   decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
 
   /* If this is a typename, create a TYPENAME_TYPE.  */
-  if (typename_p && decl != error_mark_node)
+  if (typename_p
+      && decl != error_mark_node
+      && !is_overloaded_fn (decl))
     {
       decl = make_typename_type (scope, decl, typename_type,
                                 /*complain=*/tf_error);
@@ -22631,7 +23318,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
   cp_ensure_no_oacc_routine (parser);
 
   /* Issue an error message if type-definitions are forbidden here.  */
-  cp_parser_check_type_definition (parser);
+  bool type_definition_ok_p = cp_parser_check_type_definition (parser);
   /* Remember that we are defining one more class.  */
   ++parser->num_classes_being_defined;
   /* Inside the class, surrounding template-parameter-lists do not
@@ -22826,7 +23513,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
       cp_default_arg_entry *e;
       tree save_ccp, save_ccr;
 
-      if (any_erroneous_template_args_p (type))
+      if (!type_definition_ok_p || any_erroneous_template_args_p (type))
        {
          /* Skip default arguments, NSDMIs, etc, in order to improve
             error recovery (c++/71169, c++/71832).  */
@@ -23351,8 +24038,11 @@ cp_parser_class_head (cp_parser* parser,
   cp_parser_check_class_key (class_key, type);
 
   /* If this type was already complete, and we see another definition,
-     that's an error.  */
-  if (type != error_mark_node && COMPLETE_TYPE_P (type))
+     that's an error.  Likewise if the type is already being defined:
+     this can happen, eg, when it's defined from within an expression 
+     (c++/84605).  */
+  if (type != error_mark_node
+      && (COMPLETE_TYPE_P (type) || TYPE_BEING_DEFINED (type)))
     {
       error_at (type_start_token->location, "redefinition of %q#T",
                type);
@@ -23471,7 +24161,7 @@ cp_parser_type_parameter_key (cp_parser* parser)
           by the standard until C++17.  */
        pedwarn (token->location, OPT_Wpedantic, 
                 "ISO C++ forbids typename key in template template parameter;"
-                " use -std=c++17 or -std=gnu++17");
+                " use %<-std=c++17%> or %<-std=gnu++17%>");
     }
   else
     cp_parser_error (parser, "expected %<class%> or %<typename%>");
@@ -23672,7 +24362,8 @@ cp_parser_member_declaration (cp_parser* parser)
   /* Parse the decl-specifier-seq.  */
   decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
-                               CP_PARSER_FLAGS_OPTIONAL,
+                               (CP_PARSER_FLAGS_OPTIONAL
+                                | CP_PARSER_FLAGS_TYPENAME_OPTIONAL),
                                &decl_specifiers,
                                &declares_class_or_enum);
   /* Check for an invalid type-name.  */
@@ -23823,6 +24514,8 @@ cp_parser_member_declaration (cp_parser* parser)
              tree identifier;
              tree width;
              tree late_attributes = NULL_TREE;
+             location_t id_location
+               = cp_lexer_peek_token (parser->lexer)->location;
 
              if (named_bitfld)
                identifier = cp_parser_identifier (parser);
@@ -23854,8 +24547,8 @@ cp_parser_member_declaration (cp_parser* parser)
                      && identifier != NULL_TREE)
                    pedwarn (loc, 0,
                             "default member initializers for bit-fields "
-                            "only available with -std=c++2a or "
-                            "-std=gnu++2a");
+                            "only available with %<-std=c++2a%> or "
+                            "%<-std=gnu++2a%>");
 
                  initializer = cp_parser_save_nsdmi (parser);
                  if (identifier == NULL_TREE)
@@ -23891,7 +24584,8 @@ cp_parser_member_declaration (cp_parser* parser)
              decl = grokbitfield (identifier
                                   ? make_id_declarator (NULL_TREE,
                                                         identifier,
-                                                        sfk_none)
+                                                        sfk_none,
+                                                        id_location)
                                   : NULL,
                                   &decl_specifiers,
                                   width, initializer,
@@ -23902,14 +24596,16 @@ cp_parser_member_declaration (cp_parser* parser)
              cp_declarator *declarator;
              tree asm_specification;
              int ctor_dtor_or_conv_p;
+             bool static_p = (decl_specifiers.storage_class == sc_static);
 
              /* Parse the declarator.  */
              declarator
                = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                                       CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
                                        &ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL,
                                        /*member_p=*/true,
-                                       friend_p);
+                                       friend_p, static_p);
 
              /* If something went wrong parsing the declarator, make sure
                 that we at least consume some tokens.  */
@@ -24474,6 +25170,12 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
          matching_parens parens;
          parens.consume_open (parser);
 
+         tree save_ccp = current_class_ptr;
+         tree save_ccr = current_class_ref;
+
+         if (current_class_type)
+           inject_this_parameter (current_class_type, TYPE_UNQUALIFIED);
+
          if (require_constexpr)
            {
              /* Types may not be defined in an exception-specification.  */
@@ -24481,7 +25183,17 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
              parser->type_definition_forbidden_message
              = G_("types may not be defined in an exception-specification");
 
-             expr = cp_parser_constant_expression (parser);
+             bool non_constant_p;
+             expr
+               = cp_parser_constant_expression (parser,
+                                                /*allow_non_constant=*/true,
+                                                &non_constant_p);
+             if (non_constant_p
+                 && !require_potential_rvalue_constant_expression (expr))
+               {
+                 expr = NULL_TREE;
+                 return_cond = true;
+               }
 
              /* Restore the saved message.  */
              parser->type_definition_forbidden_message = saved_message;
@@ -24493,6 +25205,9 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
            }
 
          parens.require_close (parser);
+
+         current_class_ptr = save_ccp;
+         current_class_ref = save_ccr;
        }
       else
        {
@@ -24653,8 +25368,11 @@ cp_parser_try_block (cp_parser* parser)
 
   cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
   if (parser->in_function_body
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
-    error ("%<try%> in %<constexpr%> function");
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && cxx_dialect < cxx2a)
+    pedwarn (input_location, 0,
+            "%<try%> in %<constexpr%> function only "
+            "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
 
   try_block = begin_try_block ();
   cp_parser_compound_statement (parser, NULL, BCS_TRY_BLOCK, false);
@@ -24768,7 +25486,8 @@ cp_parser_exception_declaration (cp_parser* parser)
     = G_("types may not be defined in exception-declarations");
 
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+  cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+                               /*is_declaration=*/true,
                                /*is_trailing_return=*/false,
                                &type_specifiers);
   /* If it's a `)', then there is no declarator.  */
@@ -24776,10 +25495,12 @@ cp_parser_exception_declaration (cp_parser* parser)
     declarator = NULL;
   else
     declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
+                                      CP_PARSER_FLAGS_NONE,
                                       /*ctor_dtor_or_conv_p=*/NULL,
                                       /*parenthesized_p=*/NULL,
                                       /*member_p=*/false,
-                                      /*friend_p=*/false);
+                                      /*friend_p=*/false,
+                                      /*static_p=*/false);
 
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
@@ -25118,9 +25839,11 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
       /* Look for the two `(' tokens.  */
       matching_parens outer_parens;
-      outer_parens.require_open (parser);
+      if (!outer_parens.require_open (parser))
+       ok = false;
       matching_parens inner_parens;
-      inner_parens.require_open (parser);
+      if (!inner_parens.require_open (parser))
+       ok = false;
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -25165,11 +25888,15 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
    the arguments, if any.  */
 
 static tree
-cp_parser_gnu_attribute_list (cp_parser* parser)
+cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
 {
   tree attribute_list = NULL_TREE;
   bool save_translate_strings_p = parser->translate_strings_p;
 
+  /* Don't create wrapper nodes within attributes: the
+     handlers don't know how to handle them.  */
+  auto_suppress_location_wrappers sentinel;
+
   parser->translate_strings_p = false;
   while (true)
     {
@@ -25232,9 +25959,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser)
 
          token = cp_lexer_peek_token (parser->lexer);
        }
-      /* Now, look for more attributes.  If the next token isn't a
-        `,', we're done.  */
-      if (token->type != CPP_COMMA)
+      /* Unless EXACTLY_ONE is set look for more attributes.
+        If the next token isn't a `,', we're done.  */
+      if (exactly_one || token->type != CPP_COMMA)
        break;
 
       /* Consume the comma and keep going.  */
@@ -25336,14 +26063,19 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
          return error_mark_node;
        }
 
+      attr_ns = canonicalize_attr_name (attr_ns);
       attr_id = canonicalize_attr_name (attr_id);
       attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
                                   NULL_TREE);
       token = cp_lexer_peek_token (parser->lexer);
     }
   else if (attr_ns)
-    attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
-                                NULL_TREE);
+    {
+      attr_ns = canonicalize_attr_name (attr_ns);
+      attr_id = canonicalize_attr_name (attr_id);
+      attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
+                                  NULL_TREE);
+    }
   else
     {
       attr_id = canonicalize_attr_name (attr_id);
@@ -25519,7 +26251,7 @@ cp_parser_std_attribute_spec (cp_parser *parser)
                  && !in_system_header_at (input_location))
                pedwarn (input_location, 0,
                         "attribute using prefix only available "
-                        "with -std=c++17 or -std=gnu++17");
+                        "with %<-std=c++17%> or %<-std=gnu++17%>");
 
              cp_lexer_consume_token (parser->lexer);
              cp_lexer_consume_token (parser->lexer);
@@ -25535,7 +26267,7 @@ cp_parser_std_attribute_spec (cp_parser *parser)
          || !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
        cp_parser_skip_to_end_of_statement (parser);
       else
-       /* Warn about parsing c++11 attribute in non-c++1 mode, only
+       /* Warn about parsing c++11 attribute in non-c++11 mode, only
           when we are sure that we have actually parsed them.  */
        maybe_warn_cpp0x (CPP0X_ATTRIBUTES);
     }
@@ -25610,6 +26342,10 @@ cp_parser_std_attribute_spec_seq (cp_parser *parser)
   tree attr_specs = NULL_TREE;
   tree attr_last = NULL_TREE;
 
+  /* Don't create wrapper nodes within attributes: the
+     handlers don't know how to handle them.  */
+  auto_suppress_location_wrappers sentinel;
+
   while (true)
     {
       tree attr_spec = cp_parser_std_attribute_spec (parser);
@@ -25639,8 +26375,11 @@ cp_parser_skip_balanced_tokens (cp_parser *parser, size_t n)
   do
     switch (cp_lexer_peek_nth_token (parser->lexer, n++)->type)
       {
-      case CPP_EOF:
       case CPP_PRAGMA_EOL:
+       if (!parser->lexer->in_pragma)
+         break;
+       /* FALLTHRU */
+      case CPP_EOF:
        /* Ran out of tokens.  */
        return orig_n;
       case CPP_OPEN_PAREN:
@@ -25835,7 +26574,7 @@ cp_parser_requires_clause_opt (cp_parser *parser)
          && tok->u.value == ridpointers[RID_REQUIRES])
        {
          error_at (cp_lexer_peek_token (parser->lexer)->location,
-                   "%<requires%> only available with -fconcepts");
+                   "%<requires%> only available with %<-fconcepts%>");
          /* Parse and discard the requires-clause.  */
          cp_lexer_consume_token (parser->lexer);
          cp_parser_requires_clause (parser);
@@ -25926,7 +26665,8 @@ cp_parser_requirement_parameter_list (cp_parser *parser)
   if (!parens.require_open (parser))
     return error_mark_node;
 
-  tree parms = cp_parser_parameter_declaration_clause (parser);
+  tree parms
+    = cp_parser_parameter_declaration_clause (parser, CP_PARSER_FLAGS_NONE);
 
   if (!parens.require_close (parser))
     return error_mark_node;
@@ -26680,6 +27420,16 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
                                            /*type_p=*/false,
                                            /*is_declaration=*/false));
 
+  /* Resolve the TYPENAME_TYPE, because the call above didn't do it.  */
+  if (nested_name_specifier
+      && TREE_CODE (nested_name_specifier) == TYPENAME_TYPE)
+    {
+      tree s = resolve_typename_type (nested_name_specifier,
+                                     /*only_current_p=*/false);
+      if (TREE_CODE (s) != TYPENAME_TYPE)
+       nested_name_specifier = s;
+    }
+
   outside_class_specifier_p = (!at_class_scope_p ()
                               || !TYPE_BEING_DEFINED (current_class_type)
                               || friend_p);
@@ -27084,8 +27834,12 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
            {
              tree parm_list = TREE_VEC_ELT (parameter_list, 0);
              tree parm = INNERMOST_TEMPLATE_PARMS (parm_list);
-             if (TREE_TYPE (parm) != char_type_node
-                 || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+             if (CLASS_TYPE_P (TREE_TYPE (parm)))
+               /* OK, C++20 string literal operator template.  We don't need
+                  to warn in lower dialects here because we will have already
+                  warned about the template parameter.  */;
+             else if (TREE_TYPE (parm) != char_type_node
+                      || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
                ok = false;
            }
          else if (num_parms == 2 && cxx_dialect >= cxx14)
@@ -27098,20 +27852,25 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
                  || TREE_TYPE (parm) != TREE_TYPE (type)
                  || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
                ok = false;
+             else
+               /* http://cplusplus.github.io/EWG/ewg-active.html#66  */
+               pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+                        "ISO C++ did not adopt string literal operator templa"
+                        "tes taking an argument pack of characters");
            }
          else
            ok = false;
        }
       if (!ok)
        {
-         if (cxx_dialect >= cxx14)
-           error ("literal operator template %qD has invalid parameter list."
-                  "  Expected non-type template argument pack <char...>"
-                  " or <typename CharT, CharT...>",
+         if (cxx_dialect > cxx17)
+           error ("literal operator template %qD has invalid parameter list;"
+                  "  Expected non-type template parameter pack <char...> "
+                  "or single non-type parameter of class type",
                   decl);
          else
            error ("literal operator template %qD has invalid parameter list."
-                  "  Expected non-type template argument pack <char...>",
+                  "  Expected non-type template parameter pack <char...>",
                   decl);
        }
     }
@@ -27176,18 +27935,18 @@ cp_parser_template_introduction (cp_parser* parser, bool member_p)
      matching identifiers.  */
   tree introduction_list = cp_parser_introduction_list (parser);
 
+  /* Look for closing brace for introduction.  */
+  if (!braces.require_close (parser))
+    return true;
+
   /* The introduction-list shall not be empty.  */
   int nargs = TREE_VEC_LENGTH (introduction_list);
   if (nargs == 0)
     {
-      error ("empty introduction-list");
+      /* In cp_parser_introduction_list we have already issued an error.  */
       return true;
     }
 
-  /* Look for closing brace for introduction.  */
-  if (!braces.require_close (parser))
-    return true;
-
   if (tmpl_decl == error_mark_node)
     {
       cp_parser_name_lookup_error (parser, concept_name, tmpl_decl, NLE_NULL,
@@ -27349,7 +28108,8 @@ cp_parser_single_declaration (cp_parser* parser,
      alternative.  */
   decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
-                               CP_PARSER_FLAGS_OPTIONAL,
+                               (CP_PARSER_FLAGS_OPTIONAL
+                                | CP_PARSER_FLAGS_TYPENAME_OPTIONAL),
                                &decl_specifiers,
                                &declares_class_or_enum);
   if (friend_p)
@@ -27439,6 +28199,7 @@ cp_parser_single_declaration (cp_parser* parser,
          || decl_specifiers.type != error_mark_node))
     {
       decl = cp_parser_init_declarator (parser,
+                                       CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
                                        &decl_specifiers,
                                        checks,
                                        /*function_definition_allowed_p=*/true,
@@ -27700,8 +28461,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   tree saved_qualifying_scope;
   tree saved_object_scope;
   bool saved_greater_than_is_operator_p;
-  int saved_unevaluated_operand;
-  int saved_inhibit_evaluation_warnings;
 
   /* [temp.names]
 
@@ -27718,10 +28477,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   saved_object_scope = parser->object_scope;
   /* We need to evaluate the template arguments, even though this
      template-id may be nested within a "sizeof".  */
-  saved_unevaluated_operand = cp_unevaluated_operand;
-  cp_unevaluated_operand = 0;
-  saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
-  c_inhibit_evaluation_warnings = 0;
+  cp_evaluated ev;
   /* Parse the template-argument-list itself.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER)
       || cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
@@ -27790,8 +28546,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   parser->scope = saved_scope;
   parser->qualifying_scope = saved_qualifying_scope;
   parser->object_scope = saved_object_scope;
-  cp_unevaluated_operand = saved_unevaluated_operand;
-  c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
 
   return arguments;
 }
@@ -27993,7 +28747,7 @@ cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field)
 static void
 cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 {
-  bool saved_local_variables_forbidden_p;
+  unsigned char saved_local_variables_forbidden_p;
   tree parm, parmdecl;
 
   /* While we're parsing the default args, we might (due to the
@@ -28005,7 +28759,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
   /* Local variable names (and the `this' keyword) may not appear
      in a default argument.  */
   saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
-  parser->local_variables_forbidden_p = true;
+  parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN;
 
   push_defarg_context (fn);
 
@@ -28171,20 +28925,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 
       /* If all went well, then we're done.  */
       if (cp_parser_parse_definitely (parser))
-       {
-         cp_decl_specifier_seq decl_specs;
-
-         /* Build a trivial decl-specifier-seq.  */
-         clear_decl_specs (&decl_specs);
-         decl_specs.type = type;
-
-         /* Call grokdeclarator to figure out what type this is.  */
-         expr = grokdeclarator (NULL,
-                                &decl_specs,
-                                TYPENAME,
-                                /*initialized=*/0,
-                                /*attrlist=*/NULL);
-       }
+       expr = type;
     }
 
   /* If the type-id production did not work out, then we must be
@@ -28292,14 +29033,15 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
 {
   decl_specs->any_specifiers_p = true;
 
-  /* If the user tries to redeclare bool, char16_t, char32_t, or wchar_t
-     (with, for example, in "typedef int wchar_t;") we remember that
+  /* If the user tries to redeclare bool, char8_t, char16_t, char32_t, or
+     wchar_t (with, for example, in "typedef int wchar_t;") we remember that
      this is what happened.  In system headers, we ignore these
      declarations so that G++ can work with system headers that are not
      C++-safe.  */
   if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)
       && !type_definition_p
       && (type_spec == boolean_type_node
+         || type_spec == char8_type_node
          || type_spec == char16_type_node
          || type_spec == char32_type_node
          || type_spec == wchar_type_node)
@@ -28361,7 +29103,7 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
   if (decl_specs == NULL)
     return;
 
-  source_location location = token->location;
+  location_t location = token->location;
 
   if (decl_specs->locations[ds] == 0)
     {
@@ -28390,7 +29132,7 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
          gcc_rich_location richloc (location);
          if (gnu != decl_specs->gnu_thread_keyword_p)
            {
-             richloc.add_range (decl_specs->locations[ds_thread], false);
+             richloc.add_range (decl_specs->locations[ds_thread]);
              error_at (&richloc,
                        "both %<__thread%> and %<thread_local%> specified");
            }
@@ -29093,10 +29835,12 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
                      int ctor_dtor_or_conv_p;
                      cp_lexer_consume_token (parser->lexer);
                      cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                                           CP_PARSER_FLAGS_NONE,
                                            &ctor_dtor_or_conv_p,
                                            /*parenthesized_p=*/NULL,
                                            /*member_p=*/true,
-                                           /*friend_p=*/false);
+                                           /*friend_p=*/false,
+                                           /*static_p=*/false);
                      peek = cp_lexer_peek_token (parser->lexer);
                      if (cp_parser_error_occurred (parser))
                        break;
@@ -29112,8 +29856,9 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
                {
                  cp_lexer_consume_token (parser->lexer);
                  begin_scope (sk_function_parms, NULL_TREE);
-                 if (cp_parser_parameter_declaration_list (parser)
-                     == error_mark_node)
+                 tree t = cp_parser_parameter_declaration_list
+                           (parser, CP_PARSER_FLAGS_NONE);
+                 if (t == error_mark_node)
                    error = true;
                  pop_bindings_and_leave_scope ();
                }
@@ -30128,7 +30873,8 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
        }
 
       /* TODO: parse attributes for tail parameters.  */
-      parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+      parmdecl = cp_parser_parameter_declaration (parser, CP_PARSER_FLAGS_NONE,
+                                                 false, NULL);
       parm = grokdeclarator (parmdecl->declarator,
                             &parmdecl->decl_specifiers,
                             PARM, /*initialized=*/0,
@@ -30444,7 +31190,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
              /* Get the name of the bitfield.  */
              declarator = make_id_declarator (NULL_TREE,
                                               cp_parser_identifier (parser),
-                                              sfk_none);
+                                              sfk_none, token->location);
 
             eat_colon:
              cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
@@ -30457,10 +31203,12 @@ cp_parser_objc_class_ivars (cp_parser* parser)
              /* Parse the declarator.  */
              declarator
                = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                                       CP_PARSER_FLAGS_NONE,
                                        &ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL,
                                        /*member_p=*/false,
-                                       /*friend_p=*/false);
+                                       /*friend_p=*/false,
+                                       /*static_p=*/false);
            }
 
          /* Look for attributes that apply to the ivar.  */
@@ -30810,7 +31558,8 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
        {
          /* We have "@catch (NSException *exception)" or something
             like that.  Parse the parameter declaration.  */
-         parm = cp_parser_parameter_declaration (parser, false, NULL);
+         parm = cp_parser_parameter_declaration (parser, CP_PARSER_FLAGS_NONE,
+                                                 false, NULL);
          if (parm == NULL)
            parameter_declaration = error_mark_node;
          else
@@ -31016,7 +31765,8 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
 
       /* Parse the declarator.  */
       declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
-                                        NULL, NULL, false, false);
+                                        CP_PARSER_FLAGS_NONE,
+                                        NULL, NULL, false, false, false);
 
       /* Look for attributes that apply to the ivar.  */
       attributes = cp_parser_attributes_opt (parser);
@@ -31349,7 +32099,7 @@ cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
 }
 
 \f
-/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 parsing routines.  */
+/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 / 4.5 / 5.0 parsing routines.  */
 
 /* Returns name of the next clause.
    If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
@@ -31439,6 +32189,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
        case 'i':
          if (!strcmp ("if_present", p))
            result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
+         else if (!strcmp ("in_reduction", p))
+           result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
          else if (!strcmp ("inbranch", p))
            result = PRAGMA_OMP_CLAUSE_INBRANCH;
          else if (!strcmp ("independent", p))
@@ -31463,6 +32215,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
        case 'n':
          if (!strcmp ("nogroup", p))
            result = PRAGMA_OMP_CLAUSE_NOGROUP;
+         else if (!strcmp ("nontemporal", p))
+           result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
          else if (!strcmp ("notinbranch", p))
            result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
          else if (!strcmp ("nowait", p))
@@ -31527,7 +32281,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OMP_CLAUSE_SIMDLEN;
          break;
        case 't':
-         if (!strcmp ("taskgroup", p))
+         if (!strcmp ("task_reduction", p))
+           result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
+         else if (!strcmp ("taskgroup", p))
            result = PRAGMA_OMP_CLAUSE_TASKGROUP;
          else if (!strcmp ("thread_limit", p))
            result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
@@ -31618,6 +32374,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
     {
       tree name, decl;
 
+      if (kind == OMP_CLAUSE_DEPEND)
+       cp_parser_parse_tentatively (parser);
       token = cp_lexer_peek_token (parser->lexer);
       if (kind != 0
          && current_class_ptr
@@ -31637,15 +32395,25 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                                          /*declarator_p=*/false,
                                          /*optional_p=*/false);
          if (name == error_mark_node)
-           goto skip_comma;
+           {
+             if (kind == OMP_CLAUSE_DEPEND
+                 && cp_parser_simulate_error (parser))
+               goto depend_lvalue;
+             goto skip_comma;
+           }
 
          if (identifier_p (name))
            decl = cp_parser_lookup_name_simple (parser, name, token->location);
          else
            decl = name;
          if (decl == error_mark_node)
-           cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
-                                        token->location);
+           {
+             if (kind == OMP_CLAUSE_DEPEND
+                 && cp_parser_simulate_error (parser))
+               goto depend_lvalue;
+             cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
+                                          token->location);
+           }
        }
       if (decl == error_mark_node)
        ;
@@ -31681,6 +32449,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
              /* FALLTHROUGH.  */
            case OMP_CLAUSE_DEPEND:
            case OMP_CLAUSE_REDUCTION:
+           case OMP_CLAUSE_IN_REDUCTION:
+           case OMP_CLAUSE_TASK_REDUCTION:
              while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
                {
                  tree low_bound = NULL_TREE, length = NULL_TREE;
@@ -31698,7 +32468,14 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                    {
                      /* Look for `:'.  */
                      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
-                       goto skip_comma;
+                       {
+                         if (kind == OMP_CLAUSE_DEPEND
+                             && cp_parser_simulate_error (parser))
+                           goto depend_lvalue;
+                         goto skip_comma;
+                       }
+                     if (kind == OMP_CLAUSE_DEPEND)
+                       cp_parser_commit_to_tentative_parse (parser);
                      if (!cp_lexer_next_token_is (parser->lexer,
                                                   CPP_CLOSE_SQUARE))
                        length = cp_parser_expression (parser);
@@ -31706,7 +32483,12 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                  /* Look for the closing `]'.  */
                  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE,
                                          RT_CLOSE_SQUARE))
-                   goto skip_comma;
+                   {
+                     if (kind == OMP_CLAUSE_DEPEND
+                         && cp_parser_simulate_error (parser))
+                       goto depend_lvalue;
+                     goto skip_comma;
+                   }
 
                  decl = tree_cons (low_bound, length, decl);
                }
@@ -31715,6 +32497,21 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
              break;
            }
 
+         if (kind == OMP_CLAUSE_DEPEND)
+           {
+             if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
+                 && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+                 && cp_parser_simulate_error (parser))
+               {
+               depend_lvalue:
+                 cp_parser_abort_tentative_parse (parser);
+                 decl = cp_parser_assignment_expression (parser, NULL,
+                                                         false, false);
+               }
+             else
+               cp_parser_parse_definitely (parser);
+           }
+
          tree u = build_omp_clause (token->location, kind);
          OMP_CLAUSE_DECL (u) = decl;
          OMP_CLAUSE_CHAIN (u) = list;
@@ -31861,13 +32658,14 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list)
    seq */
 
 static tree
-cp_parser_oacc_simple_clause (cp_parser * /* parser  */,
-                             enum omp_clause_code code,
-                             tree list, location_t location)
+cp_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
+                             tree list)
 {
-  check_no_duplicate_clause (list, code, omp_clause_code_name[code], location);
-  tree c = build_omp_clause (location, code);
+  check_no_duplicate_clause (list, code, omp_clause_code_name[code], loc);
+
+  tree c = build_omp_clause (loc, code);
   OMP_CLAUSE_CHAIN (c) = list;
+
   return c;
 }
 
@@ -31923,13 +32721,13 @@ cp_parser_oacc_single_int_clause (cp_parser *parser, omp_clause_code code,
 */
 
 static tree
-cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind,
+cp_parser_oacc_shape_clause (cp_parser *parser, location_t loc,
+                            omp_clause_code kind,
                             const char *str, tree list)
 {
   const char *id = "num";
   cp_lexer *lexer = parser->lexer;
   tree ops[2] = { NULL_TREE, NULL_TREE }, c;
-  location_t loc = cp_lexer_peek_token (lexer)->location;
 
   if (kind == OMP_CLAUSE_VECTOR)
     id = "length";
@@ -32097,9 +32895,11 @@ cp_parser_oacc_wait_list (cp_parser *parser, location_t clause_loc, tree list)
 
   if (args == NULL || args->length () == 0)
     {
-      cp_parser_error (parser, "expected integer expression before ')'");
       if (args != NULL)
-       release_tree_vector (args);
+       {
+         cp_parser_error (parser, "expected integer expression list");
+         release_tree_vector (args);
+       }
       return list;
     }
 
@@ -32131,17 +32931,23 @@ cp_parser_oacc_wait_list (cp_parser *parser, location_t clause_loc, tree list)
 }
 
 /* OpenACC:
-   wait ( int-expr-list ) */
+   wait [( int-expr-list )] */
 
 static tree
 cp_parser_oacc_clause_wait (cp_parser *parser, tree list)
 {
   location_t location = cp_lexer_peek_token (parser->lexer)->location;
 
-  if (cp_lexer_peek_token (parser->lexer)->type != CPP_OPEN_PAREN)
-    return list;
+  if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
+    list = cp_parser_oacc_wait_list (parser, location, list);
+  else
+    {
+      tree c = build_omp_clause (location, OMP_CLAUSE_WAIT);
 
-  list = cp_parser_oacc_wait_list (parser, location, list);
+      OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
 
   return list;
 }
@@ -32274,7 +33080,7 @@ cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location)
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_condition (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -32299,7 +33105,11 @@ cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location)
 
    directive-name-modifier:
      parallel | task | taskloop | target data | target | target update
-     | target enter data | target exit data  */
+     | target enter data | target exit data
+
+   OpenMP 5.0:
+   directive-name-modifier:
+     ... | simd | cancel  */
 
 static tree
 cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
@@ -32318,8 +33128,12 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
       const char *p = IDENTIFIER_POINTER (id);
       int n = 2;
 
-      if (strcmp ("parallel", p) == 0)
+      if (strcmp ("cancel", p) == 0)
+       if_modifier = VOID_CST;
+      else if (strcmp ("parallel", p) == 0)
        if_modifier = OMP_PARALLEL;
+      else if (strcmp ("simd", p) == 0)
+       if_modifier = OMP_SIMD;
       else if (strcmp ("task", p) == 0)
        if_modifier = OMP_TASK;
       else if (strcmp ("taskloop", p) == 0)
@@ -32389,7 +33203,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
        }
     }
 
-  t = cp_parser_condition (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -32406,7 +33220,9 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
            const char *p = NULL;
            switch (if_modifier)
              {
+             case VOID_CST: p = "cancel"; break;
              case OMP_PARALLEL: p = "parallel"; break;
+             case OMP_SIMD: p = "simd"; break;
              case OMP_TASK: p = "task"; break;
              case OMP_TASKLOOP: p = "taskloop"; break;
              case OMP_TARGET_DATA: p = "target data"; break;
@@ -32491,7 +33307,7 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -32522,7 +33338,7 @@ cp_parser_omp_clause_num_tasks (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -32553,7 +33369,7 @@ cp_parser_omp_clause_grainsize (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -32584,7 +33400,7 @@ cp_parser_omp_clause_priority (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -32606,8 +33422,7 @@ cp_parser_omp_clause_priority (cp_parser *parser, tree list,
    hint ( expression ) */
 
 static tree
-cp_parser_omp_clause_hint (cp_parser *parser, tree list,
-                          location_t location)
+cp_parser_omp_clause_hint (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
@@ -32615,7 +33430,7 @@ cp_parser_omp_clause_hint (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -32633,7 +33448,10 @@ cp_parser_omp_clause_hint (cp_parser *parser, tree list,
 }
 
 /* OpenMP 4.5:
-   defaultmap ( tofrom : scalar ) */
+   defaultmap ( tofrom : scalar )
+
+   OpenMP 5.0:
+   defaultmap ( implicit-behavior [ : variable-category ] ) */
 
 static tree
 cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
@@ -32641,47 +33459,163 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
 {
   tree c, id;
   const char *p;
+  enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
+  enum omp_clause_defaultmap_kind category
+    = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
 
   matching_parens parens;
   if (!parens.require_open (parser))
     return list;
 
-  if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT))
+    p = "default";
+  else if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
-      cp_parser_error (parser, "expected %<tofrom%>");
+    invalid_behavior:
+      cp_parser_error (parser, "expected %<alloc%>, %<to%>, %<from%>, "
+                              "%<tofrom%>, %<firstprivate%>, %<none%> "
+                              "or %<default%>");
       goto out_err;
     }
-  id = cp_lexer_peek_token (parser->lexer)->u.value;
-  p = IDENTIFIER_POINTER (id);
-  if (strcmp (p, "tofrom") != 0)
+  else
     {
-      cp_parser_error (parser, "expected %<tofrom%>");
-      goto out_err;
+      id = cp_lexer_peek_token (parser->lexer)->u.value;
+      p = IDENTIFIER_POINTER (id);
     }
-  cp_lexer_consume_token (parser->lexer);
-  if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
-    goto out_err;
 
-  if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+  switch (p[0])
     {
-      cp_parser_error (parser, "expected %<scalar%>");
-      goto out_err;
+    case 'a':
+      if (strcmp ("alloc", p) == 0)
+       behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
+      else
+       goto invalid_behavior;
+      break;
+
+    case 'd':
+      if (strcmp ("default", p) == 0)
+       behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
+      else
+       goto invalid_behavior;
+      break;
+
+    case 'f':
+      if (strcmp ("firstprivate", p) == 0)
+       behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
+      else if (strcmp ("from", p) == 0)
+       behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
+      else
+       goto invalid_behavior;
+      break;
+
+    case 'n':
+      if (strcmp ("none", p) == 0)
+       behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
+      else
+       goto invalid_behavior;
+      break;
+
+    case 't':
+      if (strcmp ("tofrom", p) == 0)
+       behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
+      else if (strcmp ("to", p) == 0)
+       behavior = OMP_CLAUSE_DEFAULTMAP_TO;
+      else
+       goto invalid_behavior;
+      break;
+
+    default:
+      goto invalid_behavior;
     }
-  id = cp_lexer_peek_token (parser->lexer)->u.value;
-  p = IDENTIFIER_POINTER (id);
-  if (strcmp (p, "scalar") != 0)
+  cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
     {
-      cp_parser_error (parser, "expected %<scalar%>");
-      goto out_err;
+      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+       goto out_err;
+
+      if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+       {
+       invalid_category:
+         cp_parser_error (parser, "expected %<scalar%>, %<aggregate%> or "
+                                  "%<pointer%>");
+         goto out_err;
+       }
+      id = cp_lexer_peek_token (parser->lexer)->u.value;
+      p = IDENTIFIER_POINTER (id);
+
+      switch (p[0])
+       {
+       case 'a':
+         if (strcmp ("aggregate", p) == 0)
+           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
+         else
+           goto invalid_category;
+         break;
+
+       case 'p':
+         if (strcmp ("pointer", p) == 0)
+           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
+         else
+           goto invalid_category;
+         break;
+
+       case 's':
+         if (strcmp ("scalar", p) == 0)
+           category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
+         else
+           goto invalid_category;
+         break;
+
+       default:
+         goto invalid_category;
+       }
+
+      cp_lexer_consume_token (parser->lexer);
     }
-  cp_lexer_consume_token (parser->lexer);
   if (!parens.require_close (parser))
     goto out_err;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULTMAP, "defaultmap",
-                            location);
+  for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
+    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
+       && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
+           || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
+           || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
+               == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
+      {
+       enum omp_clause_defaultmap_kind cat = category;
+       location_t loc = OMP_CLAUSE_LOCATION (c);
+       if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
+         cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
+       p = NULL;
+       switch (cat)
+         {
+         case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
+           p = NULL;
+           break;
+         case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
+           p = "aggregate";
+           break;
+         case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
+           p = "pointer";
+           break;
+         case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
+           p = "scalar";
+           break;
+         default:
+           gcc_unreachable ();
+         }
+       if (p)
+         error_at (loc, "too many %<defaultmap%> clauses with %qs category",
+                   p);
+       else
+         error_at (loc, "too many %<defaultmap%> clauses with unspecified "
+                        "category");
+       break;
+      }
 
   c = build_omp_clause (location, OMP_CLAUSE_DEFAULTMAP);
+  OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -32756,17 +33690,54 @@ cp_parser_omp_clause_ordered (cp_parser *parser,
 
    reduction-operator:
      One of: + * - & ^ | && ||
-     id-expression  */
+     id-expression
+
+   OpenMP 5.0:
+   reduction ( reduction-modifier, reduction-operator : variable-list )
+   in_reduction ( reduction-operator : variable-list )
+   task_reduction ( reduction-operator : variable-list )  */
 
 static tree
-cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
+cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
+                               bool is_omp, tree list)
 {
   enum tree_code code = ERROR_MARK;
   tree nlist, c, id = NULL_TREE;
+  bool task = false;
+  bool inscan = false;
 
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
+  if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+    {
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT)
+         && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         cp_lexer_consume_token (parser->lexer);
+       }
+      else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+              && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
+       {
+         tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+         const char *p = IDENTIFIER_POINTER (id);
+         if (strcmp (p, "task") == 0)
+           task = true;
+         else if (strcmp (p, "inscan") == 0)
+           {
+             inscan = true;
+             sorry ("%<inscan%> modifier on %<reduction%> clause "
+                    "not supported yet");
+           }
+         if (task || inscan)
+           {
+             cp_lexer_consume_token (parser->lexer);
+             cp_lexer_consume_token (parser->lexer);
+           }
+       }
+    }
+
   switch (cp_lexer_peek_token (parser->lexer)->type)
     {
     case CPP_PLUS: code = PLUS_EXPR; break;
@@ -32839,11 +33810,15 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
   if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
     goto resync_fail;
 
-  nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list,
+  nlist = cp_parser_omp_var_list_no_open (parser, kind, list,
                                          NULL);
   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
     {
       OMP_CLAUSE_REDUCTION_CODE (c) = code;
+      if (task)
+       OMP_CLAUSE_REDUCTION_TASK (c) = 1;
+      else if (inscan)
+       OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
       OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = id;
     }
 
@@ -33077,7 +34052,7 @@ cp_parser_omp_clause_num_teams (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -33108,7 +34083,7 @@ cp_parser_omp_clause_thread_limit (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -33162,6 +34137,43 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
   return nlist;
 }
 
+/* OpenMP 2.5:
+   lastprivate ( variable-list )
+
+   OpenMP 5.0:
+   lastprivate ( [ lastprivate-modifier : ] variable-list )  */
+
+static tree
+cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list)
+{
+  bool conditional = false;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return list;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+      && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      if (strcmp ("conditional", p) == 0)
+       {
+         conditional = true;
+         cp_lexer_consume_token (parser->lexer);
+         cp_lexer_consume_token (parser->lexer);
+       }
+    }
+
+  tree nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LASTPRIVATE,
+                                              list, NULL);
+
+  if (conditional)
+    for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+      OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
+  return nlist;
+}
+
 /* OpenMP 4.0:
    linear ( variable-list )
    linear ( variable-list : expression )
@@ -33239,7 +34251,7 @@ cp_parser_omp_clause_linear (cp_parser *parser, tree list,
            step = NULL_TREE;
        }
       if (!step)
-       step = cp_parser_expression (parser);
+       step = cp_parser_assignment_expression (parser);
 
       if (!parens.require_close (parser))
        cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
@@ -33404,6 +34416,118 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc,
   return list;
 }
 
+/* OpenMP 5.0:
+   iterators ( iterators-definition )
+
+   iterators-definition:
+     iterator-specifier
+     iterator-specifier , iterators-definition
+
+   iterator-specifier:
+     identifier = range-specification
+     iterator-type identifier = range-specification
+
+   range-specification:
+     begin : end
+     begin : end : step  */
+
+static tree
+cp_parser_omp_iterators (cp_parser *parser)
+{
+  tree ret = NULL_TREE, *last = &ret;
+  cp_lexer_consume_token (parser->lexer);
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return error_mark_node;
+
+  bool saved_colon_corrects_to_scope_p
+    = parser->colon_corrects_to_scope_p;
+  bool saved_colon_doesnt_start_class_def_p
+    = parser->colon_doesnt_start_class_def_p;
+
+  do
+    {
+      tree iter_type;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+         && cp_lexer_nth_token_is (parser->lexer, 2, CPP_EQ))
+       iter_type = integer_type_node;
+      else
+       {
+         const char *saved_message
+           = parser->type_definition_forbidden_message;
+         parser->type_definition_forbidden_message
+           = G_("types may not be defined in iterator type");
+
+         iter_type = cp_parser_type_id (parser);
+
+         parser->type_definition_forbidden_message = saved_message;
+       }
+
+      location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+       {
+         cp_parser_error (parser, "expected identifier");
+         break;
+       }
+
+      tree id = cp_parser_identifier (parser);
+      if (id == error_mark_node)
+       break;
+
+      if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+       break;
+
+      parser->colon_corrects_to_scope_p = false;
+      parser->colon_doesnt_start_class_def_p = true;
+      tree begin = cp_parser_assignment_expression (parser);
+
+      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+       break;
+
+      tree end = cp_parser_assignment_expression (parser);
+
+      tree step = integer_one_node;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         step = cp_parser_assignment_expression (parser);
+       }
+
+      tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
+      DECL_ARTIFICIAL (iter_var) = 1;
+      DECL_CONTEXT (iter_var) = current_function_decl;
+      pushdecl (iter_var);
+
+      *last = make_tree_vec (6);
+      TREE_VEC_ELT (*last, 0) = iter_var;
+      TREE_VEC_ELT (*last, 1) = begin;
+      TREE_VEC_ELT (*last, 2) = end;
+      TREE_VEC_ELT (*last, 3) = step;
+      last = &TREE_CHAIN (*last);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         continue;
+       }
+      break;
+    }
+  while (1);
+
+  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+  parser->colon_doesnt_start_class_def_p
+    = saved_colon_doesnt_start_class_def_p;
+
+  if (!parens.require_close (parser))
+    cp_parser_skip_to_closing_parenthesis (parser,
+                                          /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  return ret ? ret : error_mark_node;
+}
+
 /* OpenMP 4.0:
    depend ( depend-kind : variable-list )
 
@@ -33413,41 +34537,73 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc,
    OpenMP 4.5:
    depend ( source )
 
-   depend ( sink : vec ) */
+   depend ( sink : vec )
+
+   OpenMP 5.0:
+   depend ( depend-modifier , depend-kind: variable-list )
+
+   depend-kind:
+     in | out | inout | mutexinoutset | depobj
+
+   depend-modifier:
+     iterator ( iterators-definition )  */
 
 static tree
 cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
 {
-  tree nlist, c;
-  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+  tree nlist, c, iterators = NULL_TREE;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
 
   matching_parens parens;
   if (!parens.require_open (parser))
     return list;
 
-  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+  do
     {
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+       goto invalid_kind;
+
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
 
+      if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
+       {
+         begin_scope (sk_omp, NULL);
+         iterators = cp_parser_omp_iterators (parser);
+         cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+         continue;
+       }
       if (strcmp ("in", p) == 0)
        kind = OMP_CLAUSE_DEPEND_IN;
       else if (strcmp ("inout", p) == 0)
        kind = OMP_CLAUSE_DEPEND_INOUT;
+      else if (strcmp ("mutexinoutset", p) == 0)
+       kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
       else if (strcmp ("out", p) == 0)
        kind = OMP_CLAUSE_DEPEND_OUT;
-      else if (strcmp ("source", p) == 0)
-       kind = OMP_CLAUSE_DEPEND_SOURCE;
+      else if (strcmp ("depobj", p) == 0)
+       kind = OMP_CLAUSE_DEPEND_DEPOBJ;
       else if (strcmp ("sink", p) == 0)
        kind = OMP_CLAUSE_DEPEND_SINK;
+      else if (strcmp ("source", p) == 0)
+       kind = OMP_CLAUSE_DEPEND_SOURCE;
       else
        goto invalid_kind;
+      break;
     }
-  else
-    goto invalid_kind;
+  while (1);
 
   cp_lexer_consume_token (parser->lexer);
 
+  if (iterators
+      && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+    {
+      poplevel (0, 1, 0);
+      error_at (loc, "%<iterator%> modifier incompatible with %qs",
+               kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+      iterators = NULL_TREE;
+    }
+
   if (kind == OMP_CLAUSE_DEPEND_SOURCE)
     {
       c = build_omp_clause (loc, OMP_CLAUSE_DEPEND);
@@ -33471,14 +34627,30 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
       nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND,
                                              list, NULL);
 
+      if (iterators)
+       {
+         tree block = poplevel (1, 1, 0);
+         if (iterators == error_mark_node)
+           iterators = NULL_TREE;
+         else
+           TREE_VEC_ELT (iterators, 5) = block;
+       }
+
       for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
-       OMP_CLAUSE_DEPEND_KIND (c) = kind;
+       {
+         OMP_CLAUSE_DEPEND_KIND (c) = kind;
+         if (iterators)
+           OMP_CLAUSE_DECL (c)
+             = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
+       }
     }
   return nlist;
 
  invalid_kind:
   cp_parser_error (parser, "invalid depend kind");
  resync_fail:
+  if (iterators)
+    poplevel (0, 1, 0);
   cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                         /*or_comma=*/false,
                                         /*consume_paren=*/true);
@@ -33589,7 +34761,7 @@ cp_parser_omp_clause_device (cp_parser *parser, tree list,
   if (!parens.require_open (parser))
     return list;
 
-  t = cp_parser_expression (parser);
+  t = cp_parser_assignment_expression (parser);
 
   if (t == error_mark_node
       || !parens.require_close (parser))
@@ -33776,8 +34948,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "async";
          break;
        case PRAGMA_OACC_CLAUSE_AUTO:
-         clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_AUTO,
-                                                clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_AUTO,
+                                                 clauses);
          c_name = "auto";
          break;
        case PRAGMA_OACC_CLAUSE_COLLAPSE:
@@ -33821,8 +34993,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "device_resident";
          break;
        case PRAGMA_OACC_CLAUSE_FINALIZE:
-         clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_FINALIZE,
-                                                 clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_FINALIZE,
+                                                 clauses);
          c_name = "finalize";
          break;
        case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
@@ -33832,7 +35004,7 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          break;
        case PRAGMA_OACC_CLAUSE_GANG:
          c_name = "gang";
-         clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_GANG,
+         clauses = cp_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_GANG,
                                                 c_name, clauses);
          break;
        case PRAGMA_OACC_CLAUSE_HOST:
@@ -33844,15 +35016,13 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "if";
          break;
        case PRAGMA_OACC_CLAUSE_IF_PRESENT:
-         clauses = cp_parser_oacc_simple_clause (parser,
-                                                 OMP_CLAUSE_IF_PRESENT,
-                                                 clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_IF_PRESENT,
+                                                 clauses);
          c_name = "if_present";
          break;
        case PRAGMA_OACC_CLAUSE_INDEPENDENT:
-         clauses = cp_parser_oacc_simple_clause (parser,
-                                                 OMP_CLAUSE_INDEPENDENT,
-                                                 clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_INDEPENDENT,
+                                                 clauses);
          c_name = "independent";
          break;
        case PRAGMA_OACC_CLAUSE_LINK:
@@ -33881,12 +35051,14 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "private";
          break;
        case PRAGMA_OACC_CLAUSE_REDUCTION:
-         clauses = cp_parser_omp_clause_reduction (parser, clauses);
+         clauses
+           = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                             false, clauses);
          c_name = "reduction";
          break;
        case PRAGMA_OACC_CLAUSE_SEQ:
-         clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_SEQ,
-                                                clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_SEQ,
+                                                 clauses);
          c_name = "seq";
          break;
        case PRAGMA_OACC_CLAUSE_TILE:
@@ -33900,7 +35072,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          break;
        case PRAGMA_OACC_CLAUSE_VECTOR:
          c_name = "vector";
-         clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_VECTOR,
+         clauses = cp_parser_oacc_shape_clause (parser, here,
+                                                OMP_CLAUSE_VECTOR,
                                                 c_name, clauses);
          break;
        case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
@@ -33915,7 +35088,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          break;
        case PRAGMA_OACC_CLAUSE_WORKER:
          c_name = "worker";
-         clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_WORKER,
+         clauses = cp_parser_oacc_shape_clause (parser, here,
+                                                OMP_CLAUSE_WORKER,
                                                 c_name, clauses);
          break;
        default:
@@ -33956,6 +35130,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
   bool first = true;
   cp_token *token = NULL;
 
+  /* Don't create location wrapper nodes within OpenMP clauses.  */
+  auto_suppress_location_wrappers sentinel;
+
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
       pragma_omp_clause c_kind;
@@ -34028,9 +35205,14 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                             true);
          c_name = "if";
          break;
+       case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
+         clauses
+           = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
+                                             true, clauses);
+         c_name = "in_reduction";
+         break;
        case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
-         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
-                                           clauses);
+         clauses = cp_parser_omp_clause_lastprivate (parser, clauses);
          c_name = "lastprivate";
          break;
        case PRAGMA_OMP_CLAUSE_MERGEABLE:
@@ -34068,7 +35250,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "private";
          break;
        case PRAGMA_OMP_CLAUSE_REDUCTION:
-         clauses = cp_parser_omp_clause_reduction (parser, clauses);
+         clauses
+           = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+                                             true, clauses);
          c_name = "reduction";
          break;
        case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -34081,6 +35265,13 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                            clauses);
          c_name = "shared";
          break;
+       case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
+         clauses
+           = cp_parser_omp_clause_reduction (parser,
+                                             OMP_CLAUSE_TASK_REDUCTION,
+                                             true, clauses);
+         c_name = "task_reduction";
+         break;
        case PRAGMA_OMP_CLAUSE_UNTIED:
          clauses = cp_parser_omp_clause_untied (parser, clauses,
                                                 token->location);
@@ -34091,6 +35282,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                                 clauses, token->location);
          c_name = "inbranch";
          break;
+       case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_NONTEMPORAL,
+                                           clauses);
+         c_name = "nontemporal";
+         break;
        case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
          clauses = cp_parser_omp_clause_branch (parser,
                                                 OMP_CLAUSE_NOTINBRANCH,
@@ -34353,62 +35549,154 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
 {
   tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
   tree rhs1 = NULL_TREE, orig_lhs;
-  enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+  location_t loc = pragma_tok->location;
+  enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
+  enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
   bool structured_block = false;
-  bool seq_cst = false;
-
-  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
-    {
-      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
-      const char *p = IDENTIFIER_POINTER (id);
-
-      if (!strcmp (p, "seq_cst"))
-       {
-         seq_cst = true;
-         cp_lexer_consume_token (parser->lexer);
-         if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
-             && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
-           cp_lexer_consume_token (parser->lexer);
-       }
-    }
-  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
-    {
-      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
-      const char *p = IDENTIFIER_POINTER (id);
+  bool first = true;
+  tree clauses = NULL_TREE;
 
-      if (!strcmp (p, "read"))
-       code = OMP_ATOMIC_READ;
-      else if (!strcmp (p, "write"))
-       code = NOP_EXPR;
-      else if (!strcmp (p, "update"))
-       code = OMP_ATOMIC;
-      else if (!strcmp (p, "capture"))
-       code = OMP_ATOMIC_CAPTURE_NEW;
-      else
-       p = NULL;
-      if (p)
-       cp_lexer_consume_token (parser->lexer);
-    }
-  if (!seq_cst)
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
-      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
-         && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+      if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
        cp_lexer_consume_token (parser->lexer);
 
+      first = false;
+
       if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
        {
          tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+         location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
          const char *p = IDENTIFIER_POINTER (id);
-
-         if (!strcmp (p, "seq_cst"))
+         enum tree_code new_code = ERROR_MARK;
+         enum omp_memory_order new_memory_order
+           = OMP_MEMORY_ORDER_UNSPECIFIED;
+
+         if (!strcmp (p, "read"))
+           new_code = OMP_ATOMIC_READ;
+         else if (!strcmp (p, "write"))
+           new_code = NOP_EXPR;
+         else if (!strcmp (p, "update"))
+           new_code = OMP_ATOMIC;
+         else if (!strcmp (p, "capture"))
+           new_code = OMP_ATOMIC_CAPTURE_NEW;
+         else if (!strcmp (p, "seq_cst"))
+           new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         else if (!strcmp (p, "acq_rel"))
+           new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+         else if (!strcmp (p, "release"))
+           new_memory_order = OMP_MEMORY_ORDER_RELEASE;
+         else if (!strcmp (p, "acquire"))
+           new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+         else if (!strcmp (p, "relaxed"))
+           new_memory_order = OMP_MEMORY_ORDER_RELAXED;
+         else if (!strcmp (p, "hint"))
+           {
+             cp_lexer_consume_token (parser->lexer);
+             clauses = cp_parser_omp_clause_hint (parser, clauses, cloc);
+             continue;
+           }
+         else
            {
-             seq_cst = true;
+             p = NULL;
+             error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+                             "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
+                             "%<release%>, %<relaxed%> or %<hint%> clause");
+           }
+         if (p)
+           {
+             if (new_code != ERROR_MARK)
+               {
+                 if (code != ERROR_MARK)
+                   error_at (cloc, "too many atomic clauses");
+                 else
+                   code = new_code;
+               }
+             else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+               {
+                 if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+                   error_at (cloc, "too many memory order clauses");
+                 else
+                   memory_order = new_memory_order;
+               }
              cp_lexer_consume_token (parser->lexer);
+             continue;
            }
        }
+      break;
     }
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
+  if (code == ERROR_MARK)
+    code = OMP_ATOMIC;
+  if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+    {
+      omp_requires_mask
+       = (enum omp_requires) (omp_requires_mask
+                              | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
+      switch ((enum omp_memory_order)
+             (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
+       {
+       case OMP_MEMORY_ORDER_UNSPECIFIED:
+       case OMP_MEMORY_ORDER_RELAXED:
+         memory_order = OMP_MEMORY_ORDER_RELAXED;
+         break;
+       case OMP_MEMORY_ORDER_SEQ_CST:
+         memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         break;
+       case OMP_MEMORY_ORDER_ACQ_REL:
+         switch (code)
+           {
+           case OMP_ATOMIC_READ:
+             memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+             break;
+           case NOP_EXPR: /* atomic write */
+           case OMP_ATOMIC:
+             memory_order = OMP_MEMORY_ORDER_RELEASE;
+             break;
+           default:
+             memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+             break;
+           }
+         break;
+       default:
+         gcc_unreachable ();
+       }
+    }
+  else
+    switch (code)
+      {
+      case OMP_ATOMIC_READ:
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_RELEASE)
+         {
+           error_at (loc, "%<#pragma omp atomic read%> incompatible with "
+                          "%<acq_rel%> or %<release%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      case NOP_EXPR: /* atomic write */
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+         {
+           error_at (loc, "%<#pragma omp atomic write%> incompatible with "
+                          "%<acq_rel%> or %<acquire%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      case OMP_ATOMIC:
+       if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+           || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+         {
+           error_at (loc, "%<#pragma omp atomic update%> incompatible with "
+                          "%<acq_rel%> or %<acquire%> clauses");
+           memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+         }
+       break;
+      default:
+       break;
+      }
+
   switch (code)
     {
     case OMP_ATOMIC_READ:
@@ -34708,7 +35996,9 @@ stmt_done:
       cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
     }
 done:
-  finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, seq_cst);
+  clauses = finish_omp_clauses (clauses, C_ORT_OMP);
+  finish_omp_atomic (pragma_tok->location, code, opcode, lhs, rhs, v, lhs1,
+                    rhs1, clauses, memory_order);
   if (!structured_block)
     cp_parser_consume_semicolon_at_end_of_statement (parser);
   return;
@@ -34770,6 +36060,10 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
       if (name == error_mark_node)
        name = NULL;
 
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+         && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
+       cp_lexer_consume_token (parser->lexer);
+
       clauses = cp_parser_omp_all_clauses (parser,
                                           OMP_CRITICAL_CLAUSE_MASK,
                                           "#pragma omp critical", pragma_tok);
@@ -34781,26 +36075,151 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
   return c_finish_omp_critical (input_location, stmt, name, clauses);
 }
 
+/* OpenMP 5.0:
+   # pragma omp depobj ( depobj ) depobj-clause new-line
+
+   depobj-clause:
+     depend (dependence-type : locator)
+     destroy
+     update (dependence-type)
+
+   dependence-type:
+     in
+     out
+     inout
+     mutexinout  */
+
+static void
+cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
+{
+  location_t loc = pragma_tok->location;
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    {
+      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+      return;
+    }
+
+  tree depobj = cp_parser_assignment_expression (parser);
+
+  if (!parens.require_close (parser))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  tree clause = NULL_TREE;
+  enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+  location_t c_loc = cp_lexer_peek_token (parser->lexer)->location;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      cp_lexer_consume_token (parser->lexer);
+      if (!strcmp ("depend", p))
+       {
+         clause = cp_parser_omp_clause_depend (parser, NULL_TREE, c_loc);
+         if (clause)
+           clause = finish_omp_clauses (clause, C_ORT_OMP);
+         if (!clause)
+           clause = error_mark_node;
+       }
+      else if (!strcmp ("destroy", p))
+       kind = OMP_CLAUSE_DEPEND_LAST;
+      else if (!strcmp ("update", p))
+       {
+         matching_parens c_parens;
+         if (c_parens.require_open (parser))
+           {
+             location_t c2_loc
+               = cp_lexer_peek_token (parser->lexer)->location;
+             if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+               {
+                 tree id2 = cp_lexer_peek_token (parser->lexer)->u.value;
+                 const char *p2 = IDENTIFIER_POINTER (id2);
+
+                 cp_lexer_consume_token (parser->lexer);
+                 if (!strcmp ("in", p2))
+                   kind = OMP_CLAUSE_DEPEND_IN;
+                 else if (!strcmp ("out", p2))
+                   kind = OMP_CLAUSE_DEPEND_OUT;
+                 else if (!strcmp ("inout", p2))
+                   kind = OMP_CLAUSE_DEPEND_INOUT;
+                 else if (!strcmp ("mutexinoutset", p2))
+                   kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+               }
+             if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+               {
+                 clause = error_mark_node;
+                 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
+                                   "%<mutexinoutset%>");
+               }
+             if (!c_parens.require_close (parser))
+               cp_parser_skip_to_closing_parenthesis (parser,
+                                                      /*recovering=*/true,
+                                                      /*or_comma=*/false,
+                                                      /*consume_paren=*/true);
+           }
+         else
+           clause = error_mark_node;
+       }
+    }
+  if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
+    {
+      clause = error_mark_node;
+      error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
+    }
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+
 /* OpenMP 2.5:
    # pragma omp flush flush-vars[opt] new-line
 
    flush-vars:
-     ( variable-list ) */
+     ( variable-list )
+
+   OpenMP 5.0:
+   # pragma omp flush memory-order-clause new-line  */
 
 static void
 cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
 {
+  enum memmodel mo = MEMMODEL_LAST;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+      if (!strcmp (p, "acq_rel"))
+       mo = MEMMODEL_ACQ_REL;
+      else if (!strcmp (p, "release"))
+       mo = MEMMODEL_RELEASE;
+      else if (!strcmp (p, "acquire"))
+       mo = MEMMODEL_ACQUIRE;
+      else
+       error_at (cp_lexer_peek_token (parser->lexer)->location,
+                 "expected %<acq_rel%>, %<release%> or %<acquire%>");
+      cp_lexer_consume_token (parser->lexer);
+    }
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
-    (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
+    {
+      if (mo != MEMMODEL_LAST)
+       error_at (cp_lexer_peek_token (parser->lexer)->location,
+                 "%<flush%> list specified together with memory order "
+                 "clause");
+      (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
+    }
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
-  finish_omp_flush ();
+  finish_omp_flush (mo);
 }
 
 /* Helper function, to parse omp for increment expression.  */
 
 static tree
-cp_parser_omp_for_cond (cp_parser *parser, tree decl)
+cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
 {
   tree cond = cp_parser_binary_expression (parser, false, true,
                                           PREC_NOT_OPERATOR, NULL);
@@ -34819,7 +36238,8 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
     case LE_EXPR:
       break;
     case NE_EXPR:
-      /* Fall through: OpenMP disallows NE_EXPR.  */
+      if (code != OACC_LOOP)
+       break;
       gcc_fallthrough ();
     default:
       return error_mark_node;
@@ -34969,7 +36389,8 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
      cp_parser_condition, from whence the bulk of this is copied.  */
 
   cp_parser_parse_tentatively (parser);
-  cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+  cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+                               /*is_declaration=*/true,
                                /*is_trailing_return=*/false,
                                &type_specifiers);
   if (cp_parser_parse_definitely (parser))
@@ -34981,10 +36402,12 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
 
       declarator = cp_parser_declarator (parser,
                                         CP_PARSER_DECLARATOR_NAMED,
+                                        CP_PARSER_FLAGS_NONE,
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         /*parenthesized_p=*/NULL,
                                         /*member_p=*/false,
-                                        /*friend_p=*/false);
+                                        /*friend_p=*/false,
+                                        /*static_p=*/false);
       attributes = cp_parser_attributes_opt (parser);
       asm_specification = cp_parser_asm_specification_opt (parser);
 
@@ -35163,6 +36586,192 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
   return add_private_clause;
 }
 
+/* Helper for cp_parser_omp_for_loop, handle one range-for loop.  */
+
+void
+cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block,
+                         tree &decl, tree &orig_decl, tree &init,
+                         tree &orig_init, tree &cond, tree &incr)
+{
+  tree begin, end, range_temp_decl = NULL_TREE;
+  tree iter_type, begin_expr, end_expr;
+
+  if (processing_template_decl)
+    {
+      if (check_for_bare_parameter_packs (init))
+       init = error_mark_node;
+      if (!type_dependent_expression_p (init)
+         /* do_auto_deduction doesn't mess with template init-lists.  */
+         && !BRACE_ENCLOSED_INITIALIZER_P (init))
+       {
+         tree d = decl;
+         if (decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (decl))
+           {
+             tree v = DECL_VALUE_EXPR (decl);
+             if (TREE_CODE (v) == ARRAY_REF
+                 && VAR_P (TREE_OPERAND (v, 0))
+                 && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+               d = TREE_OPERAND (v, 0);
+           }
+         do_range_for_auto_deduction (d, init);
+       }
+      cond = global_namespace;
+      incr = NULL_TREE;
+      orig_init = init;
+      if (this_pre_body)
+       this_pre_body = pop_stmt_list (this_pre_body);
+      return;
+    }
+
+  init = mark_lvalue_use (init);
+
+  if (decl == error_mark_node || init == error_mark_node)
+    /* If an error happened previously do nothing or else a lot of
+       unhelpful errors would be issued.  */
+    begin_expr = end_expr = iter_type = error_mark_node;
+  else
+    {
+      tree range_temp;
+
+      if (VAR_P (init)
+         && array_of_runtime_bound_p (TREE_TYPE (init)))
+       /* Can't bind a reference to an array of runtime bound.  */
+       range_temp = init;
+      else
+       {
+         range_temp = build_range_temp (init);
+         DECL_NAME (range_temp) = NULL_TREE;
+         pushdecl (range_temp);
+         cp_finish_decl (range_temp, init,
+                         /*is_constant_init*/false, NULL_TREE,
+                         LOOKUP_ONLYCONVERTING);
+         range_temp_decl = range_temp;
+         range_temp = convert_from_reference (range_temp);
+       }
+      iter_type = cp_parser_perform_range_for_lookup (range_temp,
+                                                     &begin_expr, &end_expr);
+    }
+
+  tree end_iter_type = iter_type;
+  if (cxx_dialect >= cxx17)
+    end_iter_type = cv_unqualified (TREE_TYPE (end_expr));
+  end = build_decl (input_location, VAR_DECL, NULL_TREE, end_iter_type);
+  TREE_USED (end) = 1;
+  DECL_ARTIFICIAL (end) = 1;
+  pushdecl (end);
+  cp_finish_decl (end, end_expr,
+                 /*is_constant_init*/false, NULL_TREE,
+                 LOOKUP_ONLYCONVERTING);
+
+  /* The new for initialization statement.  */
+  begin = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type);
+  TREE_USED (begin) = 1;
+  DECL_ARTIFICIAL (begin) = 1;
+  pushdecl (begin);
+  orig_init = init;
+  if (CLASS_TYPE_P (iter_type))
+    init = NULL_TREE;
+  else
+    {
+      init = begin_expr;
+      begin_expr = NULL_TREE;
+    }
+  cp_finish_decl (begin, begin_expr,
+                 /*is_constant_init*/false, NULL_TREE,
+                 LOOKUP_ONLYCONVERTING);
+
+  /* The new for condition.  */
+  if (CLASS_TYPE_P (iter_type))
+    cond = build2 (NE_EXPR, boolean_type_node, begin, end);
+  else
+    cond = build_x_binary_op (input_location, NE_EXPR,
+                             begin, ERROR_MARK,
+                             end, ERROR_MARK,
+                             NULL, tf_warning_or_error);
+
+  /* The new increment expression.  */
+  if (CLASS_TYPE_P (iter_type))
+    incr = build2 (PREINCREMENT_EXPR, iter_type, begin, NULL_TREE);
+  else
+    incr = finish_unary_op_expr (input_location,
+                                PREINCREMENT_EXPR, begin,
+                                tf_warning_or_error);
+
+  orig_decl = decl;
+  decl = begin;
+  if (for_block)
+    {
+      vec_safe_push (for_block, this_pre_body);
+      this_pre_body = NULL_TREE;
+    }
+
+  tree decomp_first_name = NULL_TREE;
+  unsigned decomp_cnt = 0;
+  if (orig_decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (orig_decl))
+    {
+      tree v = DECL_VALUE_EXPR (orig_decl);
+      if (TREE_CODE (v) == ARRAY_REF
+         && VAR_P (TREE_OPERAND (v, 0))
+         && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+       {
+         tree d = orig_decl;
+         orig_decl = TREE_OPERAND (v, 0);
+         decomp_cnt = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
+         decomp_first_name = d;
+       }
+    }
+
+  tree auto_node = type_uses_auto (TREE_TYPE (orig_decl));
+  if (auto_node)
+    {
+      tree t = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
+                                    tf_none);
+      if (!error_operand_p (t))
+       TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl),
+                                                  t, auto_node);
+    }
+
+  tree v = make_tree_vec (decomp_cnt + 3);
+  TREE_VEC_ELT (v, 0) = range_temp_decl;
+  TREE_VEC_ELT (v, 1) = end;
+  TREE_VEC_ELT (v, 2) = orig_decl;
+  for (unsigned i = 0; i < decomp_cnt; i++)
+    {
+      TREE_VEC_ELT (v, i + 3) = decomp_first_name;
+      decomp_first_name = DECL_CHAIN (decomp_first_name);
+    }
+  orig_decl = tree_cons (NULL_TREE, NULL_TREE, v);
+}
+
+/* Helper for cp_parser_omp_for_loop, finalize part of range for
+   inside of the collapsed body.  */
+
+void
+cp_finish_omp_range_for (tree orig, tree begin)
+{
+  gcc_assert (TREE_CODE (orig) == TREE_LIST
+             && TREE_CODE (TREE_CHAIN (orig)) == TREE_VEC);
+  tree decl = TREE_VEC_ELT (TREE_CHAIN (orig), 2);
+  tree decomp_first_name = NULL_TREE;
+  unsigned int decomp_cnt = 0;
+
+  if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+    {
+      decomp_first_name = TREE_VEC_ELT (TREE_CHAIN (orig), 3);
+      decomp_cnt = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3;
+      cp_maybe_mangle_decomp (decl, decomp_first_name, decomp_cnt);
+    }
+
+  /* The declaration is initialized with *__begin inside the loop body.  */
+  cp_finish_decl (decl,
+                 build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
+                                       tf_warning_or_error),
+                 /*is_constant_init*/false, NULL_TREE,
+                 LOOKUP_ONLYCONVERTING);
+  if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+    cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
+}
+
 /* Parse the restricted form of the for statement allowed by OpenMP.  */
 
 static tree
@@ -35170,7 +36779,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
                        tree *cclauses, bool *if_p)
 {
   tree init, orig_init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
-  tree real_decl, initv, condv, incrv, declv;
+  tree orig_decl;
+  tree real_decl, initv, condv, incrv, declv, orig_declv;
   tree this_pre_body, cl, ordered_cl = NULL_TREE;
   location_t loc_first;
   bool collapse_err = false;
@@ -35223,6 +36833,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
   initv = make_tree_vec (count);
   condv = make_tree_vec (count);
   incrv = make_tree_vec (count);
+  orig_declv = NULL_TREE;
 
   loc_first = cp_lexer_peek_token (parser->lexer)->location;
 
@@ -35240,13 +36851,79 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
        }
       loc = cp_lexer_consume_token (parser->lexer)->location;
 
+      /* Don't create location wrapper nodes within an OpenMP "for"
+        statement.  */
+      auto_suppress_location_wrappers sentinel;
+
       matching_parens parens;
       if (!parens.require_open (parser))
        return NULL;
 
-      init = orig_init = decl = real_decl = NULL;
+      init = orig_init = decl = real_decl = orig_decl = NULL_TREE;
       this_pre_body = push_stmt_list ();
 
+      if (code != OACC_LOOP && cxx_dialect >= cxx11)
+       {
+         /* Save tokens so that we can put them back.  */
+         cp_lexer_save_tokens (parser->lexer);
+
+         /* Look for ':' that is not nested in () or {}.  */
+         bool is_range_for
+           = (cp_parser_skip_to_closing_parenthesis_1 (parser,
+                                                       /*recovering=*/false,
+                                                       CPP_COLON,
+                                                       /*consume_paren=*/
+                                                       false) == -1);
+
+         /* Roll back the tokens we skipped.  */
+         cp_lexer_rollback_tokens (parser->lexer);
+
+         if (is_range_for)
+           {
+             bool saved_colon_corrects_to_scope_p
+               = parser->colon_corrects_to_scope_p;
+
+             /* A colon is used in range-based for.  */
+             parser->colon_corrects_to_scope_p = false;
+
+             /* Parse the declaration.  */
+             cp_parser_simple_declaration (parser,
+                                           /*function_definition_allowed_p=*/
+                                           false, &decl);
+             parser->colon_corrects_to_scope_p
+               = saved_colon_corrects_to_scope_p;
+
+             cp_parser_require (parser, CPP_COLON, RT_COLON);
+
+             init = cp_parser_range_for (parser, NULL_TREE, NULL_TREE, decl,
+                                         false, 0, true);
+
+             cp_convert_omp_range_for (this_pre_body, for_block, decl,
+                                       orig_decl, init, orig_init,
+                                       cond, incr);
+             if (this_pre_body)
+               {
+                 if (pre_body)
+                   {
+                     tree t = pre_body;
+                     pre_body = push_stmt_list ();
+                     add_stmt (t);
+                     add_stmt (this_pre_body);
+                     pre_body = pop_stmt_list (pre_body);
+                   }
+                 else
+                   pre_body = this_pre_body;
+               }
+
+             if (ordered_cl)
+               error_at (OMP_CLAUSE_LOCATION (ordered_cl),
+                         "%<ordered%> clause with parameter on "
+                         "range-based %<for%> loop");
+
+             goto parse_close_paren;
+           }
+       }
+
       add_private_clause
        = cp_parser_omp_for_loop_init (parser, this_pre_body, for_block,
                                       init, orig_init, decl, real_decl);
@@ -35323,7 +37000,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
                error_at (loc, "iteration variable %qD "
                          "should not be firstprivate",
                          decl);
-             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+             else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
                       && OMP_CLAUSE_DECL (c) == decl)
                error_at (loc, "iteration variable %qD should not be reduction",
                          decl);
@@ -35352,7 +37030,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
 
       cond = NULL;
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-       cond = cp_parser_omp_for_cond (parser, decl);
+       cond = cp_parser_omp_for_cond (parser, decl, code);
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
       incr = NULL;
@@ -35372,6 +37050,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
            protected_set_expr_location (incr, input_location);
        }
 
+    parse_close_paren:
       if (!parens.require_close (parser))
        cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                               /*or_comma=*/false,
@@ -35386,6 +37065,14 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
          orig_inits.safe_grow_cleared (i + 1);
          orig_inits[i] = orig_init;
        }
+      if (orig_decl)
+       {
+         if (!orig_declv)
+           orig_declv = copy_node (declv);
+         TREE_VEC_ELT (orig_declv, i) = orig_decl;
+       }
+      else if (orig_declv)
+       TREE_VEC_ELT (orig_declv, i) = decl;
 
       if (i == count - 1)
        break;
@@ -35434,15 +37121,27 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
 
   /* Note that the grammar doesn't call for a structured block here,
      though the loop as a whole is a structured block.  */
-  body = push_stmt_list ();
+  if (orig_declv)
+    {
+      body = begin_omp_structured_block ();
+      for (i = 0; i < count; i++)
+       if (TREE_VEC_ELT (orig_declv, i) != TREE_VEC_ELT (declv, i))
+         cp_finish_omp_range_for (TREE_VEC_ELT (orig_declv, i),
+                                  TREE_VEC_ELT (declv, i));
+    }
+  else
+    body = push_stmt_list ();
   cp_parser_statement (parser, NULL_TREE, false, if_p);
-  body = pop_stmt_list (body);
+  if (orig_declv)
+    body = finish_omp_structured_block (body);
+  else
+    body = pop_stmt_list (body);
 
   if (declv == NULL_TREE)
     ret = NULL_TREE;
   else
-    ret = finish_omp_for (loc_first, code, declv, NULL, initv, condv, incrv,
-                         body, pre_body, &orig_inits, clauses);
+    ret = finish_omp_for (loc_first, code, declv, orig_declv, initv, condv,
+                         incrv, body, pre_body, &orig_inits, clauses);
 
   while (nbraces)
     {
@@ -35506,7 +37205,9 @@ cp_omp_split_clauses (location_t loc, enum tree_code code,
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE)      \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE)  \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL))
 
 static tree
 cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
@@ -35537,13 +37238,14 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
        }
     }
 
+  keep_next_level (true);
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
   ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses, if_p);
 
   cp_parser_end_omp_structured_block (parser, save);
-  add_stmt (finish_omp_structured_block (sb));
+  add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
 
   return ret;
 }
@@ -35636,26 +37338,78 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
       clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
     }
 
+  keep_next_level (true);
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
   ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses, if_p);
 
   cp_parser_end_omp_structured_block (parser, save);
-  add_stmt (finish_omp_structured_block (sb));
+  add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
 
   return ret;
 }
 
+static tree cp_parser_omp_taskloop (cp_parser *, cp_token *, char *,
+                                   omp_clause_mask, tree *, bool *);
+
 /* OpenMP 2.5:
    # pragma omp master new-line
      structured-block  */
 
 static tree
-cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
+cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok,
+                     char *p_name, omp_clause_mask mask, tree *cclauses,
+                     bool *if_p)
 {
-  cp_parser_require_pragma_eol (parser, pragma_tok);
-  return c_finish_omp_master (input_location,
+  tree clauses, sb, ret;
+  unsigned int save;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  strcat (p_name, " master");
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      if (strcmp (p, "taskloop") == 0)
+       {
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         if (cclauses == NULL)
+           cclauses = cclauses_buf;
+
+         cp_lexer_consume_token (parser->lexer);
+         if (!flag_openmp)  /* flag_openmp_simd  */
+           return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask,
+                                          cclauses, if_p);
+         sb = begin_omp_structured_block ();
+         save = cp_parser_begin_omp_structured_block (parser);
+         ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask,
+                                       cclauses, if_p);
+         cp_parser_end_omp_structured_block (parser, save);
+         tree body = finish_omp_structured_block (sb);
+         if (ret == NULL)
+           return ret;
+         return c_finish_omp_master (loc, body);
+       }
+    }
+  if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+      return NULL_TREE;
+    }
+
+  if (cclauses)
+    {
+      clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+                                          false);
+      cp_omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses);
+    }
+  else
+    cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  return c_finish_omp_master (loc,
                              cp_parser_omp_structured_block (parser, if_p));
 }
 
@@ -35897,16 +37651,34 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
       cp_parser_skip_to_pragma_eol (parser, pragma_tok);
       return NULL_TREE;
     }
-  else if (!flag_openmp)  /* flag_openmp_simd  */
-    {
-      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
-      return NULL_TREE;
-    }
   else if (cclauses == NULL && cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
-      if (strcmp (p, "sections") == 0)
+      if (strcmp (p, "master") == 0)
+       {
+         tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+         cclauses = cclauses_buf;
+
+         cp_lexer_consume_token (parser->lexer);
+         block = begin_omp_parallel ();
+         save = cp_parser_begin_omp_structured_block (parser);
+         tree ret = cp_parser_omp_master (parser, pragma_tok, p_name, mask,
+                                          cclauses, if_p);
+         cp_parser_end_omp_structured_block (parser, save);
+         stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+                                     block);
+         OMP_PARALLEL_COMBINED (stmt) = 1;
+         if (ret == NULL_TREE)
+           return ret;
+         return stmt;
+       }
+      else if (!flag_openmp)  /* flag_openmp_simd  */
+       {
+         cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+         return NULL_TREE;
+       }
+      else if (strcmp (p, "sections") == 0)
        {
          tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
          cclauses = cclauses_buf;
@@ -35922,6 +37694,11 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
          return stmt;
        }
     }
+  else if (!flag_openmp)  /* flag_openmp_simd  */
+    {
+      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+      return NULL_TREE;
+    }
 
   clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
                                       cclauses == NULL);
@@ -35954,6 +37731,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
 {
   tree stmt = make_node (OMP_SINGLE);
   TREE_TYPE (stmt) = void_type_node;
+  SET_EXPR_LOCATION (stmt, pragma_tok->location);
 
   OMP_SINGLE_CLAUSES (stmt)
     = cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
@@ -35977,7 +37755,8 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL)        \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE)    \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
 
 static tree
 cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
@@ -35995,13 +37774,32 @@ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
 }
 
 /* OpenMP 3.0:
-   # pragma omp taskwait new-line  */
+   # pragma omp taskwait new-line
+
+   OpenMP 5.0:
+   # pragma omp taskwait taskwait-clause[opt] new-line  */
+
+#define OMP_TASKWAIT_CLAUSE_MASK                               \
+       (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
 
 static void
 cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
 {
-  cp_parser_require_pragma_eol (parser, pragma_tok);
-  finish_omp_taskwait ();
+  tree clauses
+    = cp_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
+                                "#pragma omp taskwait", pragma_tok);
+
+  if (clauses)
+    {
+      tree stmt = make_node (OMP_TASK);
+      TREE_TYPE (stmt) = void_node;
+      OMP_TASK_CLAUSES (stmt) = clauses;
+      OMP_TASK_BODY (stmt) = NULL_TREE;
+      SET_EXPR_LOCATION (stmt, pragma_tok->location);
+      add_stmt (stmt);
+    }
+  else
+    finish_omp_taskwait ();
 }
 
 /* OpenMP 3.1:
@@ -36016,15 +37814,24 @@ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
 
 /* OpenMP 4.0:
    # pragma omp taskgroup new-line
-     structured-block  */
+     structured-block
+
+   OpenMP 5.0:
+   # pragma omp taskgroup taskgroup-clause[optseq] new-line  */
+
+#define OMP_TASKGROUP_CLAUSE_MASK                              \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
 
 static tree
 cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
 {
-  cp_parser_require_pragma_eol (parser, pragma_tok);
+  tree clauses
+    = cp_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
+                                "#pragma omp taskgroup", pragma_tok);
   return c_finish_omp_taskgroup (input_location,
                                 cp_parser_omp_structured_block (parser,
-                                                                if_p));
+                                                                if_p),
+                                clauses);
 }
 
 
@@ -36197,13 +38004,14 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
       clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
     }
 
+  keep_next_level (true);
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
   ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL, if_p);
 
   cp_parser_end_omp_structured_block (parser, save);
-  add_stmt (finish_omp_structured_block (sb));
+  add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
 
   return ret;
 }
@@ -36247,6 +38055,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
          if (!flag_openmp)  /* flag_openmp_simd  */
            return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
                                             cclauses, if_p);
+         keep_next_level (true);
          sb = begin_omp_structured_block ();
          save = cp_parser_begin_omp_structured_block (parser);
          ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
@@ -36282,6 +38091,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
   tree stmt = make_node (OMP_TEAMS);
   TREE_TYPE (stmt) = void_type_node;
   OMP_TEAMS_CLAUSES (stmt) = clauses;
+  keep_next_level (true);
   OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
   SET_EXPR_LOCATION (stmt, loc);
 
@@ -36332,6 +38142,8 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
            *pc = OMP_CLAUSE_CHAIN (*pc);
            continue;
          }
+      else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR)
+       map_seen = 3;
       pc = &OMP_CLAUSE_CHAIN (*pc);
     }
 
@@ -36340,7 +38152,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
       if (map_seen == 0)
        error_at (pragma_tok->location,
                  "%<#pragma omp target data%> must contain at least "
-                 "one %<map%> clause");
+                 "one %<map%> or %<use_device_ptr%> clause");
       return NULL_TREE;
     }
 
@@ -36598,6 +38410,10 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
 {
   tree *pc = NULL, stmt;
 
+  if (flag_openmp)
+    omp_requires_mask
+      = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -37067,7 +38883,7 @@ cp_parser_oacc_enter_exit_data (cp_parser *parser, cp_token *pragma_tok,
   stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
   TREE_TYPE (stmt) = void_type_node;
   OMP_STANDALONE_CLAUSES (stmt) = clauses;
-  SET_EXPR_LOCATION (stmt, pragma_tok->location);
+  SET_EXPR_LOCATION (stmt, loc);
   add_stmt (stmt);
   return stmt;
 }
@@ -37191,8 +39007,9 @@ cp_parser_oacc_kernels_parallel (cp_parser *parser, cp_token *pragma_tok,
          cp_lexer_consume_token (parser->lexer);
          tree block = begin_omp_parallel ();
          tree clauses;
-         cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, &clauses,
-                              if_p);
+         tree stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask,
+                                          &clauses, if_p);
+         protected_set_expr_location (stmt, pragma_tok->location);
          return finish_omp_construct (code, block, clauses);
        }
     }
@@ -37609,6 +39426,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
       else
        {
          cp_parser_parse_tentatively (parser);
+         /* Don't create location wrapper nodes here.  */
+         auto_suppress_location_wrappers sentinel;
          tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false,
                                                  /*check_dependency_p=*/true,
                                                  /*template_p=*/NULL,
@@ -37951,6 +39770,150 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
   return false;
 }
 
+/* OpenMP 5.0
+   #pragma omp requires clauses[optseq] new-line  */
+
+static bool
+cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok)
+{
+  bool first = true;
+  enum omp_requires new_req = (enum omp_requires) 0;
+
+  location_t loc = pragma_tok->location;
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+    {
+      if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+
+      first = false;
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+       {
+         tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+         const char *p = IDENTIFIER_POINTER (id);
+         location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
+         enum omp_requires this_req = (enum omp_requires) 0;
+
+         if (!strcmp (p, "unified_address"))
+           this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
+         else if (!strcmp (p, "unified_shared_memory"))
+           this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
+         else if (!strcmp (p, "dynamic_allocators"))
+           this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
+         else if (!strcmp (p, "reverse_offload"))
+           this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
+         else if (!strcmp (p, "atomic_default_mem_order"))
+           {
+             cp_lexer_consume_token (parser->lexer);
+
+             matching_parens parens;
+             if (parens.require_open (parser))
+               {
+                 if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+                   {
+                     id = cp_lexer_peek_token (parser->lexer)->u.value;
+                     p = IDENTIFIER_POINTER (id);
+
+                     if (!strcmp (p, "seq_cst"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
+                     else if (!strcmp (p, "relaxed"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
+                     else if (!strcmp (p, "acq_rel"))
+                       this_req
+                         = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
+                   }
+                 if (this_req == 0)
+                   {
+                     error_at (cp_lexer_peek_token (parser->lexer)->location,
+                               "expected %<seq_cst%>, %<relaxed%> or "
+                               "%<acq_rel%>");
+                     if (cp_lexer_nth_token_is (parser->lexer, 2,
+                                                CPP_CLOSE_PAREN))
+                       cp_lexer_consume_token (parser->lexer);
+                   }
+                 else
+                   cp_lexer_consume_token (parser->lexer);
+
+                 if (!parens.require_close (parser))
+                   cp_parser_skip_to_closing_parenthesis (parser,
+                                                          /*recovering=*/true,
+                                                          /*or_comma=*/false,
+                                                          /*consume_paren=*/
+                                                          true);
+
+                 if (this_req == 0)
+                   {
+                     cp_parser_require_pragma_eol (parser, pragma_tok);
+                     return false;
+                   }
+               }
+             p = NULL;
+           }
+         else
+           {
+             error_at (cloc, "expected %<unified_address%>, "
+                             "%<unified_shared_memory%>, "
+                             "%<dynamic_allocators%>, "
+                              "%<reverse_offload%> "
+                              "or %<atomic_default_mem_order%> clause");
+             cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+             return false;
+           }
+         if (p)
+           sorry_at (cloc, "%qs clause on %<requires%> directive not "
+                           "supported yet", p);
+         if (p)
+           cp_lexer_consume_token (parser->lexer);
+         if (this_req)
+           {
+             if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 if ((this_req & new_req) != 0)
+                   error_at (cloc, "too many %qs clauses", p);
+                 if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
+                     && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
+                   error_at (cloc, "%qs clause used lexically after first "
+                                   "target construct or offloading API", p);
+               }
+             else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 error_at (cloc, "too many %qs clauses",
+                           "atomic_default_mem_order");
+                 this_req = (enum omp_requires) 0;
+               }
+             else if ((omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+               {
+                 error_at (cloc, "more than one %<atomic_default_mem_order%>"
+                                 " clause in a single compilation unit");
+                 this_req
+                   = (enum omp_requires)
+                      (omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
+               }
+             else if ((omp_requires_mask
+                       & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
+               error_at (cloc, "%<atomic_default_mem_order%> clause used "
+                               "lexically after first %<atomic%> construct "
+                               "without memory order clause");
+             new_req = (enum omp_requires) (new_req | this_req);
+             omp_requires_mask
+               = (enum omp_requires) (omp_requires_mask | this_req);
+             continue;
+           }
+       }
+      break;
+    }
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  if (new_req == 0)
+    error_at (loc, "%<pragma omp requires%> requires at least one clause");
+  return false;
+}
+
+
 /* OpenMP 4.5:
    #pragma omp taskloop taskloop-clause[optseq] new-line
      for-loop
@@ -37972,7 +39935,9 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL)        \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE)    \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)      \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
 
 static tree
 cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
@@ -37985,6 +39950,10 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
 
   strcat (p_name, " taskloop");
   mask |= OMP_TASKLOOP_CLAUSE_MASK;
+  /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
+     clause.  */
+  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
+    mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
@@ -38032,6 +40001,7 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
       clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
     }
 
+  keep_next_level (true);
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
@@ -38039,7 +40009,7 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
                                if_p);
 
   cp_parser_end_omp_structured_block (parser, save);
-  add_stmt (finish_omp_structured_block (sb));
+  add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
 
   return ret;
 }
@@ -38346,7 +40316,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
                                if_p);
       break;
     case PRAGMA_OMP_MASTER:
-      stmt = cp_parser_omp_master (parser, pragma_tok, if_p);
+      strcpy (p_name, "#pragma omp");
+      stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL,
+                                  if_p);
       break;
     case PRAGMA_OMP_PARALLEL:
       strcpy (p_name, "#pragma omp");
@@ -38806,6 +40778,21 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
        }
       break;
 
+    case PRAGMA_OMP_DEPOBJ:
+      switch (context)
+       {
+       case pragma_compound:
+         cp_parser_omp_depobj (parser, pragma_tok);
+         return false;
+       case pragma_stmt:
+         error_at (pragma_tok->location, "%<#pragma %s%> may only be "
+                   "used in compound statements", "omp depobj");
+         break;
+       default:
+         goto bad_stmt;
+       }
+      break;
+
     case PRAGMA_OMP_FLUSH:
       switch (context)
        {
@@ -38973,6 +40960,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
       pop_omp_privatization_clauses (stmt);
       return true;
 
+    case PRAGMA_OMP_REQUIRES:
+      return cp_parser_omp_requires (parser, pragma_tok);
+
     case PRAGMA_OMP_ORDERED:
       if (context != pragma_stmt && context != pragma_compound)
        goto bad_stmt;
@@ -39124,6 +41114,8 @@ c_parse_file (void)
                                ? dk_no_deferred : dk_no_check);
   cp_parser_translation_unit (the_parser);
   the_parser = NULL;
+
+  finish_translation_unit ();
 }
 
 /* Create an identifier for a generic parameter type (a synthesized