Change C++ to C comments.
[gcc.git] / gcc / cp / parser.c
index 8244366e669a4cab856b98d72b64fb5762ddaa9a..165039ef07c00768a2fc4ac3f05b1ea42ceaaa0c 100644 (file)
@@ -247,6 +247,10 @@ static void cp_lexer_stop_debugging
 
 static cp_token_cache *cp_token_cache_new
   (cp_token *, cp_token *);
+static tree cp_parser_late_noexcept_specifier
+  (cp_parser *, tree);
+static void noexcept_override_late_checks
+  (tree, tree);
 
 static void cp_parser_initial_pragma
   (cp_token *);
@@ -570,8 +574,10 @@ cp_debug_parser (FILE *file, cp_parser *parser)
   cp_debug_print_flag (file, "Colon doesn't start a class definition",
                              parser->colon_doesnt_start_class_def_p);
   if (parser->type_definition_forbidden_message)
-    fprintf (file, "Error message for forbidden type definitions: %s\n",
-            parser->type_definition_forbidden_message);
+    fprintf (file, "Error message for forbidden type definitions: %s %s\n",
+            parser->type_definition_forbidden_message,
+            parser->type_definition_forbidden_message_arg
+            ? parser->type_definition_forbidden_message_arg : "<none>");
   cp_debug_print_unparsed_queues (file, parser->unparsed_queues);
   fprintf (file, "Number of class definitions in progress: %u\n",
           parser->num_classes_being_defined);
@@ -765,6 +771,16 @@ cp_lexer_previous_token (cp_lexer *lexer)
   return cp_lexer_token_at (lexer, tp);
 }
 
+/* Overload for make_location, taking the lexer to mean the location of the
+   previous token.  */
+
+static inline location_t
+make_location (location_t caret, location_t start, cp_lexer *lexer)
+{
+  cp_token *t = cp_lexer_previous_token (lexer);
+  return make_location (caret, start, t->location);
+}
+
 /* nonzero if we are presently saving tokens.  */
 
 static inline int
@@ -816,14 +832,28 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
             {
               /* Warn about the C++0x keyword (but still treat it as
                  an identifier).  */
-              warning (OPT_Wc__11_compat, 
-                       "identifier %qE is a keyword in C++11",
-                       token->u.value);
+             warning_at (token->location, OPT_Wc__11_compat,
+                         "identifier %qE is a keyword in C++11",
+                         token->u.value);
 
               /* Clear out the C_RID_CODE so we don't warn about this
                  particular identifier-turned-keyword again.  */
               C_SET_RID_CODE (token->u.value, RID_MAX);
             }
+         if (warn_cxx20_compat
+             && C_RID_CODE (token->u.value) >= RID_FIRST_CXX20
+             && C_RID_CODE (token->u.value) <= RID_LAST_CXX20)
+           {
+             /* Warn about the C++20 keyword (but still treat it as
+                an identifier).  */
+             warning_at (token->location, OPT_Wc__20_compat,
+                         "identifier %qE is a keyword in C++20",
+                         token->u.value);
+
+             /* Clear out the C_RID_CODE so we don't warn about this
+                particular identifier-turned-keyword again.  */
+             C_SET_RID_CODE (token->u.value, RID_MAX);
+           }
 
          token->keyword = RID_MAX;
        }
@@ -961,13 +991,14 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
     case RID_FLOAT:
     case RID_DOUBLE:
     case RID_VOID:
-      /* GNU extensions.  */ 
+      /* GNU extensions.  */
     case RID_ATTRIBUTE:
     case RID_TYPEOF:
       /* C++0x extensions.  */
     case RID_DECLTYPE:
     case RID_UNDERLYING_TYPE:
     case RID_CONSTEXPR:
+    case RID_CONSTINIT:
       return true;
 
     default:
@@ -1306,7 +1337,7 @@ cp_lexer_start_debugging (cp_lexer* lexer)
 {
   if (!LEXER_DEBUGGING_ENABLED_P)
     fatal_error (input_location,
-                "LEXER_DEBUGGING_ENABLED_P is not set to true");
+                "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true");
 
   lexer->debugging_p = true;
   cp_lexer_debug_stream = stderr;
@@ -1319,7 +1350,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 {
   if (!LEXER_DEBUGGING_ENABLED_P)
     fatal_error (input_location,
-                "LEXER_DEBUGGING_ENABLED_P is not set to true");
+                "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true");
 
   lexer->debugging_p = false;
   cp_lexer_debug_stream = NULL;
@@ -1638,7 +1669,7 @@ make_array_declarator (cp_declarator *element, tree bounds)
 
 /* Determine whether the declarator we've seen so far can be a
    parameter pack, when followed by an ellipsis.  */
-static bool 
+static bool
 declarator_can_be_parameter_pack (cp_declarator *declarator)
 {
   if (declarator && declarator->parameter_pack_p)
@@ -1719,7 +1750,7 @@ function_declarator_p (const cp_declarator *declarator)
     }
   return false;
 }
+
 /* The parser.  */
 
 /* Overview
@@ -1797,7 +1828,9 @@ enum
   /* When parsing a decl-specifier-seq, only allow mutable or constexpr.  */
   CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10,
   /* When parsing a decl-specifier-seq, allow missing typename.  */
-  CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20
+  CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20,
+  /* When parsing of the noexcept-specifier should be delayed.  */
+  CP_PARSER_FLAGS_DELAY_NOEXCEPT = 0x40
 };
 
 /* This type is used for parameters and variables which hold
@@ -1972,11 +2005,14 @@ cp_parser_context_new (cp_parser_context* next)
   parser->unparsed_queues->last ().nsdmis
 #define unparsed_classes \
   parser->unparsed_queues->last ().classes
+#define unparsed_noexcepts \
+  parser->unparsed_queues->last ().noexcepts
 
 static void
 push_unparsed_function_queues (cp_parser *parser)
 {
-  cp_unparsed_functions_entry e = {NULL, make_tree_vector (), NULL, NULL};
+  cp_unparsed_functions_entry e = { NULL, make_tree_vector (), NULL, NULL,
+                                   NULL };
   vec_safe_push (parser->unparsed_queues, e);
 }
 
@@ -2081,7 +2117,7 @@ static cp_expr cp_parser_assignment_expression
 static enum tree_code cp_parser_assignment_operator_opt
   (cp_parser *);
 static cp_expr cp_parser_expression
-  (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false);
+  (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false, bool = false);
 static cp_expr cp_parser_constant_expression
   (cp_parser *, bool = false, bool * = NULL, bool = false);
 static cp_expr cp_parser_builtin_offsetof
@@ -2162,7 +2198,7 @@ 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_nonclass_name 
+static tree cp_parser_nonclass_name
   (cp_parser* parser);
 static tree cp_parser_elaborated_type_specifier
   (cp_parser *, bool, bool);
@@ -2240,7 +2276,7 @@ static tree cp_parser_parameter_declaration_list
   (cp_parser *, cp_parser_flags);
 static cp_parameter_declarator *cp_parser_parameter_declaration
   (cp_parser *, cp_parser_flags, bool, bool *);
-static tree cp_parser_default_argument 
+static tree cp_parser_default_argument
   (cp_parser *, bool);
 static void cp_parser_function_body
   (cp_parser *, bool);
@@ -2344,7 +2380,7 @@ static void cp_parser_explicit_instantiation
 static void cp_parser_explicit_specialization
   (cp_parser *);
 
-/* Exception handling [gram.exception] */
+/* Exception handling [gram.except] */
 
 static tree cp_parser_try_block
   (cp_parser *);
@@ -2359,9 +2395,11 @@ static tree cp_parser_exception_declaration
 static tree cp_parser_throw_expression
   (cp_parser *);
 static tree cp_parser_exception_specification_opt
-  (cp_parser *);
+  (cp_parser *, cp_parser_flags);
 static tree cp_parser_type_id_list
   (cp_parser *);
+static tree cp_parser_noexcept_specification_opt
+  (cp_parser *, cp_parser_flags, bool, bool *, bool);
 
 /* GNU Extensions */
 
@@ -2480,9 +2518,9 @@ static tree cp_parser_objc_statement
   (cp_parser *);
 static bool cp_parser_objc_valid_prefix_attributes
   (cp_parser *, tree *);
-static void cp_parser_objc_at_property_declaration 
+static void cp_parser_objc_at_property_declaration
   (cp_parser *) ;
-static void cp_parser_objc_at_synthesize_declaration 
+static void cp_parser_objc_at_synthesize_declaration
   (cp_parser *) ;
 static void cp_parser_objc_at_dynamic_declaration
   (cp_parser *) ;
@@ -2986,7 +3024,7 @@ cp_parser_name_lookup_error (cp_parser* parser,
            break;
          default:
            gcc_unreachable ();
-           
+
        }
     }
   else if (parser->scope == global_namespace)
@@ -3054,8 +3092,9 @@ cp_parser_check_type_definition (cp_parser* parser)
   if (parser->type_definition_forbidden_message)
     {
       /* Don't use `%s' to print the string, because quotations (`%<', `%>')
-        in the message need to be interpreted.  */
-      error (parser->type_definition_forbidden_message);
+        or %qs in the message need to be interpreted.  */
+      error (parser->type_definition_forbidden_message,
+            parser->type_definition_forbidden_message_arg);
       return false;
     }
   return true;
@@ -3084,7 +3123,7 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
     {
       error_at (type_location,
                "new types may not be defined in a return type");
-      inform (type_location, 
+      inform (type_location,
              "(perhaps a semicolon is missing after the definition of %qT)",
              type);
     }
@@ -3331,6 +3370,9 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
               && id_equal (id, "thread_local"))
        inform (location, "C++11 %<thread_local%> only available with "
                "%<-std=c++11%> or %<-std=gnu++11%>");
+      else if (cxx_dialect < cxx2a && id == ridpointers[(int)RID_CONSTINIT])
+       inform (location, "C++20 %<constinit%> only available with "
+               "%<-std=c++2a%> or %<-std=gnu++2a%>");
       else if (!flag_concepts && id == ridpointers[(int)RID_CONCEPT])
        inform (location, "%<concept%> only available with %<-fconcepts%>");
       else if (processing_template_decl && current_class_type
@@ -3357,7 +3399,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
                    if (TREE_CODE (field) == TYPE_DECL
                        && DECL_NAME (field) == id)
                      {
-                       inform (location, 
+                       inform (location,
                                "(perhaps %<typename %T::%E%> was intended)",
                                BINFO_TYPE (b), id);
                        break;
@@ -4342,18 +4384,16 @@ cp_parser_userdef_char_literal (cp_parser *parser)
 
   /* Build up a call to the user-defined operator  */
   /* Lookup the name we got back from the id-expression.  */
-  vec<tree, va_gc> *args = make_tree_vector ();
+  releasing_vec args;
   vec_safe_push (args, value);
   decl = lookup_literal_operator (name, args);
   if (!decl || decl == error_mark_node)
     {
       error ("unable to find character literal operator %qD with %qT argument",
             name, TREE_TYPE (value));
-      release_tree_vector (args);
       return error_mark_node;
     }
   result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
-  release_tree_vector (args);
   return result;
 }
 
@@ -4440,11 +4480,10 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
   tree num_string = USERDEF_LITERAL_NUM_STRING (literal);
   tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
   tree decl, result;
-  vec<tree, va_gc> *args;
 
   /* Look for a literal operator taking the exact type of numeric argument
      as the literal value.  */
-  args = make_tree_vector ();
+  releasing_vec args;
   vec_safe_push (args, value);
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
@@ -4469,30 +4508,26 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
                        "floating literal truncated to zero");
        }
 
-      release_tree_vector (args);
       return result;
     }
-  release_tree_vector (args);
 
   /* If the numeric argument didn't work, look for a raw literal
      operator taking a const char* argument consisting of the number
      in string format.  */
-  args = make_tree_vector ();
+  args->truncate (0);
   vec_safe_push (args, num_string);
   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);
 
   /* If the raw literal didn't work, look for a non-type template
      function with parameter pack char....  Call the function with
      template parameter characters representing the number.  */
-  args = make_tree_vector ();
+  args->truncate (0);
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
@@ -4506,12 +4541,9 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
       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;
     }
 
-  release_tree_vector (args);
-
   /* In C++14 the standard library defines complex number suffixes that
      conflict with GNU extensions.  Prefer them if <complex> is #included.  */
   bool ext = cpp_get_options (parse_in)->ext_numeric_literals;
@@ -4544,7 +4576,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
   else if (i14)
     {
       inform (token->location, "add %<using namespace std::complex_literals%> "
-             "(from <complex>) to enable the C++14 user-defined literal "
+             "(from %<<complex>%>) to enable the C++14 user-defined literal "
              "suffixes");
       if (ext)
        inform (token->location, "or use %<j%> instead of %<i%> for the "
@@ -4599,8 +4631,7 @@ cp_parser_userdef_string_literal (tree literal)
 
   /* Build up a call to the user-defined operator.  */
   /* Lookup the name we got back from the id-expression.  */
-  releasing_vec rargs;
-  vec<tree, va_gc> *&args = rargs.get_ref();
+  releasing_vec args;
   vec_safe_push (args, value);
   vec_safe_push (args, build_int_cst (size_type_node, len));
   decl = lookup_literal_operator (name, args);
@@ -4654,7 +4685,7 @@ static void
 cp_parser_translation_unit (cp_parser* parser)
 {
   gcc_checking_assert (!cp_error_declarator);
-  
+
   /* Create the declarator obstack.  */
   gcc_obstack_init (&declarator_obstack);
   /* Create the error declarator.  */
@@ -4670,7 +4701,7 @@ cp_parser_translation_unit (cp_parser* parser)
   for (;;)
     {
       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
@@ -5120,14 +5151,14 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
      __builtin_offsetof ( type-id , offsetof-expression )
 
    C++ Extensions:
-     __has_nothrow_assign ( type-id )   
+     __has_nothrow_assign ( type-id )
      __has_nothrow_constructor ( type-id )
      __has_nothrow_copy ( type-id )
-     __has_trivial_assign ( type-id )   
+     __has_trivial_assign ( type-id )
      __has_trivial_constructor ( type-id )
      __has_trivial_copy ( type-id )
      __has_trivial_destructor ( type-id )
-     __has_virtual_destructor ( type-id )     
+     __has_virtual_destructor ( type-id )
      __is_abstract ( type-id )
      __is_base_of ( type-id , type-id )
      __is_class ( type-id )
@@ -5515,10 +5546,10 @@ cp_parser_primary_expression (cp_parser *parser,
 
        case RID_HAS_NOTHROW_ASSIGN:
        case RID_HAS_NOTHROW_CONSTRUCTOR:
-       case RID_HAS_NOTHROW_COPY:        
+       case RID_HAS_NOTHROW_COPY:
        case RID_HAS_TRIVIAL_ASSIGN:
        case RID_HAS_TRIVIAL_CONSTRUCTOR:
-       case RID_HAS_TRIVIAL_COPY:        
+       case RID_HAS_TRIVIAL_COPY:
        case RID_HAS_TRIVIAL_DESTRUCTOR:
        case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS:
        case RID_HAS_VIRTUAL_DESTRUCTOR:
@@ -6060,7 +6091,7 @@ cp_parser_unqualified_id (cp_parser* parser,
                    && constructor_name_p (token->u.value, scope))))
          {
            cp_lexer_consume_token (parser->lexer);
-           return cp_expr (build_nt (BIT_NOT_EXPR, scope), loc);
+           return build_min_nt_loc (loc, BIT_NOT_EXPR, scope);
          }
 
        /* ~auto means the destructor of whatever the object is.  */
@@ -6071,7 +6102,7 @@ cp_parser_unqualified_id (cp_parser* parser,
                       "%<~auto%> only available with "
                       "%<-std=c++14%> or %<-std=gnu++14%>");
            cp_lexer_consume_token (parser->lexer);
-           return cp_expr (build_nt (BIT_NOT_EXPR, make_auto (), loc));
+           return build_min_nt_loc (loc, BIT_NOT_EXPR, make_auto ());
          }
 
        /* If there was an explicit qualification (S::~T), first look
@@ -6161,8 +6192,8 @@ cp_parser_unqualified_id (cp_parser* parser,
                   time.  */
                type_decl = cp_parser_identifier (parser);
                if (type_decl != error_mark_node)
-                 type_decl = build_nt (BIT_NOT_EXPR, type_decl);
-               return cp_expr (type_decl, loc);
+                 type_decl = build_min_nt_loc (loc, BIT_NOT_EXPR, type_decl);
+               return type_decl;
              }
          }
        /* If an error occurred, assume that the name of the
@@ -6170,7 +6201,7 @@ cp_parser_unqualified_id (cp_parser* parser,
           class.  That allows us to keep parsing after running
           into ill-formed destructor names.  */
        if (type_decl == error_mark_node && scope)
-         return build_nt (BIT_NOT_EXPR, scope);
+         return build_min_nt_loc (loc, BIT_NOT_EXPR, scope);
        else if (type_decl == error_mark_node)
          return error_mark_node;
 
@@ -6197,7 +6228,7 @@ cp_parser_unqualified_id (cp_parser* parser,
                    "typedef-name %qD used as destructor declarator",
                    type_decl);
 
-       return cp_expr (build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl), loc));
+       return build_min_nt_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
 
     case CPP_KEYWORD:
@@ -6274,7 +6305,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
   cp_token *token;
 
   /* Remember where the nested-name-specifier starts.  */
-  if (cp_parser_uncommitted_to_tentative_parse_p (parser))
+  if (cp_parser_uncommitted_to_tentative_parse_p (parser)
+      && cp_lexer_next_token_is_not (parser->lexer, CPP_NESTED_NAME_SPECIFIER))
     {
       start = cp_lexer_token_position (parser->lexer, false);
       push_deferring_access_checks (dk_deferred);
@@ -6408,9 +6440,11 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                  == CPP_SCOPE))
            {
              token = cp_lexer_consume_token (parser->lexer);
-             error_at (token->location, "decltype evaluates to %qT, "
-                       "which is not a class or enumeration type",
-                       token->u.tree_check_value->value);
+             tree dtype = token->u.tree_check_value->value;
+             if (dtype != error_mark_node)
+               error_at (token->location, "%<decltype%> evaluates to %qT, "
+                         "which is not a class or enumeration type",
+                         dtype);
              parser->scope = error_mark_node;
              error_p = true;
              /* As below.  */
@@ -6686,7 +6720,7 @@ cp_parser_qualifying_entity (cp_parser *parser,
   saved_object_scope = parser->object_scope;
   /* Try for a class-name first.  If the SAVED_SCOPE is a type, then
      there is no need to look for a namespace-name.  */
-  only_class_p = template_keyword_p 
+  only_class_p = template_keyword_p
     || (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98);
   if (!only_class_p)
     cp_parser_parse_tentatively (parser);
@@ -6733,7 +6767,7 @@ cp_parser_compound_literal_p (cp_parser *parser)
     = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
                                              /*consume_paren=*/true)
        && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
-  
+
   /* Roll back the tokens we skipped.  */
   cp_lexer_rollback_tokens (parser->lexer);
 
@@ -6883,7 +6917,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            break;
          case RID_REINTCAST:
            postfix_expression
-             = build_reinterpret_cast (type, expression, 
+             = build_reinterpret_cast (type, expression,
                                         tf_warning_or_error);
            break;
          case RID_CONSTCAST:
@@ -7510,7 +7544,9 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
          index = cp_parser_braced_list (parser, &expr_nonconst_p);
        }
       else
-       index = cp_parser_expression (parser);
+       index = cp_parser_expression (parser, NULL, /*cast_p=*/false,
+                                     /*decltype_p=*/false,
+                                     /*warn_comma_p=*/warn_comma_subscript);
     }
 
   parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
@@ -7765,17 +7801,15 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
              (name, parser->scope, scope);
          postfix_expression
            = finish_class_member_access_expr (postfix_expression, name,
-                                              template_p, 
+                                              template_p,
                                               tf_warning_or_error);
          /* Build a location e.g.:
               ptr->access_expr
               ~~~^~~~~~~~~~~~~
             where the caret is at the deref token, ranging from
             the start of postfix_expression to the end of the access expr.  */
-         location_t end_loc
-           = get_finish (cp_lexer_previous_token (parser->lexer)->location);
          location_t combined_loc
-           = make_location (input_location, start_loc, end_loc);
+           = make_location (input_location, start_loc, parser->lexer);
          protected_set_expr_location (postfix_expression, combined_loc);
        }
     }
@@ -8185,10 +8219,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
               ^~~~~~~~~~~~~~
               with start == caret at the start of the "alignof"/"sizeof"
               token, 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);
+             = make_location (start_loc, start_loc, parser->lexer);
 
            cp_expr ret_expr (ret);
            ret_expr.set_location (compound_loc);
@@ -8289,8 +8321,6 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
 
            parser->type_definition_forbidden_message = saved_message;
 
-           location_t finish_loc
-             = cp_lexer_peek_token (parser->lexer)->location;
            parens.require_close (parser);
 
            /* Construct a location of the form:
@@ -8298,7 +8328,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
               ^~~~~~~~~~~~~~~
               with start == caret, finishing at the close-paren.  */
            location_t noexcept_loc
-             = make_location (start_loc, start_loc, finish_loc);
+             = make_location (start_loc, start_loc, parser->lexer);
 
            return cp_expr (finish_noexcept_expr (expr, tf_warning_or_error),
                            noexcept_loc);
@@ -8349,15 +8379,13 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
          /* Consume the '&&' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Look for the identifier.  */
-         location_t finish_loc
-           = get_finish (cp_lexer_peek_token (parser->lexer)->location);
          identifier = cp_parser_identifier (parser);
          /* Construct a location of the form:
               &&label
               ^~~~~~~
             with caret==start at the "&&", finish at the end of the label.  */
          location_t combined_loc
-           = make_location (start_loc, start_loc, finish_loc);
+           = make_location (start_loc, start_loc, parser->lexer);
          /* Create an expression representing the address.  */
          expression = finish_label_address_expr (identifier, combined_loc);
          if (cp_parser_non_integral_constant_expression (parser,
@@ -8518,12 +8546,12 @@ cp_parser_has_attribute_expression (cp_parser *parser)
   /* 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;
+  const char *saved_message_arg
+    = parser->type_definition_forbidden_message_arg;
+  parser->type_definition_forbidden_message
+    = G_("types may not be defined in %qs expressions");
+  parser->type_definition_forbidden_message_arg
+    = IDENTIFIER_POINTER (ridpointers[RID_BUILTIN_HAS_ATTRIBUTE]);
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
@@ -8552,9 +8580,9 @@ cp_parser_has_attribute_expression (cp_parser *parser)
   cp_parser_parse_definitely (parser);
 
   /* If the type-id production did not work out, then we must be
-     looking at the unary-expression production.  */
+     looking at an expression.  */
   if (!oper || oper == error_mark_node)
-    oper = cp_parser_unary_expression (parser);
+    oper = cp_parser_assignment_expression (parser);
 
   STRIP_ANY_LOCATION_WRAPPER (oper);
 
@@ -8562,10 +8590,9 @@ cp_parser_has_attribute_expression (cp_parser *parser)
   --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->type_definition_forbidden_message_arg = saved_message_arg;
   parser->integral_constant_expression_p
     = saved_integral_constant_expression_p;
   parser->non_integral_constant_expression_p
@@ -8606,10 +8633,8 @@ cp_parser_has_attribute_expression (cp_parser *parser)
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      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);
+    = make_location (start_loc, start_loc, parser->lexer);
 
   cp_expr ret_expr (ret ? boolean_true_node : boolean_false_node);
   ret_expr.set_location (compound_loc);
@@ -8687,7 +8712,7 @@ cp_parser_new_expression (cp_parser* parser)
        {
          error_at (token->location,
                    "array bound forbidden after parenthesized type-id");
-         inform (token->location, 
+         inform (token->location,
                  "try removing the parentheses around the type-id");
          cp_parser_direct_new_declarator (parser);
        }
@@ -8731,9 +8756,8 @@ cp_parser_new_expression (cp_parser* parser)
                  ^~~~~~~~~~~~
          with caret == start at the start of the "new" token, and the end
          at the end of the final token we consumed.  */
-      cp_token *end_tok = cp_lexer_previous_token (parser->lexer);
-      location_t end_loc = get_finish (end_tok->location);
-      location_t combined_loc = make_location (start_loc, start_loc, end_loc);
+      location_t combined_loc = make_location (start_loc, start_loc,
+                                              parser->lexer);
 
       /* Create a representation of the new-expression.  */
       ret = build_new (&placement, type, nelts, &initializer, global_scope_p,
@@ -8861,7 +8885,7 @@ cp_parser_new_declarator_opt (cp_parser* parser)
 {
   enum tree_code code;
   tree type, std_attributes = NULL_TREE;
-  cp_cv_quals cv_quals;  
+  cp_cv_quals cv_quals;
 
   /* We don't know if there's a ptr-operator next, or not.  */
   cp_parser_parse_tentatively (parser);
@@ -9345,7 +9369,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
              return expr;
            }
        }
-      else 
+      else
         cp_parser_abort_tentative_parse (parser);
     }
 
@@ -9443,6 +9467,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 {
   cp_parser_expression_stack stack;
   cp_parser_expression_stack_entry *sp = &stack[0];
+  cp_parser_expression_stack_entry *disable_warnings_sp = NULL;
   cp_parser_expression_stack_entry current;
   cp_expr rhs;
   cp_token *token;
@@ -9506,12 +9531,14 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 
       /* For "false && x" or "true || x", x will never be executed;
         disable warnings while evaluating it.  */
-      if (current.tree_type == TRUTH_ANDIF_EXPR)
-       c_inhibit_evaluation_warnings +=
-         cp_fully_fold (current.lhs) == truthvalue_false_node;
-      else if (current.tree_type == TRUTH_ORIF_EXPR)
-       c_inhibit_evaluation_warnings +=
-         cp_fully_fold (current.lhs) == truthvalue_true_node;
+      if ((current.tree_type == TRUTH_ANDIF_EXPR
+          && cp_fully_fold (current.lhs) == truthvalue_false_node)
+         || (current.tree_type == TRUTH_ORIF_EXPR
+             && cp_fully_fold (current.lhs) == truthvalue_true_node))
+       {
+         disable_warnings_sp = sp;
+         ++c_inhibit_evaluation_warnings;
+       }
 
       /* Extract another operand.  It may be the RHS of this expression
         or the LHS of a new, higher priority expression.  */
@@ -9557,12 +9584,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
        }
 
       /* Undo the disabling of warnings done above.  */
-      if (current.tree_type == TRUTH_ANDIF_EXPR)
-       c_inhibit_evaluation_warnings -=
-         cp_fully_fold (current.lhs) == truthvalue_false_node;
-      else if (current.tree_type == TRUTH_ORIF_EXPR)
-       c_inhibit_evaluation_warnings -=
-         cp_fully_fold (current.lhs) == truthvalue_true_node;
+      if (sp == disable_warnings_sp)
+       {
+         disable_warnings_sp = NULL;
+         --c_inhibit_evaluation_warnings;
+       }
 
       if (warn_logical_not_paren
          && TREE_CODE_CLASS (current.tree_type) == tcc_comparison
@@ -9677,8 +9703,8 @@ cp_parser_question_colon_clause (cp_parser* parser, cp_expr logical_or_expr)
   if (cp_parser_allow_gnu_extensions_p (parser)
       && token->type == CPP_COLON)
     {
-      pedwarn (token->location, OPT_Wpedantic, 
-               "ISO C++ does not allow ?: with omitted middle operand");
+      pedwarn (token->location, OPT_Wpedantic,
+              "ISO C++ does not allow %<?:%> with omitted middle operand");
       /* Implicit true clause.  */
       expr = NULL_TREE;
       c_inhibit_evaluation_warnings +=
@@ -9902,12 +9928,13 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
    CAST_P is true if this expression is the target of a cast.
    DECLTYPE_P is true if this expression is the immediate operand of decltype,
      except possibly parenthesized or on the RHS of a comma (N3276).
+   WARN_COMMA_P is true if a comma should be diagnosed.
 
    Returns a representation of the expression.  */
 
 static cp_expr
 cp_parser_expression (cp_parser* parser, cp_id_kind * pidk,
-                     bool cast_p, bool decltype_p)
+                     bool cast_p, bool decltype_p, bool warn_comma_p)
 {
   cp_expr expression = NULL_TREE;
   location_t loc = UNKNOWN_LOCATION;
@@ -9954,6 +9981,17 @@ cp_parser_expression (cp_parser* parser, cp_id_kind * pidk,
        break;
       /* Consume the `,'.  */
       loc = cp_lexer_peek_token (parser->lexer)->location;
+      if (warn_comma_p)
+       {
+         /* [depr.comma.subscript]: A comma expression appearing as
+            the expr-or-braced-init-list of a subscripting expression
+            is deprecated.  A parenthesized comma expression is not
+            deprecated.  */
+         warning_at (loc, OPT_Wcomma_subscript,
+                     "top-level comma expression in array subscript "
+                     "is deprecated");
+         warn_comma_p = false;
+       }
       cp_lexer_consume_token (parser->lexer);
       /* A comma operator cannot appear in a constant-expression.  */
       if (cp_parser_non_integral_constant_expression (parser, NIC_COMMA))
@@ -10314,7 +10352,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
   if (binary)
     {
       cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+
       {
        type_id_in_expr_sentinel s (parser);
        type2 = cp_parser_type_id (parser);
@@ -10360,7 +10398,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case CPTK_DIRECT_BASES:
       return cp_expr (finish_bases (type1, true), trait_loc);
     default:
-      return cp_expr (finish_trait_expr (kind, type1, type2), trait_loc);
+      return finish_trait_expr (trait_loc, kind, type1, type2);
     }
 }
 
@@ -10395,7 +10433,7 @@ cp_parser_lambda_expression (cp_parser* parser)
        }
       ok = false;
     }
-  else if (parser->in_template_argument_list_p)
+  else if (parser->in_template_argument_list_p || processing_template_parmlist)
     {
       if (!token->error_reported)
        {
@@ -10476,7 +10514,7 @@ cp_parser_lambda_expression (cp_parser* parser)
     if (ok)
       maybe_add_lambda_conv_op (type);
 
-    type = finish_struct (type, /*attributes=*/NULL_TREE);
+    finish_struct (type, /*attributes=*/NULL_TREE);
 
     parser->num_template_parameter_lists = saved_num_template_parameter_lists;
     parser->in_statement = in_statement;
@@ -10498,10 +10536,9 @@ cp_parser_lambda_expression (cp_parser* parser)
   insert_pending_capture_proxies ();
 
   /* Update the lambda expression to a range.  */
-  cp_token *end_tok = cp_lexer_previous_token (parser->lexer);
   LAMBDA_EXPR_LOCATION (lambda_expr) = make_location (token->location,
                                                      token->location,
-                                                     end_tok->location);
+                                                     parser->lexer);
 
   if (ok)
     lambda_expr = build_lambda_object (lambda_expr);
@@ -10533,7 +10570,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
 
   /* Record default capture mode.  "[&" "[=" "[&," "[=,"  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
-      && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_NAME)
+      && !cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)
+      && !cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_THIS))
     LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE;
   else if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
     LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_COPY;
@@ -10547,6 +10585,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
        error ("non-local lambda expression cannot have a capture-default");
     }
 
+  hash_set<tree, true> ids;
+  tree first_capture_id = NULL_TREE;
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
     {
       cp_token* capture_token;
@@ -10582,11 +10622,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
            pedwarn (loc, 0, "explicit by-copy capture of %<this%> redundant "
                     "with by-copy capture default");
          cp_lexer_consume_token (parser->lexer);
-         add_capture (lambda_expr,
-                      /*id=*/this_identifier,
-                      /*initializer=*/finish_this_expr (),
-                      /*by_reference_p=*/true,
-                      explicit_init_p);
+         if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+           pedwarn (input_location, 0,
+                    "already captured %qD in lambda expression",
+                    this_identifier);
+         else
+           add_capture (lambda_expr, /*id=*/this_identifier,
+                        /*initializer=*/finish_this_expr (),
+                        /*by_reference_p=*/true, explicit_init_p);
          continue;
        }
 
@@ -10600,21 +10643,36 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
                             "%<-std=c++17%> or %<-std=gnu++17%>");
          cp_lexer_consume_token (parser->lexer);
          cp_lexer_consume_token (parser->lexer);
-         add_capture (lambda_expr,
-                      /*id=*/this_identifier,
-                      /*initializer=*/finish_this_expr (),
-                      /*by_reference_p=*/false,
-                      explicit_init_p);
+         if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+           pedwarn (input_location, 0,
+                    "already captured %qD in lambda expression",
+                    this_identifier);
+         else
+           add_capture (lambda_expr, /*id=*/this_identifier,
+                        /*initializer=*/finish_this_expr (),
+                        /*by_reference_p=*/false, explicit_init_p);
+         continue;
+       }
+
+      /* But reject `&this'.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
+         && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_THIS))
+       {
+         error_at (cp_lexer_peek_token (parser->lexer)->location,
+                   "%<this%> cannot be captured by reference");
+         cp_lexer_consume_token (parser->lexer);
+         cp_lexer_consume_token (parser->lexer);
          continue;
        }
 
       bool init_pack_expansion = false;
+      location_t ellipsis_loc = UNKNOWN_LOCATION;
       if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
        {
-         location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+         ellipsis_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%>");
+           pedwarn (ellipsis_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;
        }
@@ -10719,8 +10777,21 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
 
          if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
            {
+             location_t loc = cp_lexer_peek_token (parser->lexer)->location;
              cp_lexer_consume_token (parser->lexer);
              capture_init_expr = make_pack_expansion (capture_init_expr);
+             if (init_pack_expansion)
+               {
+                 /* If what follows is an initializer, the second '...' is
+                    invalid.  But for cases like [...xs...], the first one
+                    is invalid.  */
+                 if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)
+                     || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+                     || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+                   ellipsis_loc = loc;
+                 error_at (ellipsis_loc, "too many %<...%> in lambda capture");
+                 continue;
+               }
            }
        }
 
@@ -10739,11 +10810,28 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
                     "default", capture_id);
        }
 
-      add_capture (lambda_expr,
-                  capture_id,
-                  capture_init_expr,
-                  /*by_reference_p=*/capture_kind == BY_REFERENCE,
-                  explicit_init_p);
+      /* Check for duplicates.
+        Optimize for the zero or one explicit captures cases and only create
+        the hash_set after adding second capture.  */
+      bool found = false;
+      if (!ids.is_empty ())
+       found = ids.add (capture_id);
+      else if (first_capture_id == NULL_TREE)
+       first_capture_id = capture_id;
+      else if (capture_id == first_capture_id)
+       found = true;
+      else
+       {
+         ids.add (first_capture_id);
+         ids.add (capture_id);
+       }
+      if (found)
+       pedwarn (input_location, 0,
+                "already captured %qD in lambda expression", capture_id);
+      else
+       add_capture (lambda_expr, capture_id, capture_init_expr,
+                    /*by_reference_p=*/capture_kind == BY_REFERENCE,
+                    explicit_init_p);
 
       /* If there is any qualification still in effect, clear it
         now; we will be starting fresh with the next capture.  */
@@ -10776,7 +10864,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
      This means an empty parameter list, no attributes, and no exception
      specification.  */
   tree param_list = void_list_node;
-  tree attributes = NULL_TREE;
+  tree std_attrs = NULL_TREE;
+  tree gnu_attrs = NULL_TREE;
   tree exception_spec = NULL_TREE;
   tree template_param_list = NULL_TREE;
   tree tx_qual = NULL_TREE;
@@ -10835,7 +10924,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       /* In the decl-specifier-seq of the lambda-declarator, each
         decl-specifier shall either be mutable or constexpr.  */
       int declares_class_or_enum;
-      if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
+      if (cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
+         && !cp_next_tokens_can_be_gnu_attribute_p (parser))
        cp_parser_decl_specifier_seq (parser,
                                      CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR,
                                      &lambda_specs, &declares_class_or_enum);
@@ -10850,9 +10940,10 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       tx_qual = cp_parser_tx_qualifier_opt (parser);
 
       /* Parse optional exception specification.  */
-      exception_spec = cp_parser_exception_specification_opt (parser);
+      exception_spec
+       = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE);
 
-      attributes = cp_parser_std_attribute_spec_seq (parser);
+      std_attrs = cp_parser_std_attribute_spec_seq (parser);
 
       /* Parse optional trailing return type.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
@@ -10861,6 +10952,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
           return_type = cp_parser_trailing_type_id (parser);
         }
 
+      if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+       gnu_attrs = cp_parser_gnu_attributes_opt (parser);
+
       /* The function parameters must be in scope all the way until after the
          trailing-return-type in case of decltype.  */
       pop_bindings_and_leave_scope ();
@@ -10908,18 +11002,18 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
                                       exception_spec,
                                        return_type,
                                        /*requires_clause*/NULL_TREE);
-    declarator->std_attributes = attributes;
+    declarator->std_attributes = std_attrs;
 
     fco = grokmethod (&return_type_specs,
                      declarator,
-                     NULL_TREE);
+                     gnu_attrs);
     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;
+       DECL_SET_LAMBDA_FUNCTION (fco, true);
       }
     if (template_param_list)
       {
@@ -11088,11 +11182,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
     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);
-    }
+    attrs_loc = make_location (attrs_loc, attrs_loc, parser->lexer);
   if (c_dialect_objc ())
     {
       if (!cp_parser_parse_definitely (parser))
@@ -11169,7 +11259,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
            }
          cp_parser_declaration_statement (parser);
          return;
-         
+
        case RID_TRANSACTION_ATOMIC:
        case RID_TRANSACTION_RELAXED:
        case RID_SYNCHRONIZED:
@@ -11591,12 +11681,12 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
          || token->type == CPP_PRAGMA_EOL
          || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END))
        break;
-      
+
       /* If we are in a compound statement and find 'else' then
         something went wrong.  */
       else if (token->type == CPP_KEYWORD && token->keyword == RID_ELSE)
        {
-         if (parser->in_statement & IN_IF_STMT) 
+         if (parser->in_statement & IN_IF_STMT)
            break;
          else
            {
@@ -11999,6 +12089,10 @@ cp_parser_condition (cp_parser* parser)
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
 
+  /* Gather the attributes that were provided with the
+     decl-specifiers.  */
+  tree prefix_attributes = type_specifiers.attributes;
+
   cp_parser_maybe_commit_to_declaration (parser,
                                         type_specifiers.any_specifiers_p);
 
@@ -12034,7 +12128,7 @@ cp_parser_condition (cp_parser* parser)
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
        cp_parser_simulate_error (parser);
-       
+
       /* If we did see an `=' or '{', then we are looking at a declaration
         for sure.  */
       if (cp_parser_parse_definitely (parser))
@@ -12049,7 +12143,7 @@ cp_parser_condition (cp_parser* parser)
          /* Create the declaration.  */
          decl = start_decl (declarator, &type_specifiers,
                             /*initialized_p=*/true,
-                            attributes, /*prefix_attributes=*/NULL_TREE,
+                            attributes, prefix_attributes,
                             &pushed_scope);
 
          /* Parse the initializer.  */
@@ -12491,8 +12585,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
       else
        {
          /* Use global functions with ADL.  */
-         vec<tree, va_gc> *vec;
-         vec = make_tree_vector ();
+         releasing_vec vec;
 
          vec_safe_push (vec, range);
 
@@ -12504,8 +12597,6 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
                                              tf_warning_or_error);
          *end = finish_call_expr (member_end, &vec, false, true,
                                   tf_warning_or_error);
-
-         release_tree_vector (vec);
        }
 
       /* Last common checks.  */
@@ -12553,19 +12644,17 @@ static tree
 cp_parser_range_for_member_function (tree range, tree identifier)
 {
   tree member, res;
-  vec<tree, va_gc> *vec;
 
   member = finish_class_member_access_expr (range, identifier,
                                            false, tf_warning_or_error);
   if (member == error_mark_node)
     return error_mark_node;
 
-  vec = make_tree_vector ();
+  releasing_vec vec;
   res = finish_call_expr (member, &vec,
                          /*disallow_virtual=*/false,
                          /*koenig_p=*/false,
                          tf_warning_or_error);
-  release_tree_vector (vec);
   return res;
 }
 
@@ -12804,7 +12893,7 @@ cp_parser_jump_statement (cp_parser* parser)
   switch (keyword)
     {
     case RID_BREAK:
-      in_statement = parser->in_statement & ~IN_IF_STMT;      
+      in_statement = parser->in_statement & ~IN_IF_STMT;
       switch (in_statement)
        {
        case 0:
@@ -12865,7 +12954,7 @@ cp_parser_jump_statement (cp_parser* parser)
             expression.  */
          expr = NULL_TREE;
        /* Build the return-statement.  */
-       if (current_function_auto_return_pattern && in_discarded_stmt)
+       if (FNDECL_USED_AUTO (current_function_decl) && in_discarded_stmt)
          /* Don't deduce from a discarded return statement.  */;
        else
          statement = finish_return_stmt (expr);
@@ -13771,9 +13860,12 @@ cp_parser_decomposition_declaration (cp_parser *parser,
 
       if (decl != error_mark_node)
        {
+         int flags = (decl_spec_seq_has_spec_p (decl_specifiers, ds_constinit)
+                      ? LOOKUP_CONSTINIT : 0);
          cp_maybe_mangle_decomp (decl, prev, v.length ());
          cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
-                         is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT);
+                         (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT)
+                         | flags);
          cp_finish_decomp (decl, prev, v.length ());
        }
     }
@@ -13925,7 +14017,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
        {
          /* decl-specifier:
               friend
-               constexpr */
+              constexpr
+              constinit */
        case RID_FRIEND:
          if (!at_class_scope_p ())
            {
@@ -13947,9 +14040,23 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
           cp_lexer_consume_token (parser->lexer);
           break;
 
+       case RID_CONSTINIT:
+         ds = ds_constinit;
+         cp_lexer_consume_token (parser->lexer);
+         break;
+
         case RID_CONCEPT:
           ds = ds_concept;
           cp_lexer_consume_token (parser->lexer);
+         /* In C++20 a concept definition is just 'concept name = expr;'
+            Support that syntax by pretending we've seen 'bool'.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+             && cp_lexer_nth_token_is (parser->lexer, 2, CPP_EQ))
+           {
+             cp_parser_set_decl_spec_type (decl_specs, boolean_type_node,
+                                           token, /*type_definition*/false);
+             decl_specs->any_type_specifiers_p = true;
+           }
           break;
 
          /* function-specifier:
@@ -13988,7 +14095,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             GNU Extension:
               thread  */
        case RID_AUTO:
-          if (cxx_dialect == cxx98) 
+          if (cxx_dialect == cxx98)
             {
              /* Consume the token.  */
              cp_lexer_consume_token (parser->lexer);
@@ -14034,7 +14141,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       if (found_decl_spec
          && (flags & CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR)
          && token->keyword != RID_CONSTEXPR)
-       error ("decl-specifier invalid in condition");
+       error ("%<decl-specifier%> invalid in condition");
 
       if (found_decl_spec
          && (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
@@ -14359,12 +14466,12 @@ cp_parser_linkage_specification (cp_parser* parser)
 /* Parse a static_assert-declaration.
 
    static_assert-declaration:
-     static_assert ( constant-expression , string-literal ) ; 
+     static_assert ( constant-expression , string-literal ) ;
      static_assert ( constant-expression ) ; (C++17)
 
    If MEMBER_P, this static_assert is a class member.  */
 
-static void 
+static void
 cp_parser_static_assert(cp_parser *parser, bool member_p)
 {
   cp_expr condition;
@@ -14377,7 +14484,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
   token_loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Look for the `static_assert' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, 
+  if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT,
                                   RT_STATIC_ASSERT))
     return;
 
@@ -14392,7 +14499,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
 
   /* Parse the constant-expression.  Allow a non-constant expression
      here in order to give better diagnostics in finish_static_assert.  */
-  condition = 
+  condition =
     cp_parser_constant_expression (parser,
                                    /*allow_non_constant_p=*/true,
                                    /*non_constant_p=*/&dummy);
@@ -14401,7 +14508,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 "
+                "%<static_assert%> without a message "
                 "only available with %<-std=c++17%> or %<-std=gnu++17%>");
       /* Eat the ')'  */
       cp_lexer_consume_token (parser->lexer);
@@ -14415,14 +14522,14 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
       cp_parser_require (parser, CPP_COMMA, RT_COMMA);
 
       /* Parse the string-literal message.  */
-      message = cp_parser_string_literal (parser, 
+      message = cp_parser_string_literal (parser,
                                          /*translate=*/false,
                                          /*wide_ok=*/true);
 
       /* A `)' completes the static assertion.  */
       if (!parens.require_close (parser))
-       cp_parser_skip_to_closing_parenthesis (parser, 
-                                               /*recovering=*/true, 
+       cp_parser_skip_to_closing_parenthesis (parser,
+                                               /*recovering=*/true,
                                                /*or_comma=*/false,
                                               /*consume_paren=*/true);
     }
@@ -14437,7 +14544,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
   if (assert_loc == UNKNOWN_LOCATION)
     assert_loc = token_loc;
 
-  /* Complete the static assertion, which may mean either processing 
+  /* Complete the static assertion, which may mean either processing
      the static assert now or saving it for template instantiation.  */
   finish_static_assert (condition, message, assert_loc, member_p);
 }
@@ -14511,7 +14618,7 @@ cp_parser_decltype_expr (cp_parser *parser,
             id_expression_or_member_access_p = true;
         }
 
-      if (expr 
+      if (expr
           && expr != error_mark_node
           && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
         /* We have an id-expression.  */
@@ -14531,7 +14638,7 @@ cp_parser_decltype_expr (cp_parser *parser,
                                            /*cast_p=*/false, /*decltype*/true,
                                            /*member_access_only_p=*/true, NULL);
 
-      if (expr 
+      if (expr
           && expr != error_mark_node
           && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
         /* We have an id-expression.  */
@@ -14590,7 +14697,7 @@ cp_parser_decltype (cp_parser *parser)
   push_deferring_access_checks (dk_deferred);
 
   tree expr = NULL_TREE;
-  
+
   if (cxx_dialect >= cxx14
       && cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
     /* decltype (auto) */
@@ -14675,7 +14782,7 @@ cp_parser_decltype (cp_parser *parser)
   cp_lexer_purge_tokens_after (parser->lexer, start_token);
 
   pop_to_parent_deferring_access_checks ();
-  
+
   return expr;
 }
 
@@ -14759,8 +14866,9 @@ cp_parser_conversion_type_id (cp_parser* parser)
   parser->type_definition_forbidden_message
     = G_("types may not be defined in a conversion-type-id");
 
-  /* Parse the type-specifiers.  */
-  cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+  /* Parse the type-specifiers.  DR 2413 clarifies that `typename' is
+     optional in conversion-type-id.  */
+  cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
                                /*is_declaration=*/false,
                                /*is_trailing_return=*/false,
                                &type_specifiers);
@@ -15047,7 +15155,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
-      error_at (token->location, 
+      error_at (token->location,
                "keyword %<typename%> not allowed in this context (a qualified "
                "member initializer is implicitly a type)");
       cp_lexer_consume_token (parser->lexer);
@@ -15466,10 +15574,8 @@ cp_parser_operator (cp_parser* parser, location_t start_loc)
             ^~~~~~~~~~~~~~~~~~~~~
           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);
+         = make_location (start_loc, start_loc, parser->lexer);
        return cp_expr (id, combined_loc);
       }
 
@@ -15577,7 +15683,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
 
       /* Parse the template-parameter.  */
       parm_loc = cp_lexer_peek_token (parser->lexer)->location;
-      parameter = cp_parser_template_parameter (parser, 
+      parameter = cp_parser_template_parameter (parser,
                                                 &is_non_type,
                                                 &is_parameter_pack);
       /* Add it to the list.  */
@@ -16391,10 +16497,8 @@ cp_parser_template_id (cp_parser *parser,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      with caret == start at the start of the template-name,
      ranging until the closing '>'.  */
-  location_t finish_loc
-    = get_finish (cp_lexer_previous_token (parser->lexer)->location);
   location_t combined_loc
-    = make_location (token->location, token->location, finish_loc);
+    = make_location (token->location, token->location, parser->lexer);
 
   /* Check for concepts autos where they don't belong.  We could
      identify types in some cases of idnetifier TEMPL, looking ahead
@@ -16438,10 +16542,7 @@ cp_parser_template_id (cp_parser *parser,
     {
       /* If it's not a class-template or a template-template, it should be
         a function-template.  */
-      gcc_assert ((DECL_FUNCTION_TEMPLATE_P (templ)
-                  || TREE_CODE (templ) == OVERLOAD
-                  || TREE_CODE (templ) == FUNCTION_DECL
-                  || BASELINK_P (templ)));
+      gcc_assert (OVL_P (templ) || BASELINK_P (templ));
 
       template_id = lookup_template_function (templ, arguments);
       if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR)
@@ -16857,7 +16958,7 @@ cp_parser_template_argument (cp_parser* parser)
      Here 'X()' is a valid type-id of a function type, but the user just
      wanted to write the expression "X() >> 5". Thus, we remember that we
      found a valid type-id, but we still try to parse the argument as an
-     expression to see what happens. 
+     expression to see what happens.
 
      In C++0x, the '>>' will be considered two separate '>'
      tokens.  */
@@ -17483,7 +17584,7 @@ cp_parser_type_specifier (cp_parser* parser,
 
    simple-type-specifier:
      auto
-     decltype ( expression )   
+     decltype ( expression )
      char16_t
      char32_t
      __underlying_type ( type-id )
@@ -17563,6 +17664,12 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        {
          decl_specs->explicit_intN_p = true;
          decl_specs->int_n_idx = idx;
+         /* Check if the alternate "__intN__" form has been used instead of
+            "__intN".  */
+         if (strncmp (IDENTIFIER_POINTER (token->u.value)
+                       + (IDENTIFIER_LENGTH (token->u.value) - 2),
+                       "__", 2) == 0)
+           decl_specs->int_n_alt = true;
        }
       type = int_n_trees [idx].signed_type;
       break;
@@ -17767,7 +17874,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
       /* Don't gobble tokens or issue error messages if this is an
         optional type-specifier.  */
-      if ((flags & CP_PARSER_FLAGS_OPTIONAL) || cxx_dialect >= cxx17)
+      if (flags & CP_PARSER_FLAGS_OPTIONAL)
        cp_parser_parse_tentatively (parser);
 
       token = cp_lexer_peek_token (parser->lexer);
@@ -17807,37 +17914,26 @@ cp_parser_simple_type_specifier (cp_parser* parser,
              else
                {
                  cp_parser_error (parser, "expected template-id for type");
-                 type = NULL_TREE;
+                 type = error_mark_node;
                }
            }
        }
-      /* Otherwise, look for a type-name.  */
-      else
-       type = cp_parser_type_name (parser, (qualified_p && typename_p));
 
-      /* Keep track of all name-lookups performed in class scopes.  */
-      if (type
-         && !global_p
-         && !qualified_p
-         && TREE_CODE (type) == TYPE_DECL
-         && identifier_p (DECL_NAME (type)))
-       maybe_note_name_used_in_class (DECL_NAME (type), type);
-      /* If it didn't work out, we don't have a TYPE.  */
-      if (((flags & CP_PARSER_FLAGS_OPTIONAL) || cxx_dialect >= cxx17)
-         && !cp_parser_parse_definitely (parser))
-       type = NULL_TREE;
-      if (!type && cxx_dialect >= cxx17)
+      /* Otherwise, look for a type-name.  */
+      if (!type)
        {
-         if (flags & CP_PARSER_FLAGS_OPTIONAL)
+         if (cxx_dialect >= cxx17)
            cp_parser_parse_tentatively (parser);
 
-         cp_parser_global_scope_opt (parser,
-                                     /*current_scope_valid_p=*/false);
-         cp_parser_nested_name_specifier_opt (parser,
-                                              /*typename_keyword_p=*/false,
-                                              /*check_dependency_p=*/true,
-                                              /*type_p=*/false,
-                                              /*is_declaration=*/false);
+         type = cp_parser_type_name (parser, (qualified_p && typename_p));
+
+         if (cxx_dialect >= cxx17 && !cp_parser_parse_definitely (parser))
+           type = NULL_TREE;
+       }
+
+      if (!type && cxx_dialect >= cxx17)
+       {
+         /* Try class template argument deduction.  */
          tree name = cp_parser_identifier (parser);
          if (name && TREE_CODE (name) == IDENTIFIER_NODE
              && parser->scope != error_mark_node)
@@ -17863,11 +17959,21 @@ cp_parser_simple_type_specifier (cp_parser* parser,
            }
          else
            type = error_mark_node;
-
-         if ((flags & CP_PARSER_FLAGS_OPTIONAL)
-             && !cp_parser_parse_definitely (parser))
-           type = NULL_TREE;
        }
+
+      /* If it didn't work out, we don't have a TYPE.  */
+      if ((flags & CP_PARSER_FLAGS_OPTIONAL)
+         && !cp_parser_parse_definitely (parser))
+       type = NULL_TREE;
+
+      /* Keep track of all name-lookups performed in class scopes.  */
+      if (type
+         && !global_p
+         && !qualified_p
+         && TREE_CODE (type) == TYPE_DECL
+         && identifier_p (DECL_NAME (type)))
+       maybe_note_name_used_in_class (DECL_NAME (type), type);
+
       if (type && decl_specs)
        cp_parser_set_decl_spec_type (decl_specs, type,
                                      token,
@@ -17971,12 +18077,12 @@ cp_parser_type_name (cp_parser* parser, bool typename_keyword_p)
                                         /*is_declaration=*/false);
       /* Note that this must be an instantiation of an alias template
         because [temp.names]/6 says:
-        
+
             A template-id that names an alias template specialization
             is a type-name.
 
         Whereas [temp.names]/7 says:
-        
+
             A simple-template-id that names a class template
             specialization is a class-name.
 
@@ -18127,7 +18233,7 @@ cp_parser_nonclass_name (cp_parser* parser)
   type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
 
   type_decl = strip_using_decl (type_decl);
-  
+
   /* If we found an overload set, then it may refer to a concept-name. */
   if (tree decl = cp_parser_maybe_concept_name (parser, type_decl))
     type_decl = decl;
@@ -18165,7 +18271,7 @@ cp_parser_nonclass_name (cp_parser* parser)
   else if (type_decl != error_mark_node
           && !parser->scope)
     maybe_note_name_used_in_class (identifier, type_decl);
-  
+
   return type_decl;
 }
 
@@ -18330,7 +18436,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       /* If the `typename' keyword is in effect and DECL is not a type
         decl, then type is non existent.   */
       else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
-        ; 
+        ;
       else if (TREE_CODE (decl) == TYPE_DECL)
        {
          type = check_elaborated_type_specifier (tag_type, decl,
@@ -18345,7 +18451,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
            check_unqualified_spec_or_inst (type, token->location);
        }
       else if (decl == error_mark_node)
-       type = error_mark_node; 
+       type = error_mark_node;
     }
 
   if (!type)
@@ -18593,7 +18699,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
      enum-key identifier enum-base [opt] ;
 
    GNU Extensions:
-     enum-key attributes[opt] identifier [opt] enum-base [opt] 
+     enum-key attributes[opt] identifier [opt] enum-base [opt]
        { enumerator-list [opt] }attributes[opt]
      enum-key attributes[opt] identifier [opt] enum-base [opt]
        { enumerator-list, }attributes[opt] [C++0x]
@@ -19172,7 +19278,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   for (;;)
     {
       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)
@@ -19206,7 +19312,7 @@ cp_parser_namespace_definition (cp_parser* parser)
          is_inline |= nested_inline_p;
          break;
        }
-  
+
       if (!nested_definition_count && cxx_dialect < cxx17)
         pedwarn (input_location, OPT_Wpedantic,
                 "nested namespace definitions only available with "
@@ -19225,7 +19331,7 @@ cp_parser_namespace_definition (cp_parser* parser)
 
   if (nested_definition_count && !identifier)
     cp_parser_error (parser, "namespace name required");
-  
+
   if (nested_definition_count && attribs)
     error_at (token->location,
              "a nested namespace definition cannot have attributes");
@@ -19291,7 +19397,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
     return;
   /* Look for the `=' token.  */
   if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
-      && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) 
+      && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
       error_at (token->location, "%<namespace%> definition is not allowed here");
       /* Skip the definition.  */
@@ -19304,6 +19410,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   /* Look for the qualified-namespace-specifier.  */
   namespace_specifier
     = cp_parser_qualified_namespace_specifier (parser);
+  cp_warn_deprecated_use_scopes (namespace_specifier);
   /* Look for the `;' token.  */
   cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
@@ -19341,15 +19448,15 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser)
 
    using-declaration:
      using typename [opt] :: [opt] nested-name-specifier unqualified-id ;
-     using :: unqualified-id ;  
+     using :: unqualified-id ;
 
    access-declaration:
-     qualified-id ;  
+     qualified-id ;
 
    */
 
 static bool
-cp_parser_using_declaration (cp_parser* parser, 
+cp_parser_using_declaration (cp_parser* parser,
                             bool access_declaration_p)
 {
   cp_token *token;
@@ -19370,7 +19477,7 @@ cp_parser_using_declaration (cp_parser* parser,
     {
       /* Look for the `using' keyword.  */
       cp_parser_require_keyword (parser, RID_USING, RT_USING);
-      
+
  again:
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -19418,6 +19525,8 @@ cp_parser_using_declaration (cp_parser* parser,
           && !TYPE_FUNCTION_SCOPE_P (qscope))
     qscope = CP_TYPE_CONTEXT (qscope);
 
+  cp_warn_deprecated_use_scopes (qscope);
+
   if (access_declaration_p && cp_parser_error_occurred (parser))
     /* Something has already gone wrong; there's no need to parse
        further.  Since an error has occurred, the return value of
@@ -19481,24 +19590,7 @@ cp_parser_using_declaration (cp_parser* parser,
            finish_member_declaration (decl);
        }
       else
-       {
-         decl = cp_parser_lookup_name_simple (parser,
-                                              identifier,
-                                              token->location);
-         if (decl == error_mark_node)
-           cp_parser_name_lookup_error (parser, identifier,
-                                        decl, NLE_NULL,
-                                        token->location);
-         else if (check_for_bare_parameter_packs (decl))
-           {
-             cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
-             return false;
-           }
-         else if (!at_namespace_scope_p ())
-           finish_local_using_decl (decl, qscope, identifier);
-         else
-           finish_namespace_using_decl (decl, qscope, identifier);
-       }
+       finish_nonmember_using_decl (qscope, identifier);
     }
 
   if (!access_declaration_p
@@ -19642,7 +19734,7 @@ cp_parser_alias_declaration (cp_parser* parser)
   if (decl == error_mark_node)
     return decl;
 
-  // Attach constraints to the alias declaration.
+  /* Attach constraints to the alias declaration.  */
   if (flag_concepts && current_template_parms)
     {
       tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
@@ -19695,14 +19787,12 @@ cp_parser_using_directive (cp_parser* parser)
                                       /*is_declaration=*/true);
   /* Get the namespace being used.  */
   namespace_decl = cp_parser_namespace_name (parser);
+  cp_warn_deprecated_use_scopes (namespace_decl);
   /* And any specified attributes.  */
   attribs = cp_parser_attributes_opt (parser);
 
   /* Update the symbol table.  */
-  if (namespace_bindings_p ())
-    finish_namespace_using_directive (namespace_decl, attribs);
-  else
-    finish_local_using_directive (namespace_decl, attribs);
+  finish_using_directive (namespace_decl, attribs);
 
   /* Look for the final `;'.  */
   cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
@@ -19753,16 +19843,18 @@ cp_parser_asm_definition (cp_parser* parser)
   bool invalid_inputs_p = false;
   bool invalid_outputs_p = false;
   required_token missing = RT_NONE;
+  location_t asm_loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Look for the `asm' keyword.  */
   cp_parser_require_keyword (parser, RID_ASM, RT_ASM);
 
+  /* In C++2a, unevaluated inline assembly is permitted in constexpr
+     functions.  */
   if (parser->in_function_body
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
-    {
-      error ("%<asm%> in %<constexpr%> function");
-      cp_function_chain->invalid_constexpr = true;
-    }
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && (cxx_dialect < cxx2a))
+    pedwarn (asm_loc, 0, "%<asm%> in %<constexpr%> function only available "
+            "with %<-std=c++2a%> or %<-std=gnu++2a%>");
 
   /* Handle the asm-qualifier-list.  */
   location_t volatile_loc = UNKNOWN_LOCATION;
@@ -19780,14 +19872,15 @@ cp_parser_asm_definition (cp_parser* parser)
          case RID_VOLATILE:
            if (volatile_loc)
              {
-               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               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);
+                 warning_at (loc, 0, "%<asm%> qualifier %qT ignored "
+                             "outside of function body", token->u.value);
                volatile_loc = loc;
              }
            cp_lexer_consume_token (parser->lexer);
@@ -19796,7 +19889,8 @@ cp_parser_asm_definition (cp_parser* parser)
          case RID_INLINE:
            if (inline_loc)
              {
-               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               error_at (loc, "duplicate %<asm%> qualifier %qT",
+                         token->u.value);
                inform (inline_loc, "first seen here");
              }
            else
@@ -19809,7 +19903,8 @@ cp_parser_asm_definition (cp_parser* parser)
          case RID_GOTO:
            if (goto_loc)
              {
-               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               error_at (loc, "duplicate %<asm%> qualifier %qT",
+                         token->u.value);
                inform (goto_loc, "first seen here");
              }
            else
@@ -19821,7 +19916,7 @@ cp_parser_asm_definition (cp_parser* parser)
 
          case RID_CONST:
          case RID_RESTRICT:
-           error_at (loc, "%qT is not an asm qualifier", token->u.value);
+           error_at (loc, "%qT is not an %<asm%> qualifier", token->u.value);
            cp_lexer_consume_token (parser->lexer);
            continue;
 
@@ -19837,7 +19932,7 @@ cp_parser_asm_definition (cp_parser* parser)
 
   if (!parser->in_function_body && (inline_p || goto_p))
     {
-      error_at (first_loc, "asm qualifier outside of function body");
+      error_at (first_loc, "%<asm%> qualifier outside of function body");
       inline_p = goto_p = false;
     }
 
@@ -19965,7 +20060,7 @@ cp_parser_asm_definition (cp_parser* parser)
       /* Create the ASM_EXPR.  */
       if (parser->in_function_body)
        {
-         asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
+         asm_stmt = finish_asm_stmt (asm_loc, volatile_p, string, outputs,
                                      inputs, clobbers, labels, inline_p);
          /* If the extended syntax was not used, mark the ASM_EXPR.  */
          if (!extended_p)
@@ -20219,7 +20314,7 @@ cp_parser_init_declarator (cp_parser* parser,
             on a function-definition.  */
          if (asm_specification)
            error_at (asm_spec_start_token->location,
-                     "an asm-specification is not allowed "
+                     "an %<asm%> specification is not allowed "
                      "on a function-definition");
          if (attributes)
            error_at (attributes_start_token->location,
@@ -20467,6 +20562,8 @@ cp_parser_init_declarator (cp_parser* parser,
      declarations.  */
   if (!member_p && decl && decl != error_mark_node && !range_for_decl_p)
     {
+      int cf = (decl_spec_seq_has_spec_p (decl_specifiers, ds_constinit)
+               ? LOOKUP_CONSTINIT : 0);
       cp_finish_decl (decl,
                      initializer, !is_non_constant_init,
                      asm_specification,
@@ -20475,14 +20572,14 @@ cp_parser_init_declarator (cp_parser* parser,
                         `explicit' constructor is OK.  Otherwise, an
                         `explicit' constructor cannot be used.  */
                      ((is_direct_init || !is_initialized)
-                      ? LOOKUP_NORMAL : LOOKUP_IMPLICIT));
+                      ? LOOKUP_NORMAL : LOOKUP_IMPLICIT) | cf);
     }
   else if ((cxx_dialect != cxx98) && friend_p
           && decl && TREE_CODE (decl) == FUNCTION_DECL)
     /* Core issue #226 (C++0x only): A default template-argument
        shall not be specified in a friend class template
        declaration. */
-    check_default_tmpl_args (decl, current_template_parms, /*is_primary=*/true, 
+    check_default_tmpl_args (decl, current_template_parms, /*is_primary=*/true,
                              /*is_partial=*/false, /*is_friend_decl=*/1);
 
   if (!friend_p && pushed_scope)
@@ -20783,7 +20880,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                  tree tx_qual = cp_parser_tx_qualifier_opt (parser);
                  /* And the exception-specification.  */
                  exception_specification
-                   = cp_parser_exception_specification_opt (parser);
+                   = cp_parser_exception_specification_opt (parser, flags);
 
                  attrs = cp_parser_std_attribute_spec_seq (parser);
 
@@ -21822,7 +21919,7 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
            return error_mark_node;
          }
       }
-  
+
   return groktypename (&type_specifier_seq, abstract_declarator,
                       is_template_arg);
 }
@@ -22427,7 +22524,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
          /* Consume the `...'. */
          cp_lexer_consume_token (parser->lexer);
          maybe_warn_variadic_templates ();
-         
+
          /* Build a pack expansion type */
          if (template_parm_p)
            template_parameter_pack_p = true;
@@ -22454,12 +22551,14 @@ cp_parser_parameter_declaration (cp_parser *parser,
          && !LAMBDA_TYPE_P (current_class_type))
        default_argument = cp_parser_cache_defarg (parser, /*nsdmi=*/false);
 
-      // A constrained-type-specifier may declare a type template-parameter.
+      /* A constrained-type-specifier may declare a type
+        template-parameter.  */
       else if (declares_constrained_type_template_parameter (type))
         default_argument
           = cp_parser_default_type_template_argument (parser);
 
-      // A constrained-type-specifier may declare a template-template-parameter.
+      /* A constrained-type-specifier may declare a
+        template-template-parameter.  */
       else if (declares_constrained_template_template_parameter (type))
         default_argument
           = cp_parser_default_template_template_argument (parser);
@@ -22481,11 +22580,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
               || (decl_specifiers.type
                   && PACK_EXPANSION_P (decl_specifiers.type)))
        {
-         /* Find the name of the parameter pack.  */     
+         /* Find the name of the parameter pack.  */
          cp_declarator *id_declarator = declarator;
          while (id_declarator && id_declarator->kind != cdk_id)
            id_declarator = id_declarator->declarator;
-         
+
          if (id_declarator && id_declarator->kind == cdk_id)
            error_at (declarator_token_start->location,
                      template_parm_p
@@ -22776,7 +22875,7 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
    production is used).  The TREE_TYPE for the CONSTRUCTOR will be
    NULL_TREE.  There is no way to detect whether or not the optional
    trailing `,' was provided.  NON_CONSTANT_P is as for
-   cp_parser_initializer.  */     
+   cp_parser_initializer.  */
 
 static cp_expr
 cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
@@ -22877,7 +22976,7 @@ cp_parser_array_designator_p (cp_parser *parser)
   bool array_designator_p
     = (cp_parser_skip_to_closing_square_bracket (parser)
        && cp_lexer_next_token_is (parser->lexer, CPP_EQ));
-  
+
   /* Roll back the tokens we skipped.  */
   cp_lexer_rollback_tokens (parser->lexer);
 
@@ -23084,7 +23183,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p,
          {
            if (IDENTIFIER_MARKED (designator))
              {
-               error_at (cp_expr_loc_or_loc (val, input_location),
+               error_at (cp_expr_loc_or_input_loc (val),
                          "%<.%s%> designator used multiple times in "
                          "the same initializer list",
                          IDENTIFIER_POINTER (designator));
@@ -23265,7 +23364,7 @@ cp_parser_class_name (cp_parser *parser,
           /* In Objective-C 2.0, a classname followed by '.' starts a
              dot-syntax expression, and it's not a type-name.  */
           || (c_dialect_objc ()
-              && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT 
+              && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
               && objc_is_class_name (decl)))
     decl = error_mark_node;
 
@@ -23277,6 +23376,34 @@ cp_parser_class_name (cp_parser *parser,
   return decl;
 }
 
+/* Make sure that any member-function parameters are in scope.
+   For instance, a function's noexcept-specifier can use the function's
+   parameters:
+
+   struct S {
+     void fn (int p) noexcept(noexcept(p));
+   };
+
+   so we need to make sure name lookup can find them.  This is used
+   when we delay parsing of the noexcept-specifier.  */
+
+static void
+inject_parm_decls (tree decl)
+{
+  begin_scope (sk_function_parms, decl);
+  tree args = DECL_ARGUMENTS (decl);
+
+  do_push_parm_decls (decl, args, /*nonparms=*/NULL);
+}
+
+/* Undo the effects of inject_parm_decls.  */
+
+static void
+pop_injected_parms (void)
+{
+  pop_bindings_and_leave_scope ();
+}
+
 /* Parse a class-specifier.
 
    class-specifier:
@@ -23587,6 +23714,60 @@ cp_parser_class_specifier_1 (cp_parser* parser)
       vec_safe_truncate (unparsed_classes, 0);
       after_nsdmi_defaulted_late_checks (type);
 
+      /* If there are noexcept-specifiers that have not yet been processed,
+        take care of them now.  */
+      class_type = NULL_TREE;
+      pushed_scope = NULL_TREE;
+      FOR_EACH_VEC_SAFE_ELT (unparsed_noexcepts, ix, decl)
+       {
+         tree ctx = DECL_CONTEXT (decl);
+         if (class_type != ctx)
+           {
+             if (pushed_scope)
+               pop_scope (pushed_scope);
+             class_type = ctx;
+             pushed_scope = push_scope (class_type);
+           }
+
+         tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
+         spec = TREE_PURPOSE (spec);
+
+         /* Make sure that any template parameters are in scope.  */
+         maybe_begin_member_template_processing (decl);
+
+         /* Make sure that any member-function parameters are in scope.  */
+         inject_parm_decls (decl);
+
+         /* 'this' is not allowed in static member functions.  */
+         unsigned char local_variables_forbidden_p
+           = parser->local_variables_forbidden_p;
+         if (DECL_THIS_STATIC (decl))
+           parser->local_variables_forbidden_p |= THIS_FORBIDDEN;
+
+         /* Now we can parse the noexcept-specifier.  */
+         spec = cp_parser_late_noexcept_specifier (parser, spec);
+
+         if (spec != error_mark_node)
+           TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec);
+
+         /* Restore the state of local_variables_forbidden_p.  */
+         parser->local_variables_forbidden_p = local_variables_forbidden_p;
+
+         /* The finish_struct call above performed various override checking,
+            but it skipped unparsed noexcept-specifier operands.  Now that we
+            have resolved them, check again.  */
+         noexcept_override_late_checks (type, decl);
+
+         /* Remove any member-function parameters from the symbol table.  */
+         pop_injected_parms ();
+
+         /* Remove any template parameters from the symbol table.  */
+         maybe_end_member_template_processing ();
+       }
+      vec_safe_truncate (unparsed_noexcepts, 0);
+      if (pushed_scope)
+       pop_scope (pushed_scope);
+
       /* Now parse the body of the functions.  */
       if (flag_openmp)
        {
@@ -24166,7 +24347,7 @@ cp_parser_type_parameter_key (cp_parser* parser)
       if (pedantic && tag_type == typename_type && cxx_dialect < cxx17)
        /* typename is not allowed in a template template parameter
           by the standard until C++17.  */
-       pedwarn (token->location, OPT_Wpedantic, 
+       pedwarn (token->location, OPT_Wpedantic,
                 "ISO C++ forbids typename key in template template parameter;"
                 " use %<-std=c++17%> or %<-std=gnu++17%>");
     }
@@ -24255,7 +24436,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
    member-declarator:
      declarator attributes [opt] pure-specifier [opt]
      declarator attributes [opt] constant-initializer [opt]
-     identifier [opt] attributes [opt] : constant-expression  
+     identifier [opt] attributes [opt] : constant-expression
 
    C++0x Extensions:
 
@@ -24566,7 +24747,7 @@ cp_parser_member_declaration (cp_parser* parser)
                    }
                }
              else
-               { 
+               {
                  /* Look for attributes that apply to the bitfield after
                     the `:' token and width.  This is where GCC used to
                     parse attributes in the past, pedwarn if there is
@@ -24604,11 +24785,15 @@ cp_parser_member_declaration (cp_parser* parser)
              tree asm_specification;
              int ctor_dtor_or_conv_p;
              bool static_p = (decl_specifiers.storage_class == sc_static);
+             cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+             if (!friend_p
+                 && !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef))
+               flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT;
 
              /* Parse the declarator.  */
              declarator
                = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
-                                       CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                                       flags,
                                        &ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL,
                                        /*member_p=*/true,
@@ -25142,6 +25327,89 @@ cp_parser_base_specifier (cp_parser* parser)
 
 /* Exception handling [gram.exception] */
 
+/* Save the tokens that make up the noexcept-specifier for a member-function.
+   Returns a DEFERRED_PARSE.  */
+
+static tree
+cp_parser_save_noexcept (cp_parser *parser)
+{
+  cp_token *first = parser->lexer->next_token;
+  /* We want everything up to, including, the final ')'.  */
+  cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0);
+  cp_token *last = parser->lexer->next_token;
+
+  /* As with default arguments and NSDMIs, make use of DEFERRED_PARSE
+     to carry the information we will need.  */
+  tree expr = make_node (DEFERRED_PARSE);
+  /* Save away the noexcept-specifier; we will process it when the
+     class is complete.  */
+  DEFPARSE_TOKENS (expr) = cp_token_cache_new (first, last);
+  expr = build_tree_list (expr, NULL_TREE);
+  return expr;
+}
+
+/* Used for late processing of noexcept-specifiers of member-functions.
+   DEFAULT_ARG is the unparsed operand of a noexcept-specifier which
+   we saved for later; parse it now.  */
+
+static tree
+cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg)
+{
+  /* Make sure we've gotten something that hasn't been parsed yet.  */
+  gcc_assert (TREE_CODE (default_arg) == DEFERRED_PARSE);
+
+  push_unparsed_function_queues (parser);
+
+  /* Push the saved tokens for the noexcept-specifier onto the parser's
+     lexer stack.  */
+  cp_token_cache *tokens = DEFPARSE_TOKENS (default_arg);
+  cp_parser_push_lexer_for_tokens (parser, tokens);
+
+  /* Parse the cached noexcept-specifier.  */
+  tree parsed_arg
+    = cp_parser_noexcept_specification_opt (parser,
+                                           CP_PARSER_FLAGS_NONE,
+                                           /*require_constexpr=*/true,
+                                           /*consumed_expr=*/NULL,
+                                           /*return_cond=*/false);
+
+  /* Revert to the main lexer.  */
+  cp_parser_pop_lexer (parser);
+
+  /* Restore the queue.  */
+  pop_unparsed_function_queues (parser);
+
+  /* And we're done.  */
+  return parsed_arg;
+}
+
+/* Perform late checking of overriding function with respect to their
+   noexcept-specifiers.  TYPE is the class and FNDECL is the function
+   that potentially overrides some virtual function with the same
+   signature.  */
+
+static void
+noexcept_override_late_checks (tree type, tree fndecl)
+{
+  tree binfo = TYPE_BINFO (type);
+  tree base_binfo;
+
+  if (DECL_STATIC_FUNCTION_P (fndecl))
+    return;
+
+  for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+    {
+      tree basetype = BINFO_TYPE (base_binfo);
+
+      if (!TYPE_POLYMORPHIC_P (basetype))
+       continue;
+
+      tree fn = look_for_overrides_here (basetype, fndecl);
+      if (fn)
+       maybe_check_overriding_exception_spec (fndecl, fn);
+    }
+}
+
 /* Parse an (optional) noexcept-specification.
 
    noexcept-specification:
@@ -25152,10 +25420,12 @@ cp_parser_base_specifier (cp_parser* parser)
    expression if parentheses follow noexcept, or return BOOLEAN_TRUE_NODE if
    there are no parentheses.  CONSUMED_EXPR will be set accordingly.
    Otherwise, returns a noexcept specification unless RETURN_COND is true,
-   in which case a boolean condition is returned instead.  */
+   in which case a boolean condition is returned instead.  The parser flags
+   FLAGS is used to control parsing.  */
 
 static tree
 cp_parser_noexcept_specification_opt (cp_parser* parser,
+                                     cp_parser_flags flags,
                                      bool require_constexpr,
                                      bool* consumed_expr,
                                      bool return_cond)
@@ -25170,6 +25440,29 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
   if (cp_parser_is_keyword (token, RID_NOEXCEPT))
     {
       tree expr;
+
+      /* [class.mem]/6 says that a noexcept-specifer (within the
+        member-specification of the class) is a complete-class context of
+        a class.  So, if the noexcept-specifier has the optional expression,
+        just save the tokens, and reparse this after we're done with the
+        class.  */
+      const bool literal_p
+       = ((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
+           || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD))
+          && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN));
+
+      if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
+         /* No need to delay parsing for a number literal or true/false.  */
+         && !literal_p
+         && at_class_scope_p ()
+         /* We don't delay parsing for friend member functions,
+            alias-declarations, and typedefs, even though the standard seems
+            to require it.  */
+         && (flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT)
+         && TYPE_BEING_DEFINED (current_class_type)
+         && !LAMBDA_TYPE_P (current_class_type))
+       return cp_parser_save_noexcept (parser);
+
       cp_lexer_consume_token (parser->lexer);
 
       if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
@@ -25240,10 +25533,11 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
      throw ( type-id-list [opt] )
 
    Returns a TREE_LIST representing the exception-specification.  The
-   TREE_VALUE of each node is a type.  */
+   TREE_VALUE of each node is a type.  The parser flags FLAGS is used to
+   control parsing.  */
 
 static tree
-cp_parser_exception_specification_opt (cp_parser* parser)
+cp_parser_exception_specification_opt (cp_parser* parser, cp_parser_flags flags)
 {
   cp_token *token;
   tree type_id_list;
@@ -25253,8 +25547,11 @@ cp_parser_exception_specification_opt (cp_parser* parser)
   token = cp_lexer_peek_token (parser->lexer);
 
   /* Is it a noexcept-specification?  */
-  type_id_list = cp_parser_noexcept_specification_opt (parser, true, NULL,
-                                                      false);
+  type_id_list
+    = cp_parser_noexcept_specification_opt (parser, flags,
+                                           /*require_constexpr=*/true,
+                                           /*consumed_expr=*/NULL,
+                                           /*return_cond=*/false);
   if (type_id_list != NULL_TREE)
     return type_id_list;
 
@@ -25641,8 +25938,8 @@ cp_parser_asm_operand_list (cp_parser* parser)
       /* Look for the `)'.  */
       parens.require_close (parser);
 
-      if (name == error_mark_node 
-         || string_literal == error_mark_node 
+      if (name == error_mark_node
+         || string_literal == error_mark_node
          || expression == error_mark_node)
         invalid_operands = true;
 
@@ -25925,7 +26222,7 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
 
          /* Save away the identifier that indicates which attribute
             this is.  */
-         identifier = (token->type == CPP_KEYWORD) 
+         identifier = (token->type == CPP_KEYWORD)
            /* For keywords, use the canonical spelling, not the
               parsed identifier.  */
            ? ridpointers[(int) token->keyword]
@@ -25942,9 +26239,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
              vec<tree, va_gc> *vec;
              int attr_flag = (attribute_takes_identifier_p (identifier)
                               ? id_attr : normal_attr);
-             vec = cp_parser_parenthesized_expression_list 
-                   (parser, attr_flag, /*cast_p=*/false, 
-                   /*allow_expansion_p=*/false, 
+             vec = cp_parser_parenthesized_expression_list
+                   (parser, attr_flag, /*cast_p=*/false,
+                   /*allow_expansion_p=*/false,
                    /*non_constant_p=*/NULL);
              if (vec == NULL)
                arguments = error_mark_node;
@@ -26088,11 +26385,11 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
       attr_id = canonicalize_attr_name (attr_id);
       attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
                                   NULL_TREE);
-      /* C++11 noreturn attribute is equivalent to GNU's.  */
-      if (is_attribute_p ("noreturn", attr_id))
-       TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier;
+      /* We used to treat C++11 noreturn attribute as equivalent to GNU's,
+        but no longer: we have to be able to tell [[noreturn]] and
+        __attribute__((noreturn)) apart.  */
       /* C++14 deprecated attribute is equivalent to GNU's.  */
-      else if (is_attribute_p ("deprecated", attr_id))
+      if (is_attribute_p ("deprecated", attr_id))
        TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier;
       /* C++17 fallthrough attribute is equivalent to GNU's.  */
       else if (is_attribute_p ("fallthrough", attr_id))
@@ -26116,6 +26413,20 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
     vec<tree, va_gc> *vec;
     int attr_flag = normal_attr;
 
+    /* Maybe we don't expect to see any arguments for this attribute.  */
+    const attribute_spec *as
+      = lookup_attribute_spec (TREE_PURPOSE (attribute));
+    if (as && as->max_length == 0)
+      {
+       error_at (token->location, "%qE attribute does not take any arguments",
+                 attr_id);
+       cp_parser_skip_to_closing_parenthesis (parser,
+                                              /*recovering=*/true,
+                                              /*or_comma=*/false,
+                                              /*consume_paren=*/true);
+       return error_mark_node;
+      }
+
     if (attr_ns == gnu_identifier
        && attribute_takes_identifier_p (attr_id))
       /* A GNU attribute that takes an identifier in parameter.  */
@@ -26324,6 +26635,12 @@ cp_parser_std_attribute_spec (cp_parser *parser)
       if (alignas_expr == error_mark_node)
        return error_mark_node;
 
+      /* Missing ')' means the code cannot possibly be valid; go ahead
+        and commit to make sure we issue a hard error.  */
+      if (cp_parser_uncommitted_to_tentative_parse_p (parser)
+         && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+       cp_parser_commit_to_tentative_parse (parser);
+
       if (!parens.require_close (parser))
        return error_mark_node;
 
@@ -27277,7 +27594,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
            template_id_p = true;
          }
 
-       return cp_parser_check_template_parameters 
+       return cp_parser_check_template_parameters
          (parser, num_templates, template_id_p, declarator_location,
           declarator);
       }
@@ -27329,14 +27646,14 @@ cp_parser_check_template_parameters (cp_parser* parser,
     {
       if (declarator && !current_function_decl)
        error_at (location, "specializing member %<%T::%E%> "
-                 "requires %<template<>%> syntax", 
+                 "requires %<template<>%> syntax",
                  declarator->u.id.qualifying_scope,
                  declarator->u.id.unqualified_name);
       else if (declarator)
        error_at (location, "invalid declaration of %<%T::%E%>",
                  declarator->u.id.qualifying_scope,
                  declarator->u.id.unqualified_name);
-      else 
+      else
        error_at (location, "too few template-parameter-lists");
       return false;
     }
@@ -27539,7 +27856,9 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
          /* A parameter declaration begins with a decl-specifier,
             which is either the "attribute" keyword, a storage class
             specifier, or (usually) a type-specifier.  */
-         && !cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
+         && !cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer)
+         /* A parameter declaration can also begin with [[attribute]].  */
+         && !cp_next_tokens_can_be_std_attribute_p (parser))
        {
          tree type;
          tree pushed_scope = NULL_TREE;
@@ -27572,9 +27891,19 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
          parser->num_template_parameter_lists = 0;
 
          /* Look for the type-specifier.  It's not optional, but its typename
-            might be.  */
+            might be.  Unless this is a friend declaration; we don't want to
+            treat
+
+              friend S (T::fn)(int);
+
+            as a constructor, but with P0634, we might assume a type when
+            looking for the type-specifier.  It is actually a function named
+            `T::fn' that takes one parameter (of type `int') and returns a
+            value of type `S'.  Constructors can be friends, but they must
+            use a qualified name.  */
          cp_parser_type_specifier (parser,
-                                   (flags & ~CP_PARSER_FLAGS_OPTIONAL),
+                                   (friend_p ? CP_PARSER_FLAGS_NONE
+                                    : (flags & ~CP_PARSER_FLAGS_OPTIONAL)),
                                    /*decl_specs=*/NULL,
                                    /*is_declarator=*/true,
                                    /*declares_class_or_enum=*/NULL,
@@ -27844,7 +28173,10 @@ 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 (CLASS_TYPE_P (TREE_TYPE (parm)))
+             if (TREE_CODE (parm) != PARM_DECL)
+               ok = false;
+             else if (MAYBE_CLASS_TYPE_P (TREE_TYPE (parm))
+                      && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (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.  */;
@@ -27858,7 +28190,7 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
              tree type = INNERMOST_TEMPLATE_PARMS (parm_type);
              tree parm_list = TREE_VEC_ELT (parameter_list, 1);
              tree parm = INNERMOST_TEMPLATE_PARMS (parm_list);
-             if (parm == error_mark_node
+             if (TREE_CODE (parm) != PARM_DECL
                  || TREE_TYPE (parm) != TREE_TYPE (type)
                  || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
                ok = false;
@@ -27874,14 +28206,16 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
       if (!ok)
        {
          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);
+           error_at (DECL_SOURCE_LOCATION (decl), "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 parameter pack <char...>",
-                  decl);
+           error_at (DECL_SOURCE_LOCATION (decl), "literal operator "
+                     "template %qD has invalid parameter list; expected "
+                     "non-type template parameter pack %<<char...>%>",
+                     decl);
        }
     }
 
@@ -28143,9 +28477,9 @@ cp_parser_single_declaration (cp_parser* parser,
       if (cp_parser_declares_only_class_p (parser)
          || (declares_class_or_enum & 2))
        {
-         // If this is a declaration, but not a definition, associate
-         // any constraints with the type declaration. Constraints
-         // are associated with definitions in cp_parser_class_specifier.
+         /* If this is a declaration, but not a definition, associate
+            any constraints with the type declaration. Constraints
+            are associated with definitions in cp_parser_class_specifier.  */
          if (declares_class_or_enum == 1)
            associate_classtype_constraints (decl_specifiers.type);
 
@@ -28294,10 +28628,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
            ^~~~~~~~~~~~~~~
         with caret == start at the start of the type name,
         finishing at the closing brace.  */
-      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);
+                                              parser->lexer);
       cast.set_location (combined_loc);
       return cast;
    }
@@ -28332,9 +28664,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
        ^~~~~~~~
      with caret == start at the start of the type name,
      finishing at the closing paren.  */
-  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);
+  location_t combined_loc = make_location (start_loc, start_loc, parser->lexer);
   cast.set_location (combined_loc);
   return cast;
 }
@@ -28370,7 +28700,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
       return error_mark_node;
     }
 
-  /* Remember it, if there default args to post process.  */
+  /* Remember it, if there are default args to post process.  */
   cp_parser_save_default_args (parser, fn);
 
   /* Save away the tokens that make up the body of the
@@ -28451,7 +28781,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
 }
 
 /* Save the tokens that make up the in-class initializer for a non-static
-   data member.  Returns a DEFAULT_ARG.  */
+   data member.  Returns a DEFERRED_PARSE.  */
 
 static tree
 cp_parser_save_nsdmi (cp_parser* parser)
@@ -28663,6 +28993,11 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
        vec_safe_push (unparsed_funs_with_default_args, entry);
        break;
       }
+
+  /* Remember if there is a noexcept-specifier to post process.  */
+  tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
+  if (UNPARSED_NOEXCEPT_SPEC_P (spec))
+    vec_safe_push (unparsed_noexcepts, decl);
 }
 
 /* DEFAULT_ARG contains the saved tokens for the initializer of DECL,
@@ -28683,7 +29018,7 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
 
   /* Push the saved tokens for the default argument onto the parser's
      lexer stack.  */
-  tokens = DEFARG_TOKENS (default_arg);
+  tokens = DEFPARSE_TOKENS (default_arg);
   cp_parser_push_lexer_for_tokens (parser, tokens);
 
   start_lambda_scope (decl);
@@ -28750,7 +29085,7 @@ cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field)
 }
 
 /* FN is a FUNCTION_DECL which may contains a parameter with an
-   unparsed DEFAULT_ARG.  Parse the default args now.  This function
+   unparsed DEFERRED_PARSE.  Parse the default args now.  This function
    assumes that the current scope is the scope in which the default
    argument should be processed.  */
 
@@ -28788,7 +29123,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       if (!default_arg)
        continue;
 
-      if (TREE_CODE (default_arg) != DEFAULT_ARG)
+      if (TREE_CODE (default_arg) != DEFERRED_PARSE)
        /* This can happen for a friend declaration for a function
           already declared with default arguments.  */
        continue;
@@ -28800,7 +29135,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       TREE_PURPOSE (parm) = parsed_arg;
 
       /* Update any instantiations we've already created.  */
-      for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0;
+      for (insts = DEFPARSE_INSTANTIATIONS (default_arg), ix = 0;
           vec_safe_iterate (insts, ix, &copy); ix++)
        TREE_PURPOSE (copy) = parsed_arg;
     }
@@ -28873,7 +29208,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 {
   tree expr = NULL_TREE;
   const char *saved_message;
-  char *tmp;
+  const char *saved_message_arg;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
 
@@ -28886,11 +29221,11 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   /* Types cannot be defined in a `sizeof' expression.  Save away the
      old message.  */
   saved_message = parser->type_definition_forbidden_message;
-  /* And create the new one.  */
-  tmp = concat ("types may not be defined in %<",
-               IDENTIFIER_POINTER (ridpointers[keyword]),
-               "%> expressions", NULL);
-  parser->type_definition_forbidden_message = tmp;
+  saved_message_arg = parser->type_definition_forbidden_message_arg;
+  parser->type_definition_forbidden_message
+    = G_("types may not be defined in %qs expressions");
+  parser->type_definition_forbidden_message_arg
+    = IDENTIFIER_POINTER (ridpointers[keyword]);
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
@@ -28909,6 +29244,8 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
     {
       tree type = NULL_TREE;
 
+      tentative_firewall firewall (parser);
+
       /* We can't be sure yet whether we're looking at a type-id or an
         expression.  */
       cp_parser_parse_tentatively (parser);
@@ -28936,21 +29273,24 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
       /* If all went well, then we're done.  */
       if (cp_parser_parse_definitely (parser))
        expr = type;
-    }
+      else
+       {
+         /* Commit to the tentative_firewall so we get syntax errors.  */
+         cp_parser_commit_to_tentative_parse (parser);
 
-  /* If the type-id production did not work out, then we must be
-     looking at the unary-expression production.  */
-  if (!expr)
+         expr = cp_parser_unary_expression (parser);
+       }
+    }
+  else
     expr = cp_parser_unary_expression (parser);
 
   /* 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->type_definition_forbidden_message_arg = saved_message_arg;
   parser->integral_constant_expression_p
     = saved_integral_constant_expression_p;
   parser->non_integral_constant_expression_p
@@ -29024,8 +29364,8 @@ cp_parser_set_storage_class (cp_parser *parser,
   decl_specs->storage_class = storage_class;
   set_and_check_decl_spec_loc (decl_specs, ds_storage_class, token);
 
-  /* A storage class specifier cannot be applied alongside a typedef 
-     specifier. If there is a typedef specifier present then set 
+  /* A storage class specifier cannot be applied alongside a typedef
+     specifier. If there is a typedef specifier present then set
      conflicting_specifiers_p which will trigger an error later
      on in grokdeclarator. */
   if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef))
@@ -29132,7 +29472,7 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
            {
              decl_specs->locations[ds_long_long] = location;
              pedwarn_cxx98 (location,
-                            OPT_Wlong_long, 
+                            OPT_Wlong_long,
                             "ISO C++ 1998 does not support %<long long%>");
            }
        }
@@ -29169,7 +29509,8 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
            "typedef",
            "using",
             "constexpr",
-           "__complex"
+           "__complex",
+           "constinit"
          };
          gcc_rich_location richloc (location);
          richloc.add_fixit_remove ();
@@ -29560,7 +29901,7 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
   cp_token *token;
 
   token = cp_lexer_peek_token (parser->lexer);
-  return (token->type == CPP_COMMA 
+  return (token->type == CPP_COMMA
           || token->type == CPP_GREATER
           || token->type == CPP_ELLIPSIS
          || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT));
@@ -29962,22 +30303,22 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
       token = cp_lexer_consume_token (parser->lexer);
     }
 
-  /* Create a DEFAULT_ARG to represent the unparsed default
+  /* Create a DEFERRED_PARSE to represent the unparsed default
      argument.  */
-  default_argument = make_node (DEFAULT_ARG);
-  DEFARG_TOKENS (default_argument)
+  default_argument = make_node (DEFERRED_PARSE);
+  DEFPARSE_TOKENS (default_argument)
     = cp_token_cache_new (first_token, token);
-  DEFARG_INSTANTIATIONS (default_argument) = NULL;
+  DEFPARSE_INSTANTIATIONS (default_argument) = NULL;
 
   return default_argument;
 }
 
-/* A location to use for diagnostics about an unparsed DEFAULT_ARG.  */
+/* A location to use for diagnostics about an unparsed DEFERRED_PARSE.  */
 
 location_t
-defarg_location (tree default_argument)
+defparse_location (tree default_argument)
 {
-  cp_token_cache *tokens = DEFARG_TOKENS (default_argument);
+  cp_token_cache *tokens = DEFPARSE_TOKENS (default_argument);
   location_t start = tokens->first->location;
   location_t end = tokens->last->location;
   return make_location (start, start, end);
@@ -30245,7 +30586,7 @@ cp_parser_objc_message_receiver (cp_parser* parser)
 
   if (cp_parser_parse_definitely (parser))
     return objc_get_class_reference (rcv);
-  
+
   cp_parser_error (parser, "objective-c++ message receiver expected");
   return error_mark_node;
 }
@@ -30346,7 +30687,7 @@ cp_parser_objc_encode_expression (cp_parser* parser)
 
   if (!type)
     {
-      error_at (token->location, 
+      error_at (token->location,
                "%<@encode%> must specify a type as an argument");
       return error_mark_node;
     }
@@ -30369,9 +30710,7 @@ cp_parser_objc_encode_expression (cp_parser* parser)
        @encode(int)
        ^~~~~~~~~~~~
      with caret==start at the @ token, finishing at the close paren.  */
-  location_t combined_loc
-    = make_location (start_loc, start_loc,
-                     cp_lexer_previous_token (parser->lexer)->location);
+  location_t combined_loc = make_location (start_loc, start_loc, parser->lexer);
 
   return cp_expr (objc_build_encode_expr (type), combined_loc);
 }
@@ -30415,9 +30754,7 @@ cp_parser_objc_protocol_expression (cp_parser* parser)
        @protocol(prot)
        ^~~~~~~~~~~~~~~
      with caret==start at the @ token, finishing at the close paren.  */
-  location_t combined_loc
-    = make_location (start_loc, start_loc,
-                     cp_lexer_previous_token (parser->lexer)->location);
+  location_t combined_loc = make_location (start_loc, start_loc, parser->lexer);
   tree result = objc_build_protocol_expr (proto);
   protected_set_expr_location (result, combined_loc);
   return result;
@@ -30502,9 +30839,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
        @selector(func)
        ^~~~~~~~~~~~~~~
      with caret==start at the @ token, finishing at the close paren.  */
-  location_t combined_loc
-    = make_location (loc, loc,
-                     cp_lexer_previous_token (parser->lexer)->location);
+  location_t combined_loc = make_location (loc, loc, parser->lexer);
   tree result = objc_build_selector_expr (combined_loc, sel_seq);
   /* TODO: objc_build_selector_expr doesn't always honor the location.  */
   protected_set_expr_location (result, combined_loc);
@@ -30528,7 +30863,7 @@ cp_parser_objc_identifier_list (cp_parser* parser)
 
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
-    return error_mark_node;      
+    return error_mark_node;
 
   list = build_tree_list (NULL_TREE, identifier);
   sep = cp_lexer_peek_token (parser->lexer);
@@ -30544,7 +30879,7 @@ cp_parser_objc_identifier_list (cp_parser* parser)
                                             identifier));
       sep = cp_lexer_peek_token (parser->lexer);
     }
-  
+
   return list;
 }
 
@@ -30583,11 +30918,11 @@ cp_parser_objc_class_declaration (cp_parser* parser)
   while (true)
     {
       tree id;
-      
+
       id = cp_parser_identifier (parser);
       if (id == error_mark_node)
        break;
-      
+
       objc_declare_class (id);
 
       if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
@@ -30711,7 +31046,7 @@ cp_parser_objc_typename (cp_parser* parser)
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
        {
          cp_type = cp_parser_type_id (parser);
-         
+
          /* If the type could not be parsed, an error has already
             been produced.  For error recovery, behave as if it had
             not been specified, which will use the default type
@@ -30843,7 +31178,7 @@ cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
          || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
        return params;
-      cp_parser_error (parser, 
+      cp_parser_error (parser,
                       "method attributes must be specified at the end");
       return error_mark_node;
     }
@@ -30859,7 +31194,7 @@ cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
 /* Parse the non-keyword Objective-C params.  */
 
 static tree
-cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, 
+cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
                                       tree* attributes)
 {
   tree params = make_node (TREE_LIST);
@@ -30904,12 +31239,12 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
              || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
            return params;
        }
-      else        
-       /* We have an error, but parse the attributes, so that we can 
+      else
+       /* We have an error, but parse the attributes, so that we can
           carry on.  */
        *attributes = cp_parser_attributes_opt (parser);
 
-      cp_parser_error (parser, 
+      cp_parser_error (parser,
                       "method attributes must be specified at the end");
       return error_mark_node;
     }
@@ -30986,11 +31321,11 @@ cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
 static bool
 cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
 {
-  tree tattr;  
+  tree tattr;
   cp_lexer_save_tokens (parser->lexer);
   tattr = cp_parser_attributes_opt (parser);
   gcc_assert (tattr) ;
-  
+
   /* If the attributes are followed by a method introducer, this is not allowed.
      Dump the attributes and flag the situation.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
@@ -31000,7 +31335,7 @@ cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
   /* Otherwise, the attributes introduce some interstitial code, possibly so
      rewind to allow that check.  */
   cp_lexer_rollback_tokens (parser->lexer);
-  return false;  
+  return false;
 }
 
 /* Parse an Objective-C method prototype list.  */
@@ -31032,10 +31367,10 @@ cp_parser_objc_method_prototype_list (cp_parser* parser)
        }
       else if (token->keyword == RID_AT_PROPERTY)
        cp_parser_objc_at_property_declaration (parser);
-      else if (token->keyword == RID_ATTRIBUTE 
+      else if (token->keyword == RID_ATTRIBUTE
               && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
-       warning_at (cp_lexer_peek_token (parser->lexer)->location, 
-                   OPT_Wattributes, 
+       warning_at (cp_lexer_peek_token (parser->lexer)->location,
+                   OPT_Wattributes,
                    "prefix attributes are ignored for methods");
       else
        /* Allow for interspersed non-ObjC++ code.  */
@@ -31088,7 +31423,7 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
            cp_lexer_consume_token (parser->lexer);
 
          ptk = cp_lexer_peek_token (parser->lexer);
-         if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS 
+         if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS
                || ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
            {
              perform_deferred_access_checks (tf_warning_or_error);
@@ -31107,7 +31442,7 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
        cp_parser_objc_at_synthesize_declaration (parser);
       else if (token->keyword == RID_AT_DYNAMIC)
        cp_parser_objc_at_dynamic_declaration (parser);
-      else if (token->keyword == RID_ATTRIBUTE 
+      else if (token->keyword == RID_ATTRIBUTE
               && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
        warning_at (token->location, OPT_Wattributes,
                    "prefix attributes are ignored for methods");
@@ -31139,7 +31474,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '{'.  */
   token = cp_lexer_peek_token (parser->lexer);
 
-  while (token->type != CPP_CLOSE_BRACE 
+  while (token->type != CPP_CLOSE_BRACE
        && token->keyword != RID_AT_END && token->type != CPP_EOF)
     {
       cp_decl_specifier_seq declspecs;
@@ -31159,7 +31494,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
       /* auto, register, static, extern, mutable.  */
       if (declspecs.storage_class != sc_none)
        {
-         cp_parser_error (parser, "invalid type for instance variable");         
+         cp_parser_error (parser, "invalid type for instance variable");
          declspecs.storage_class = sc_none;
        }
 
@@ -31169,7 +31504,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
          cp_parser_error (parser, "invalid type for instance variable");
          declspecs.locations[ds_thread] = 0;
        }
-      
+
       /* typedef.  */
       if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef))
        {
@@ -31269,10 +31604,10 @@ cp_parser_objc_class_ivars (cp_parser* parser)
     cp_parser_error (parser, "expected %<}%>");
 
   /* Do not consume the RID_AT_END, so it will be read again as terminating
-     the @interface of @implementation.  */ 
+     the @interface of @implementation.  */
   if (token->keyword != RID_AT_END && token->type != CPP_EOF)
     cp_lexer_consume_token (parser->lexer);  /* Eat '}'.  */
-    
+
   /* For historical reasons, we accept an optional semicolon.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
     cp_lexer_consume_token (parser->lexer);
@@ -31304,13 +31639,13 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
       while (true)
        {
          tree id;
-         
+
          id = cp_parser_identifier (parser);
          if (id == error_mark_node)
            break;
-         
+
          objc_declare_protocol (id, attributes);
-         
+
          if(cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
            cp_lexer_consume_token (parser->lexer);
          else
@@ -31332,7 +31667,7 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
 /* Parse an Objective-C superclass or category.  */
 
 static void
-cp_parser_objc_superclass_or_category (cp_parser *parser, 
+cp_parser_objc_superclass_or_category (cp_parser *parser,
                                       bool iface_p,
                                       tree *super,
                                       tree *categ, bool *is_class_extension)
@@ -31527,7 +31862,7 @@ cp_parser_objc_declaration (cp_parser* parser, tree attributes)
    Returns NULL_TREE.
 
    PS: This function is identical to c_parser_objc_try_catch_finally_statement
-   for C.  Keep them in sync.  */   
+   for C.  Keep them in sync.  */
 
 static tree
 cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
@@ -31592,7 +31927,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
             going.  */
          if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
            cp_lexer_consume_token (parser->lexer);
-         
+
          /* If these is no immediate closing parenthesis, the user
             probably doesn't know that parenthesis are required at
             all (ie, they typed "@catch NSException *e").  So, just
@@ -31694,9 +32029,9 @@ cp_parser_objc_statement (cp_parser * parser)
   return error_mark_node;
 }
 
-/* If we are compiling ObjC++ and we see an __attribute__ we neeed to 
+/* If we are compiling ObjC++ and we see an __attribute__ we neeed to
    look ahead to see if an objc keyword follows the attributes.  This
-   is to detect the use of prefix attributes on ObjC @interface and 
+   is to detect the use of prefix attributes on ObjC @interface and
    @protocol.  */
 
 static bool
@@ -31711,7 +32046,7 @@ cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
       return true;
     }
   cp_lexer_rollback_tokens (parser->lexer);
-  return false;  
+  return false;
 }
 
 /* This routine is a minimal replacement for
@@ -31748,14 +32083,14 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
       cp_parser_error (parser, "invalid type for property");
       declspecs.storage_class = sc_none;
     }
-  
+
   /* thread_local.  */
   if (decl_spec_seq_has_spec_p (&declspecs, ds_thread))
     {
       cp_parser_error (parser, "invalid type for property");
       declspecs.locations[ds_thread] = 0;
     }
-  
+
   /* typedef.  */
   if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef))
     {
@@ -31792,7 +32127,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
 
       if (decl == error_mark_node || decl == NULL_TREE)
        return error_mark_node;
-      
+
       /* Reset PREFIX_ATTRIBUTES.  */
       if (attributes != error_mark_node)
        {
@@ -31847,7 +32182,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
 
    PS: This function is identical to
    c_parser_objc_at_property_declaration for C.  Keep them in sync.  */
-static void 
+static void
 cp_parser_objc_at_property_declaration (cp_parser *parser)
 {
   /* The following variables hold the attributes of the properties as
@@ -31998,7 +32333,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
       /* Comma-separated properties are chained together in
         reverse order; add them one by one.  */
       properties = nreverse (properties);
-      
+
       for (; properties; properties = TREE_CHAIN (properties))
        objc_add_property_declaration (loc, copy_node (properties),
                                       property_readonly, property_readwrite,
@@ -32006,7 +32341,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                                       property_copy, property_nonatomic,
                                       property_getter_ident, property_setter_ident);
     }
-  
+
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 }
 
@@ -32030,7 +32365,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
   PS: This function is identical to c_parser_objc_at_synthesize_declaration
   for C.  Keep them in sync.
 */
-static void 
+static void
 cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
 {
   tree list = NULL_TREE;
@@ -32081,7 +32416,7 @@ cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
   PS: This function is identical to c_parser_objc_at_dynamic_declaration
   for C.  Keep them in sync.
 */
-static void 
+static void
 cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
 {
   tree list = NULL_TREE;
@@ -32146,6 +32481,10 @@ cp_parser_omp_clause_name (cp_parser *parser)
          else if (!strcmp ("async", p))
            result = PRAGMA_OACC_CLAUSE_ASYNC;
          break;
+       case 'b':
+         if (!strcmp ("bind", p))
+           result = PRAGMA_OMP_CLAUSE_BIND;
+         break;
        case 'c':
          if (!strcmp ("collapse", p))
            result = PRAGMA_OMP_CLAUSE_COLLAPSE;
@@ -32171,6 +32510,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
          else if (!strcmp ("device_resident", p))
            result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
+         else if (!strcmp ("device_type", p))
+           result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
          else if (!strcmp ("dist_schedule", p))
            result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
          break;
@@ -32245,6 +32586,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
        case 'o':
          if (!strcmp ("ordered", p))
            result = PRAGMA_OMP_CLAUSE_ORDERED;
+         else if (!strcmp ("order", p))
+           result = PRAGMA_OMP_CLAUSE_ORDER;
          break;
        case 'p':
          if (!strcmp ("parallel", p))
@@ -32311,6 +32654,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OMP_CLAUSE_UNTIED;
          else if (!strcmp ("use_device", p))
            result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
+         else if (!strcmp ("use_device_addr", p))
+           result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
          else if (!strcmp ("use_device_ptr", p))
            result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
          break;
@@ -32341,14 +32686,8 @@ static void
 check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
                           const char *name, location_t location)
 {
-  tree c;
-
-  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
-    if (OMP_CLAUSE_CODE (c) == code)
-      {
-       error_at (location, "too many %qs clauses", name);
-       break;
-      }
+  if (omp_find_clause (clauses, code))
+    error_at (location, "too many %qs clauses", name);
 }
 
 /* OpenMP 2.5:
@@ -32864,7 +33203,7 @@ cp_parser_oacc_clause_tile (cp_parser *parser, location_t clause_loc, tree list)
     {
       if (tile && !cp_parser_require (parser, CPP_COMMA, RT_COMMA))
        return list;
-      
+
       if (cp_lexer_next_token_is (parser->lexer, CPP_MULT)
          && (cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA)
              || cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN)))
@@ -33238,8 +33577,8 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
              case OMP_TARGET_DATA: p = "target data"; break;
              case OMP_TARGET: p = "target"; break;
              case OMP_TARGET_UPDATE: p = "target update"; break;
-             case OMP_TARGET_ENTER_DATA: p = "enter data"; break;
-             case OMP_TARGET_EXIT_DATA: p = "exit data"; break;
+             case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
+             case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
              default: gcc_unreachable ();
              }
            error_at (location, "too many %<if%> clauses with %qs modifier",
@@ -33636,6 +33975,100 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
   return list;
 }
 
+/* OpenMP 5.0:
+   order ( concurrent ) */
+
+static tree
+cp_parser_omp_clause_order (cp_parser *parser, tree list, location_t location)
+{
+  tree c, id;
+  const char *p;
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return list;
+
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      cp_parser_error (parser, "expected %<concurrent%>");
+      goto out_err;
+    }
+  else
+    {
+      id = cp_lexer_peek_token (parser->lexer)->u.value;
+      p = IDENTIFIER_POINTER (id);
+    }
+  if (strcmp (p, "concurrent") != 0)
+    {
+      cp_parser_error (parser, "expected %<concurrent%>");
+      goto out_err;
+    }
+  cp_lexer_consume_token (parser->lexer);
+  if (!parens.require_close (parser))
+    goto out_err;
+
+  /* check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order", location); */
+  c = build_omp_clause (location, OMP_CLAUSE_ORDER);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+
+ out_err:
+  cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                        /*or_comma=*/false,
+                                        /*consume_paren=*/true);
+  return list;
+}
+
+/* OpenMP 5.0:
+   bind ( teams | parallel | thread ) */
+
+static tree
+cp_parser_omp_clause_bind (cp_parser *parser, tree list,
+                          location_t location)
+{
+  tree c;
+  const char *p;
+  enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return list;
+
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+    invalid:
+      cp_parser_error (parser,
+                      "expected %<teams%>, %<parallel%> or %<thread%>");
+      goto out_err;
+    }
+  else
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      p = IDENTIFIER_POINTER (id);
+    }
+  if (strcmp (p, "teams") == 0)
+    kind = OMP_CLAUSE_BIND_TEAMS;
+  else if (strcmp (p, "parallel") == 0)
+    kind = OMP_CLAUSE_BIND_PARALLEL;
+  else if (strcmp (p, "thread") != 0)
+    goto invalid;
+  cp_lexer_consume_token (parser->lexer);
+  if (!parens.require_close (parser))
+    goto out_err;
+
+  /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind", location); */
+  c = build_omp_clause (location, OMP_CLAUSE_BIND);
+  OMP_CLAUSE_BIND_KIND (c) = kind;
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+
+ out_err:
+  cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                        /*or_comma=*/false,
+                                        /*consume_paren=*/true);
+  return list;
+}
+
 /* OpenMP 2.5:
    ordered
 
@@ -33735,11 +34168,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
          if (strcmp (p, "task") == 0)
            task = true;
          else if (strcmp (p, "inscan") == 0)
-           {
-             inscan = true;
-             sorry ("%<inscan%> modifier on %<reduction%> clause "
-                    "not supported yet");
-           }
+           inscan = true;
          if (task || inscan)
            {
              cp_lexer_consume_token (parser->lexer);
@@ -34193,7 +34622,7 @@ cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list)
    linear ( modifier ( variable-list ) : expression ) */
 
 static tree
-cp_parser_omp_clause_linear (cp_parser *parser, tree list, 
+cp_parser_omp_clause_linear (cp_parser *parser, tree list,
                             bool declare_simd)
 {
   tree nlist, c, step = integer_one_node;
@@ -34825,8 +35254,10 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list,
   else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
     goto resync_fail;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, "dist_schedule",
-                            location);
+  /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
+                               "dist_schedule", location); */
+  if (omp_find_clause (list, OMP_CLAUSE_DIST_SCHEDULE))
+    warning_at (location, 0, "too many %qs clauses", "dist_schedule");
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -34892,6 +35323,56 @@ cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list,
   return list;
 }
 
+/* OpenMP 5.0:
+   device_type ( host | nohost | any )  */
+
+static tree
+cp_parser_omp_clause_device_type (cp_parser *parser, tree list,
+                                 location_t location)
+{
+  tree c;
+  enum omp_clause_device_type_kind kind;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return list;
+
+  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 ("host", p) == 0)
+       kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
+      else if (strcmp ("nohost", p) == 0)
+       kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
+      else if (strcmp ("any", p) == 0)
+       kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
+      else
+       goto invalid_kind;
+    }
+  else
+    goto invalid_kind;
+
+  cp_lexer_consume_token (parser->lexer);
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
+    goto resync_fail;
+
+  c = build_omp_clause (location, OMP_CLAUSE_DEVICE_TYPE);
+  /* check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE, "device_type",
+                               location);  */
+  OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+
+ invalid_kind:
+  cp_parser_error (parser, "invalid depend kind");
+ resync_fail:
+  cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                        /*or_comma=*/false,
+                                        /*consume_paren=*/true);
+  return list;
+}
+
 /* OpenACC:
    async [( int-expr )] */
 
@@ -35157,6 +35638,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 
       switch (c_kind)
        {
+       case PRAGMA_OMP_CLAUSE_BIND:
+         clauses = cp_parser_omp_clause_bind (parser, clauses,
+                                              token->location);
+         c_name = "bind";
+         break;
        case PRAGMA_OMP_CLAUSE_COLLAPSE:
          clauses = cp_parser_omp_clause_collapse (parser, clauses,
                                                   token->location);
@@ -35205,6 +35691,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                            clauses);
          c_name = "use_device_ptr";
          break;
+       case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_USE_DEVICE_ADDR,
+                                           clauses);
+         c_name = "use_device_addr";
+         break;
        case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
          clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_IS_DEVICE_PTR,
                                            clauses);
@@ -35231,7 +35722,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "mergeable";
          break;
        case PRAGMA_OMP_CLAUSE_NOWAIT:
-         clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
+         clauses = cp_parser_omp_clause_nowait (parser, clauses,
+                                                token->location);
          c_name = "nowait";
          break;
        case PRAGMA_OMP_CLAUSE_NUM_TASKS:
@@ -35244,6 +35736,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                                      token->location);
          c_name = "num_threads";
          break;
+       case PRAGMA_OMP_CLAUSE_ORDER:
+         clauses = cp_parser_omp_clause_order (parser, clauses,
+                                               token->location);
+         c_name = "order";
+         break;
        case PRAGMA_OMP_CLAUSE_ORDERED:
          clauses = cp_parser_omp_clause_ordered (parser, clauses,
                                                  token->location);
@@ -35404,6 +35901,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                                    token->location);
          c_name = "proc_bind";
          break;
+       case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
+         clauses = cp_parser_omp_clause_device_type (parser, clauses,
+                                                     token->location);
+         c_name = "device_type";
+         break;
        case PRAGMA_OMP_CLAUSE_SAFELEN:
          clauses = cp_parser_omp_clause_safelen (parser, clauses,
                                                  token->location);
@@ -36262,7 +36764,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
          || CLASS_TYPE_P (TREE_TYPE (decl))))
     return cond;
 
-  return build_x_binary_op (cp_expr_loc_or_loc (cond, input_location),
+  return build_x_binary_op (cp_expr_loc_or_input_loc (cond),
                            TREE_CODE (cond),
                            TREE_OPERAND (cond, 0), ERROR_MARK,
                            TREE_OPERAND (cond, 1), ERROR_MARK,
@@ -36374,7 +36876,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 static tree
 cp_parser_omp_for_loop_init (cp_parser *parser,
                             tree &this_pre_body,
-                            vec<tree, va_gc> *&for_block,
+                            releasing_vec &for_block,
                             tree &init,
                             tree &orig_init,
                             tree &decl,
@@ -36421,10 +36923,10 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
       attributes = cp_parser_attributes_opt (parser);
       asm_specification = cp_parser_asm_specification_opt (parser);
 
-      if (declarator == cp_error_declarator) 
+      if (declarator == cp_error_declarator)
        cp_parser_skip_to_end_of_statement (parser);
 
-      else 
+      else
        {
          tree pushed_scope, auto_node;
 
@@ -36436,7 +36938,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
          auto_node = type_uses_auto (TREE_TYPE (decl));
          if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
            {
-             if (cp_lexer_next_token_is (parser->lexer, 
+             if (cp_lexer_next_token_is (parser->lexer,
                                          CPP_OPEN_PAREN))
                error ("parenthesized initialization is not allowed in "
                       "OpenMP %<for%> loop");
@@ -36467,7 +36969,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
                      && !type_dependent_expression_p (decl))
                    goto non_class;
                }
-                     
+
              cp_finish_decl (decl, init, !is_non_constant_init,
                              asm_specification,
                              LOOKUP_ONLYCONVERTING);
@@ -36527,7 +37029,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
            pop_scope (pushed_scope);
        }
     }
-  else 
+  else
     {
       cp_id_kind idk;
       /* If parsing a type specifier sequence failed, then
@@ -36782,6 +37284,63 @@ cp_finish_omp_range_for (tree orig, tree begin)
     cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
 }
 
+/* OpenMP 5.0:
+
+   scan-loop-body:
+     { structured-block scan-directive structured-block }  */
+
+static void
+cp_parser_omp_scan_loop_body (cp_parser *parser)
+{
+  tree substmt, clauses = NULL_TREE;
+
+  matching_braces braces;
+  if (!braces.require_open (parser))
+    return;
+
+  substmt = cp_parser_omp_structured_block (parser, NULL);
+  substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+  add_stmt (substmt);
+
+  cp_token *tok = cp_lexer_peek_token (parser->lexer);
+  if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
+    {
+      enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+      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);
+         if (strcmp (p, "inclusive") == 0)
+           clause = OMP_CLAUSE_INCLUSIVE;
+         else if (strcmp (p, "exclusive") == 0)
+           clause = OMP_CLAUSE_EXCLUSIVE;
+       }
+      if (clause != OMP_CLAUSE_ERROR)
+       {
+         cp_lexer_consume_token (parser->lexer);
+         clauses = cp_parser_omp_var_list (parser, clause, NULL_TREE);
+       }
+      else
+       cp_parser_error (parser, "expected %<inclusive%> or "
+                                "%<exclusive%> clause");
+
+      cp_parser_require_pragma_eol (parser, tok);
+    }
+  else
+    error ("expected %<#pragma omp scan%>");
+
+  clauses = finish_omp_clauses (clauses, C_ORT_OMP);
+  substmt = cp_parser_omp_structured_block (parser, NULL);
+  substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
+                       clauses);
+  add_stmt (substmt);
+
+  braces.require_close (parser);
+}
+
 /* Parse the restricted form of the for statement allowed by OpenMP.  */
 
 static tree
@@ -36795,9 +37354,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
   location_t loc_first;
   bool collapse_err = false;
   int i, collapse = 1, ordered = 0, count, nbraces = 0;
-  vec<tree, va_gc> *for_block = make_tree_vector ();
+  releasing_vec for_block;
   auto_vec<tree, 4> orig_inits;
   bool tiling = false;
+  bool inscan = false;
 
   for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
     if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
@@ -36813,6 +37373,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
        ordered_cl = cl;
        ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
       }
+    else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+            && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+            && (code == OMP_SIMD || code == OMP_FOR))
+      inscan = true;
 
   if (ordered && ordered < collapse)
     {
@@ -36958,7 +37522,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
        real_decl = decl;
       if (cclauses != NULL
          && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL
-         && real_decl != NULL_TREE)
+         && real_decl != NULL_TREE
+         && code != OMP_LOOP)
        {
          tree *c;
          for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
@@ -37018,12 +37583,12 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
            }
          if (c == NULL)
            {
-             if (code != OMP_SIMD)
+             if ((code == OMP_SIMD && collapse != 1) || code == OMP_LOOP)
+               c = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE);
+             else if (code != OMP_SIMD)
                c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
-             else if (collapse == 1)
-               c = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
              else
-               c = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE);
+               c = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
              OMP_CLAUSE_DECL (c) = add_private_clause;
              c = finish_omp_clauses (c, C_ORT_OMP);
              if (c)
@@ -37141,7 +37706,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
     }
   else
     body = push_stmt_list ();
-  cp_parser_statement (parser, NULL_TREE, false, if_p);
+  if (inscan)
+    cp_parser_omp_scan_loop_body (parser);
+  else
+    cp_parser_statement (parser, NULL_TREE, false, if_p);
   if (orig_declv)
     body = finish_omp_structured_block (body);
   else
@@ -37184,7 +37752,6 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
       else
        add_stmt (t);
     }
-  release_tree_vector (for_block);
 
   return ret;
 }
@@ -37203,6 +37770,50 @@ cp_omp_split_clauses (location_t loc, enum tree_code code,
       cclauses[i] = finish_omp_clauses (cclauses[i], C_ORT_OMP);
 }
 
+/* OpenMP 5.0:
+   #pragma omp loop loop-clause[optseq] new-line
+     for-loop  */
+
+#define OMP_LOOP_CLAUSE_MASK                                   \
+       ( (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_BIND)         \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
+
+static tree
+cp_parser_omp_loop (cp_parser *parser, cp_token *pragma_tok,
+                   char *p_name, omp_clause_mask mask, tree *cclauses,
+                   bool *if_p)
+{
+  tree clauses, sb, ret;
+  unsigned int save;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  strcat (p_name, " loop");
+  mask |= OMP_LOOP_CLAUSE_MASK;
+
+  clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+                                      cclauses == NULL);
+  if (cclauses)
+    {
+      cp_omp_split_clauses (loc, OMP_LOOP, mask, clauses, cclauses);
+      clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
+    }
+
+  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_LOOP, clauses, cclauses, if_p);
+
+  cp_parser_end_omp_structured_block (parser, save);
+  add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
+
+  return ret;
+}
+
 /* OpenMP 4.0:
    #pragma omp simd simd-clause[optseq] new-line
      for-loop  */
@@ -37217,7 +37828,8 @@ cp_omp_split_clauses (location_t loc, enum tree_code code,
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION)    \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)     \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL)  \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
 
 static tree
 cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
@@ -37277,7 +37889,8 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED)      \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)     \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)       \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)     \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
 
 static tree
 cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
@@ -37661,11 +38274,11 @@ 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 (cclauses == NULL && cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+  else 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, "master") == 0)
+      if (cclauses == NULL && strcmp (p, "master") == 0)
        {
          tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
          cclauses = cclauses_buf;
@@ -37683,12 +38296,34 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
            return ret;
          return stmt;
        }
+      else if (strcmp (p, "loop") == 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_loop (parser, pragma_tok, p_name, mask,
+                                      cclauses, if_p);
+         block = begin_omp_parallel ();
+         save = cp_parser_begin_omp_structured_block (parser);
+         tree ret = cp_parser_omp_loop (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);
+         if (ret == NULL_TREE)
+           return ret;
+         OMP_PARALLEL_COMBINED (stmt) = 1;
+         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)
+      else if (cclauses == NULL && strcmp (p, "sections") == 0)
        {
          tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
          cclauses = cclauses_buf;
@@ -38083,6 +38718,34 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
          SET_EXPR_LOCATION (ret, loc);
          return add_stmt (ret);
        }
+      else if (strcmp (p, "loop") == 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_loop (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_loop (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;
+         clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+         ret = make_node (OMP_TEAMS);
+         TREE_TYPE (ret) = void_type_node;
+         OMP_TEAMS_CLAUSES (ret) = clauses;
+         OMP_TEAMS_BODY (ret) = body;
+         OMP_TEAMS_COMBINED (ret) = 1;
+         SET_EXPR_LOCATION (ret, loc);
+         return add_stmt (ret);
+       }
     }
   if (!flag_openmp)  /* flag_openmp_simd  */
     {
@@ -38116,7 +38779,8 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE)       \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)          \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF)           \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
 
 static tree
 cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
@@ -38152,7 +38816,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)
+      else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
+              || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
        map_seen = 3;
       pc = &OMP_CLAUSE_CHAIN (*pc);
     }
@@ -38162,7 +38827,8 @@ 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%> or %<use_device_ptr%> clause");
+                 "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
+                 "clause");
       return NULL_TREE;
     }
 
@@ -39222,12 +39888,15 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
 
 #define OMP_DECLARE_TARGET_CLAUSE_MASK                         \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO)           \
-       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK))
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)         \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE))
 
 static void
 cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
 {
   tree clauses = NULL_TREE;
+  int device_type = 0;
+  bool only_device_type = true;
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     clauses
       = cp_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
@@ -39245,17 +39914,18 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
       scope_chain->omp_declare_target_attribute++;
       return;
     }
-  if (scope_chain->omp_declare_target_attribute)
-    error_at (pragma_tok->location,
-             "%<#pragma omp declare target%> with clauses in between "
-             "%<#pragma omp declare target%> without clauses and "
-             "%<#pragma omp end declare target%>");
+  for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
+      device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
     {
+      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
+       continue;
       tree t = OMP_CLAUSE_DECL (c), id;
       tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t));
       tree at2 = lookup_attribute ("omp declare target link",
                                   DECL_ATTRIBUTES (t));
+      only_device_type = false;
       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
        {
          id = get_identifier ("omp declare target link");
@@ -39288,7 +39958,34 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
                }
            }
        }
+      if (TREE_CODE (t) != FUNCTION_DECL)
+       continue;
+      if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
+       {
+         tree at3 = lookup_attribute ("omp declare target host",
+                                      DECL_ATTRIBUTES (t));
+         if (at3 == NULL_TREE)
+           {
+             id = get_identifier ("omp declare target host");
+             DECL_ATTRIBUTES (t)
+               = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+           }
+       }
+      if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
+       {
+         tree at3 = lookup_attribute ("omp declare target nohost",
+                                      DECL_ATTRIBUTES (t));
+         if (at3 == NULL_TREE)
+           {
+             id = get_identifier ("omp declare target nohost");
+             DECL_ATTRIBUTES (t)
+               = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+           }
+       }
     }
+  if (device_type && only_device_type)
+    warning_at (OMP_CLAUSE_LOCATION (clauses), 0,
+               "directive with only %<device_type%> clauses ignored");
 }
 
 static void
@@ -39512,7 +40209,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
   cp_token_cache *cp;
   int errs;
   void *p;
-    
+
   /* Get the high-water mark for the DECLARATOR_OBSTACK.  */
   p = obstack_alloc (&declarator_obstack, 0);
 
@@ -39590,8 +40287,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
                           || id_equal (orig_reduc_id, "max")))))
        error_at (loc, "predeclared arithmetic type %qT in "
                       "%<#pragma omp declare reduction%>", type);
-      else if (TREE_CODE (type) == FUNCTION_TYPE
-              || TREE_CODE (type) == METHOD_TYPE
+      else if (FUNC_OR_METHOD_TYPE_P (type)
               || TREE_CODE (type) == ARRAY_TYPE)
        error_at (loc, "function or array type %qT in "
                       "%<#pragma omp declare reduction%>", type);
@@ -39599,8 +40295,8 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
        error_at (loc, "reference type %qT in "
                       "%<#pragma omp declare reduction%>", type);
       else if (TYPE_QUALS_NO_ADDR_SPACE (type))
-       error_at (loc, "const, volatile or __restrict qualified type %qT in "
-                      "%<#pragma omp declare reduction%>", type);
+       error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified "
+                 "type %qT in %<#pragma omp declare reduction%>", type);
       else
        types.safe_push (type);
 
@@ -40098,6 +40794,9 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
        = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
                                      "#pragma acc routine",
                                      cp_lexer_peek_token (parser->lexer));
+      /* The clauses are in reverse order; fix that to make later diagnostic
+        emission easier.  */
+      data.clauses = nreverse (data.clauses);
 
       if (decl && is_overloaded_fn (decl)
          && (TREE_CODE (decl) != FUNCTION_DECL
@@ -40194,6 +40893,9 @@ cp_parser_late_parsing_oacc_routine (cp_parser *parser, tree attrs)
   parser->oacc_routine->clauses
     = cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
                                  "#pragma acc routine", pragma_tok);
+  /* The clauses are in reverse order; fix that to make later diagnostic
+     emission easier.  */
+  parser->oacc_routine->clauses = nreverse (parser->oacc_routine->clauses);
   cp_parser_pop_lexer (parser);
   /* Later, cp_finalize_oacc_routine will process the clauses, and then set
      fndecl_seen.  */
@@ -40228,33 +40930,42 @@ cp_finalize_oacc_routine (cp_parser *parser, tree fndecl, bool is_defn)
          return;
        }
 
-      if (oacc_get_fn_attrib (fndecl))
+      int compatible
+       = oacc_verify_routine_clauses (fndecl, &parser->oacc_routine->clauses,
+                                      parser->oacc_routine->loc,
+                                      "#pragma acc routine");
+      if (compatible < 0)
        {
-         error_at (parser->oacc_routine->loc,
-                   "%<#pragma acc routine%> already applied to %qD", fndecl);
          parser->oacc_routine = NULL;
          return;
        }
-
-      if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+      if (compatible > 0)
        {
-         error_at (parser->oacc_routine->loc,
-                   TREE_USED (fndecl)
-                   ? G_("%<#pragma acc routine%> must be applied before use")
-                   : G_("%<#pragma acc routine%> must be applied before "
-                        "definition"));
-         parser->oacc_routine = NULL;
-         return;
        }
+      else
+       {
+         if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+           {
+             error_at (parser->oacc_routine->loc,
+                       TREE_USED (fndecl)
+                       ? G_("%<#pragma acc routine%> must be applied before"
+                            " use")
+                       : G_("%<#pragma acc routine%> must be applied before"
+                            " definition"));
+             parser->oacc_routine = NULL;
+             return;
+           }
 
-      /* Process the routine's dimension clauses.  */
-      tree dims = oacc_build_routine_dims (parser->oacc_routine->clauses);
-      oacc_replace_fn_attrib (fndecl, dims);
+         /* Set the routine's level of parallelism.  */
+         tree dims = oacc_build_routine_dims (parser->oacc_routine->clauses);
+         oacc_replace_fn_attrib (fndecl, dims);
 
-      /* Add an "omp declare target" attribute.  */
-      DECL_ATTRIBUTES (fndecl)
-       = tree_cons (get_identifier ("omp declare target"),
-                    NULL_TREE, DECL_ATTRIBUTES (fndecl));
+         /* Add an "omp declare target" attribute.  */
+         DECL_ATTRIBUTES (fndecl)
+           = tree_cons (get_identifier ("omp declare target"),
+                        parser->oacc_routine->clauses,
+                        DECL_ATTRIBUTES (fndecl));
+       }
 
       /* Don't unset parser->oacc_routine here: we may still need it to
         diagnose wrong usage.  But, remember that we've used this "#pragma acc
@@ -40325,6 +41036,11 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
       stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL,
                                if_p);
       break;
+    case PRAGMA_OMP_LOOP:
+      strcpy (p_name, "#pragma omp");
+      stmt = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, NULL,
+                                if_p);
+      break;
     case PRAGMA_OMP_MASTER:
       strcpy (p_name, "#pragma omp");
       stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL,
@@ -40451,11 +41167,15 @@ cp_parser_transaction (cp_parser *parser, cp_token *token)
   else if (keyword == RID_ATOMIC_CANCEL)
     {
       /* cancel-and-throw is unimplemented.  */
-      sorry ("atomic_cancel");
+      sorry ("%<atomic_cancel%>");
       noex = NULL_TREE;
     }
   else
-    noex = cp_parser_noexcept_specification_opt (parser, true, NULL, true);
+    noex = cp_parser_noexcept_specification_opt (parser,
+                                                CP_PARSER_FLAGS_NONE,
+                                                /*require_constexpr=*/true,
+                                                /*consumed_expr=*/NULL,
+                                                /*return_cond=*/true);
 
   /* Keep track if we're in the lexical scope of an outer transaction.  */
   new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
@@ -40515,8 +41235,11 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
   parser->in_transaction = this_in;
 
   /* Parse a noexcept specification.  */
-  noex = cp_parser_noexcept_specification_opt (parser, false, &noex_expr,
-                                              true);
+  noex = cp_parser_noexcept_specification_opt (parser,
+                                              CP_PARSER_FLAGS_NONE,
+                                              /*require_constexpr=*/false,
+                                              &noex_expr,
+                                              /*return_cond=*/true);
 
   if (!noex || !noex_expr
       || cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
@@ -40680,7 +41403,10 @@ cp_parser_initial_pragma (cp_token *first_token)
 
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (cp_parser_pragma_kind (first_token) != PRAGMA_GCC_PCH_PREPROCESS)
-    return;
+    {
+      c_common_no_more_pch ();
+      return;
+    }
 
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (first_token->type == CPP_STRING)
@@ -40954,6 +41680,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
     case PRAGMA_OMP_CRITICAL:
     case PRAGMA_OMP_DISTRIBUTE:
     case PRAGMA_OMP_FOR:
+    case PRAGMA_OMP_LOOP:
     case PRAGMA_OMP_MASTER:
     case PRAGMA_OMP_PARALLEL:
     case PRAGMA_OMP_SECTIONS:
@@ -40993,8 +41720,14 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
       cp_parser_omp_end_declare_target (parser, pragma_tok);
       return false;
 
+    case PRAGMA_OMP_SCAN:
+      error_at (pragma_tok->location,
+               "%<#pragma omp scan%> may only be used in "
+               "a loop construct with %<inscan%> %<reduction%> clause");
+      break;
+
     case PRAGMA_OMP_SECTION:
-      error_at (pragma_tok->location, 
+      error_at (pragma_tok->location,
                "%<#pragma omp section%> may only be used in "
                "%<#pragma omp sections%> construct");
       break;
@@ -41300,7 +42033,7 @@ synthesize_implicit_template_parm  (cp_parser *parser, tree constr)
       non_type = true;
     }
 
-  // Attach the constraint to the parm before processing.
+  /* Attach the constraint to the parm before processing.  */
   tree node = build_tree_list (NULL_TREE, synth_tmpl_parm);
   TREE_TYPE (node) = constr;
   tree new_parm
@@ -41343,8 +42076,8 @@ synthesize_implicit_template_parm  (cp_parser *parser, tree constr)
       TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms;
     }
 
-  // If the new parameter was constrained, we need to add that to the
-  // constraints in the template parameter list.
+  /* If the new parameter was constrained, we need to add that to the
+     constraints in the template parameter list.  */
   if (tree req = TEMPLATE_PARM_CONSTRAINTS (tree_last (new_parm)))
     {
       tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);