]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/parser.c
Wrap option names in gcc internal messages with %< and %>.
[thirdparty/gcc.git] / gcc / cp / parser.c
index c4b969c84b9f3774dd03e353869d194ea0601144..f95111169ed3ebfe1c6ac42c2f33882faed2ff49 100644 (file)
@@ -1,5 +1,5 @@
 /* -*- C++ -*- Parser.
-   Copyright (C) 2000-2018 Free Software Foundation, Inc.
+   Copyright (C) 2000-2019 Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -536,9 +536,12 @@ cp_debug_parser (FILE *file, cp_parser *parser)
                              parser->allow_non_integral_constant_expression_p);
   cp_debug_print_flag (file, "Seen non-constant expression",
                              parser->non_integral_constant_expression_p);
-  cp_debug_print_flag (file, "Local names and 'this' forbidden in "
-                             "current context",
-                             parser->local_variables_forbidden_p);
+  cp_debug_print_flag (file, "Local names forbidden in current context",
+                             (parser->local_variables_forbidden_p
+                              & LOCAL_VARS_FORBIDDEN));
+  cp_debug_print_flag (file, "'this' forbidden in current context",
+                             (parser->local_variables_forbidden_p
+                              & THIS_FORBIDDEN));
   cp_debug_print_flag (file, "In unbraced linkage specification",
                              parser->in_unbraced_linkage_specification_p);
   cp_debug_print_flag (file, "Parsing a declarator",
@@ -945,6 +948,7 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
     case RID_TYPENAME:
       /* Simple type specifiers.  */
     case RID_CHAR:
+    case RID_CHAR8:
     case RID_CHAR16:
     case RID_CHAR32:
     case RID_WCHAR:
@@ -1643,7 +1647,7 @@ declarator_can_be_parameter_pack (cp_declarator *declarator)
 
   /* Search for a declarator name, or any other declarator that goes
      after the point where the ellipsis could appear in a parameter
-     pack. If we find any of these, then this declarator can not be
+     pack. If we find any of these, then this declarator cannot be
      made into a parameter pack.  */
   bool found = false;
   while (declarator && !found)
@@ -2203,9 +2207,10 @@ static tree cp_parser_init_declarator
    location_t *, tree *);
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool *,
-   bool, bool);
+   bool, bool, bool);
 static cp_declarator *cp_parser_direct_declarator
-  (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool, bool);
+  (cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool, bool,
+   bool);
 static enum tree_code cp_parser_ptr_operator
   (cp_parser *, tree *, cp_cv_quals *, tree *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
@@ -2246,7 +2251,7 @@ static cp_expr cp_parser_initializer_clause
 static cp_expr cp_parser_braced_list
   (cp_parser*, bool*);
 static vec<constructor_elt, va_gc> *cp_parser_initializer_list
-  (cp_parser *, bool *);
+  (cp_parser *, bool *, bool *);
 
 static void cp_parser_ctor_initializer_opt_and_function_body
   (cp_parser *, bool);
@@ -3283,7 +3288,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
                decl);
       if (DECL_CLASS_TEMPLATE_P (decl) && cxx_dialect < cxx17)
        inform (location, "class template argument deduction is only available "
-               "with -std=c++17 or -std=gnu++17");
+               "with %<-std=c++17%> or %<-std=gnu++17%>");
       inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
     }
   else if (TREE_CODE (id) == BIT_NOT_EXPR)
@@ -3317,17 +3322,17 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
         The user should have said "typename A<T>::X".  */
       if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_CONSTEXPR])
        inform (location, "C++11 %<constexpr%> only available with "
-               "-std=c++11 or -std=gnu++11");
+               "%<-std=c++11%> or %<-std=gnu++11%>");
       else if (cxx_dialect < cxx11 && id == ridpointers[(int)RID_NOEXCEPT])
        inform (location, "C++11 %<noexcept%> only available with "
-               "-std=c++11 or -std=gnu++11");
+               "%<-std=c++11%> or %<-std=gnu++11%>");
       else if (cxx_dialect < cxx11
               && TREE_CODE (id) == IDENTIFIER_NODE
               && id_equal (id, "thread_local"))
        inform (location, "C++11 %<thread_local%> only available with "
-               "-std=c++11 or -std=gnu++11");
+               "%<-std=c++11%> or %<-std=gnu++11%>");
       else if (!flag_concepts && id == ridpointers[(int)RID_CONCEPT])
-       inform (location, "%<concept%> only available with -fconcepts");
+       inform (location, "%<concept%> only available with %<-fconcepts%>");
       else if (processing_template_decl && current_class_type
               && TYPE_BINFO (current_class_type))
        {
@@ -3951,7 +3956,7 @@ cp_parser_new (void)
   parser->non_integral_constant_expression_p = false;
 
   /* Local variable names are not forbidden.  */
-  parser->local_variables_forbidden_p = false;
+  parser->local_variables_forbidden_p = 0;
 
   /* We are not processing an `extern "C"' declaration.  */
   parser->in_unbraced_linkage_specification_p = false;
@@ -4231,9 +4236,14 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
        {
        default:
        case CPP_STRING:
-       case CPP_UTF8STRING:
          TREE_TYPE (value) = char_array_type_node;
          break;
+       case CPP_UTF8STRING:
+         if (flag_char8_t)
+           TREE_TYPE (value) = char8_array_type_node;
+         else
+           TREE_TYPE (value) = char_array_type_node;
+         break;
        case CPP_STRING16:
          TREE_TYPE (value) = char16_array_type_node;
          break;
@@ -4541,7 +4551,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
                "GNU built-in suffix");
     }
   else if (!ext)
-    inform (token->location, "use -fext-numeric-literals "
+    inform (token->location, "use %<-fext-numeric-literals%> "
            "to enable more built-in suffixes");
 
   if (kind == DK_ERROR)
@@ -5321,7 +5331,7 @@ cp_parser_primary_expression (cp_parser *parser,
                && cxx_dialect < cxx17
                && !in_system_header_at (input_location))
              pedwarn (input_location, 0, "fold-expressions only available "
-                      "with -std=c++17 or -std=gnu++17");
+                      "with %<-std=c++17%> or %<-std=gnu++17%>");
          }
        else
          /* Let the front end know that this expression was
@@ -5405,7 +5415,7 @@ cp_parser_primary_expression (cp_parser *parser,
          /* Recognize the `this' keyword.  */
        case RID_THIS:
          cp_lexer_consume_token (parser->lexer);
-         if (parser->local_variables_forbidden_p)
+         if (parser->local_variables_forbidden_p & THIS_FORBIDDEN)
            {
              error_at (token->location,
                        "%<this%> may not be used in this context");
@@ -5681,14 +5691,14 @@ cp_parser_primary_expression (cp_parser *parser,
                      template <int N> struct A {
                        int a[B<N>::i];
                      };
-                    
+
                   is accepted.  At template-instantiation time, we
                   will check that B<N>::i is actually a constant.  */
                return decl;
              }
            /* Check to see if DECL is a local variable in a context
               where that is forbidden.  */
-           if (parser->local_variables_forbidden_p
+           if ((parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN)
                && local_variable_p (decl))
              {
                error_at (id_expression.get_location (),
@@ -5966,6 +5976,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        tree object_scope;
        tree scope;
        bool done;
+       location_t tilde_loc = token->location;
 
        /* Consume the `~' token.  */
        cp_lexer_consume_token (parser->lexer);
@@ -6028,9 +6039,18 @@ cp_parser_unqualified_id (cp_parser* parser,
          }
        gcc_assert (!scope || TYPE_P (scope));
 
+       token = cp_lexer_peek_token (parser->lexer);
+
+       /* Create a location with caret == start at the tilde,
+          finishing at the end of the peeked token, e.g:
+          ~token
+          ^~~~~~.  */
+       location_t loc
+         = make_location (tilde_loc, tilde_loc, token->location);
+
        /* If the name is of the form "X::~X" it's OK even if X is a
           typedef.  */
-       token = cp_lexer_peek_token (parser->lexer);
+
        if (scope
            && token->type == CPP_NAME
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
@@ -6040,18 +6060,18 @@ cp_parser_unqualified_id (cp_parser* parser,
                    && constructor_name_p (token->u.value, scope))))
          {
            cp_lexer_consume_token (parser->lexer);
-           return build_nt (BIT_NOT_EXPR, scope);
+           return cp_expr (build_nt (BIT_NOT_EXPR, scope), loc);
          }
 
        /* ~auto means the destructor of whatever the object is.  */
        if (cp_parser_is_keyword (token, RID_AUTO))
          {
            if (cxx_dialect < cxx14)
-             pedwarn (input_location, 0,
+             pedwarn (loc, 0,
                       "%<~auto%> only available with "
-                      "-std=c++14 or -std=gnu++14");
+                      "%<-std=c++14%> or %<-std=gnu++14%>");
            cp_lexer_consume_token (parser->lexer);
-           return build_nt (BIT_NOT_EXPR, make_auto ());
+           return cp_expr (build_nt (BIT_NOT_EXPR, make_auto (), loc));
          }
 
        /* If there was an explicit qualification (S::~T), first look
@@ -6142,7 +6162,7 @@ cp_parser_unqualified_id (cp_parser* parser,
                type_decl = cp_parser_identifier (parser);
                if (type_decl != error_mark_node)
                  type_decl = build_nt (BIT_NOT_EXPR, type_decl);
-               return type_decl;
+               return cp_expr (type_decl, loc);
              }
          }
        /* If an error occurred, assume that the name of the
@@ -6158,7 +6178,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        if (declarator_p && scope && !check_dtor_name (scope, type_decl))
          {
            if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-             error_at (token->location,
+             error_at (loc,
                        "declaration of %<~%T%> as member of %qT",
                        type_decl, scope);
            cp_parser_simulate_error (parser);
@@ -6173,11 +6193,11 @@ cp_parser_unqualified_id (cp_parser* parser,
            && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
            && !DECL_SELF_REFERENCE_P (type_decl)
            && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-         error_at (token->location,
+         error_at (loc,
                    "typedef-name %qD used as destructor declarator",
                    type_decl);
 
-       return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+       return cp_expr (build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl), loc));
       }
 
     case CPP_KEYWORD:
@@ -7031,6 +7051,32 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        break;
       }
 
+    case RID_BUILTIN_CONVERTVECTOR:
+      {
+       tree expression;
+       tree type;
+       /* Consume the `__builtin_convertvector' token.  */
+       cp_lexer_consume_token (parser->lexer);
+       /* Look for the opening `('.  */
+       matching_parens parens;
+       parens.require_open (parser);
+       /* Now, parse the assignment-expression.  */
+       expression = cp_parser_assignment_expression (parser);
+       /* Look for the `,'.  */
+       cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+       location_t type_location
+         = cp_lexer_peek_token (parser->lexer)->location;
+       /* Parse the type-id.  */
+       {
+         type_id_in_expr_sentinel s (parser);
+         type = cp_parser_type_id (parser);
+       }
+       /* Look for the closing `)'.  */
+       parens.require_close (parser);
+       return cp_build_vec_convert (expression, type_location, type,
+                                    tf_warning_or_error);
+      }
+
     default:
       {
        tree type;
@@ -7957,7 +8003,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
       if (cxx_dialect < cxx14)
        pedwarn (input_location, 0,
                 "%<~auto%> only available with "
-                "-std=c++14 or -std=gnu++14");
+                "%<-std=c++14%> or %<-std=gnu++14%>");
       cp_lexer_consume_token (parser->lexer);
       cp_lexer_consume_token (parser->lexer);
       *scope = NULL_TREE;
@@ -10054,7 +10100,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   {
     const char *saved_message = parser->type_definition_forbidden_message;
     parser->type_definition_forbidden_message
-      = G_("types may not be defined within __builtin_offsetof");
+      = G_("types may not be defined within %<__builtin_offsetof%>");
     type = cp_parser_type_id (parser);
     parser->type_definition_forbidden_message = saved_message;
   }
@@ -10344,7 +10390,7 @@ cp_parser_lambda_expression (cp_parser* parser)
        {
          error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
                    "lambda-expression in unevaluated context"
-                   " only available with -std=c++2a or -std=gnu++2a");
+                   " only available with %<-std=c++2a%> or %<-std=gnu++2a%>");
          token->error_reported = true;
        }
       ok = false;
@@ -10354,7 +10400,7 @@ cp_parser_lambda_expression (cp_parser* parser)
       if (!token->error_reported)
        {
          error_at (token->location, "lambda-expression in template-argument"
-                   " only available with -std=c++2a or -std=gnu++2a");
+                   " only available with %<-std=c++2a%> or %<-std=gnu++2a%>");
          token->error_reported = true;
        }
       ok = false;
@@ -10551,7 +10597,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
          location_t loc = cp_lexer_peek_token (parser->lexer)->location;
          if (cxx_dialect < cxx17)
            pedwarn (loc, 0, "%<*this%> capture only available with "
-                            "-std=c++17 or -std=gnu++17");
+                            "%<-std=c++17%> or %<-std=gnu++17%>");
          cp_lexer_consume_token (parser->lexer);
          cp_lexer_consume_token (parser->lexer);
          add_capture (lambda_expr,
@@ -10568,7 +10614,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
          location_t loc = cp_lexer_peek_token (parser->lexer)->location;
          if (cxx_dialect < cxx2a)
            pedwarn (loc, 0, "pack init-capture only available with "
-                            "-std=c++2a or -std=gnu++2a");
+                            "%<-std=c++2a%> or %<-std=gnu++2a%>");
          cp_lexer_consume_token (parser->lexer);
          init_pack_expansion = true;
        }
@@ -10607,7 +10653,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
          if (cxx_dialect < cxx14)
            pedwarn (input_location, 0,
                     "lambda capture initializers "
-                    "only available with -std=c++14 or -std=gnu++14");
+                    "only available with %<-std=c++14%> or %<-std=gnu++14%>");
          capture_init_expr = cp_parser_initializer (parser, &direct,
                                                     &non_constant, true);
          explicit_init_p = true;
@@ -10745,11 +10791,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       if (cxx_dialect < cxx14)
        pedwarn (parser->lexer->next_token->location, 0,
                 "lambda templates are only available with "
-                "-std=c++14 or -std=gnu++14");
+                "%<-std=c++14%> or %<-std=gnu++14%>");
       else if (cxx_dialect < cxx2a)
        pedwarn (parser->lexer->next_token->location, OPT_Wpedantic,
                 "lambda templates are only available with "
-                "-std=c++2a or -std=gnu++2a");
+                "%<-std=c++2a%> or %<-std=gnu++2a%>");
 
       cp_lexer_consume_token (parser->lexer);
 
@@ -10844,7 +10890,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
            = lambda_specs.locations[ds_constexpr];
        else
          error_at (lambda_specs.locations[ds_constexpr], "%<constexpr%> "
-                   "lambda only available with -std=c++17 or -std=gnu++17");
+                   "lambda only available with %<-std=c++17%> or "
+                   "%<-std=gnu++17%>");
       }
 
     p = obstack_alloc (&declarator_obstack, 0);
@@ -10902,7 +10949,8 @@ static void
 cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
 {
   bool nested = (current_function_decl != NULL_TREE);
-  bool local_variables_forbidden_p = parser->local_variables_forbidden_p;
+  unsigned char local_variables_forbidden_p
+    = parser->local_variables_forbidden_p;
   bool in_function_body = parser->in_function_body;
 
   /* The body of a lambda-expression is not a subexpression of the enclosing
@@ -10919,7 +10967,7 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
   vec<tree> omp_privatization_save;
   save_omp_privatization_clauses (omp_privatization_save);
   /* Clear this in case we're in the middle of a default argument.  */
-  parser->local_variables_forbidden_p = false;
+  parser->local_variables_forbidden_p = 0;
   parser->in_function_body = true;
 
   {
@@ -11023,7 +11071,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 {
   tree statement, std_attrs = NULL_TREE;
   cp_token *token;
-  location_t statement_location, attrs_location;
+  location_t statement_location, attrs_loc;
 
  restart:
   if (if_p != NULL)
@@ -11032,13 +11080,19 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
   statement = NULL_TREE;
 
   saved_token_sentinel saved_tokens (parser->lexer);
-  attrs_location = cp_lexer_peek_token (parser->lexer)->location;
+  attrs_loc = cp_lexer_peek_token (parser->lexer)->location;
   if (c_dialect_objc ())
     /* In obj-c++, seeing '[[' might be the either the beginning of
        c++11 attributes, or a nested objc-message-expression.  So
        let's parse the c++11 attributes tentatively.  */
     cp_parser_parse_tentatively (parser);
   std_attrs = cp_parser_std_attribute_spec_seq (parser);
+  if (std_attrs)
+    {
+      location_t end_loc
+       = cp_lexer_previous_token (parser->lexer)->location;
+      attrs_loc = make_location (attrs_loc, attrs_loc, end_loc);
+    }
   if (c_dialect_objc ())
     {
       if (!cp_parser_parse_definitely (parser))
@@ -11070,14 +11124,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
        case RID_IF:
        case RID_SWITCH:
-         std_attrs = process_stmt_hotness_attribute (std_attrs);
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_selection_statement (parser, if_p, chain);
          break;
 
        case RID_WHILE:
        case RID_DO:
        case RID_FOR:
-         std_attrs = process_stmt_hotness_attribute (std_attrs);
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_iteration_statement (parser, if_p, false, 0);
          break;
 
@@ -11085,7 +11139,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        case RID_CONTINUE:
        case RID_RETURN:
        case RID_GOTO:
-         std_attrs = process_stmt_hotness_attribute (std_attrs);
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_jump_statement (parser);
          break;
 
@@ -11095,12 +11149,12 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        case RID_AT_FINALLY:
        case RID_AT_SYNCHRONIZED:
        case RID_AT_THROW:
-         std_attrs = process_stmt_hotness_attribute (std_attrs);
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_objc_statement (parser);
          break;
 
        case RID_TRY:
-         std_attrs = process_stmt_hotness_attribute (std_attrs);
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_try_block (parser);
          break;
 
@@ -11121,11 +11175,11 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        case RID_SYNCHRONIZED:
        case RID_ATOMIC_NOEXCEPT:
        case RID_ATOMIC_CANCEL:
-         std_attrs = process_stmt_hotness_attribute (std_attrs);
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_transaction (parser, token);
          break;
        case RID_TRANSACTION_CANCEL:
-         std_attrs = process_stmt_hotness_attribute (std_attrs);
+         std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
          statement = cp_parser_transaction_cancel (parser);
          break;
 
@@ -11202,7 +11256,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
       if (loc_after_labels != NULL)
        *loc_after_labels = statement_location;
 
-      std_attrs = process_stmt_hotness_attribute (std_attrs);
+      std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
 
       /* Look for an expression-statement instead.  */
       statement = cp_parser_expression_statement (parser, in_statement_expr);
@@ -11232,7 +11286,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
   /* Allow "[[fallthrough]];", but warn otherwise.  */
   if (std_attrs != NULL_TREE)
-    warning_at (attrs_location,
+    warning_at (attrs_loc,
                OPT_Wattributes,
                "attributes at the beginning of statement are ignored");
 }
@@ -11661,7 +11715,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
            cp_token *tok = cp_lexer_consume_token (parser->lexer);
            if (cxx_dialect < cxx17 && !in_system_header_at (tok->location))
              pedwarn (tok->location, 0, "%<if constexpr%> only available "
-                      "with -std=c++17 or -std=gnu++17");
+                      "with %<-std=c++17%> or %<-std=gnu++17%>");
          }
 
        /* Look for the `('.  */
@@ -11688,7 +11742,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
            if (cxx_dialect < cxx17)
              pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0,
                       "init-statement in selection statements only available "
-                      "with -std=c++17 or -std=gnu++17");
+                      "with %<-std=c++17%> or %<-std=gnu++17%>");
            cp_parser_init_statement (parser, &decl);
          }
 
@@ -11964,7 +12018,8 @@ cp_parser_condition (cp_parser* parser)
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         /*parenthesized_p=*/NULL,
                                         /*member_p=*/false,
-                                        /*friend_p=*/false);
+                                        /*friend_p=*/false,
+                                        /*static_p=*/false);
       /* Parse the attributes.  */
       attributes = cp_parser_attributes_opt (parser);
       /* Parse the asm-specification.  */
@@ -12674,7 +12729,7 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
            {
              pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0,
                       "range-based %<for%> loops with initializer only "
-                      "available with -std=c++2a or -std=gnu++2a");
+                      "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
              *decl = error_mark_node;
            }
        }
@@ -12698,7 +12753,7 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
          if (cxx_dialect < cxx11)
            pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0,
                     "range-based %<for%> loops only available with "
-                    "-std=c++11 or -std=gnu++11");
+                    "%<-std=c++11%> or %<-std=gnu++11%>");
        }
       else
        /* The ';' is not consumed yet because we told
@@ -13640,7 +13695,7 @@ cp_parser_decomposition_declaration (cp_parser *parser,
 
   if (cxx_dialect < cxx17)
     pedwarn (loc, 0, "structured bindings only available with "
-                    "-std=c++17 or -std=gnu++17");
+                    "%<-std=c++17%> or %<-std=gnu++17%>");
 
   tree pushed_scope;
   cp_declarator *declarator = make_declarator (cdk_decomp);
@@ -14177,8 +14232,8 @@ cp_parser_function_specifier_opt (cp_parser* parser,
 
            if (cxx_dialect < cxx2a)
              pedwarn (token->location, 0,
-                      "%<explicit(bool)%> only available with -std=c++2a "
-                      "or -std=gnu++2a");
+                      "%<explicit(bool)%> only available with %<-std=c++2a%> "
+                      "or %<-std=gnu++2a%>");
 
            /* Parse the constant-expression.  */
            expr = cp_parser_constant_expression (parser);
@@ -14346,7 +14401,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
       if (cxx_dialect < cxx17)
        pedwarn (input_location, OPT_Wpedantic,
                 "static_assert without a message "
-                "only available with -std=c++17 or -std=gnu++17");
+                "only available with %<-std=c++17%> or %<-std=gnu++17%>");
       /* Eat the ')'  */
       cp_lexer_consume_token (parser->lexer);
       message = build_string (1, "");
@@ -16994,6 +17049,14 @@ cp_parser_template_argument (cp_parser* parser)
     argument = cp_parser_constant_expression (parser);
   else
     {
+      /* In C++20, we can encounter a braced-init-list.  */
+      if (cxx_dialect >= cxx2a
+         && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+       {
+         bool expr_non_constant_p;
+         return cp_parser_braced_list (parser, &expr_non_constant_p);
+       }
+
       /* With C++17 generalized non-type template arguments we need to handle
         lvalue constant expressions, too.  */
       argument = cp_parser_assignment_expression (parser);
@@ -17097,7 +17160,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
                                /*ctor_dtor_or_conv_p=*/NULL,
                                /*parenthesized_p=*/NULL,
                                /*member_p=*/false,
-                               /*friend_p=*/false);
+                               /*friend_p=*/false,
+                               /*static_p=*/false);
       if (declares_class_or_enum & 2)
        cp_parser_check_for_definition_in_return_type (declarator,
                                                       decl_specifiers.type,
@@ -17463,6 +17527,9 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        decl_specs->explicit_char_p = true;
       type = char_type_node;
       break;
+    case RID_CHAR8:
+      type = char8_type_node;
+      break;
     case RID_CHAR16:
       type = char16_type_node;
       break;
@@ -17576,17 +17643,17 @@ cp_parser_simple_type_specifier (cp_parser* parser,
                error_at (token->location,
                         "use of %<auto%> in lambda parameter declaration "
                         "only available with "
-                        "-std=c++14 or -std=gnu++14");
+                        "%<-std=c++14%> or %<-std=gnu++14%>");
            }
          else if (cxx_dialect < cxx14)
            error_at (token->location,
                     "use of %<auto%> in parameter declaration "
                     "only available with "
-                    "-std=c++14 or -std=gnu++14");
+                    "%<-std=c++14%> or %<-std=gnu++14%>");
          else if (!flag_concepts)
            pedwarn (token->location, 0,
                     "use of %<auto%> in parameter declaration "
-                    "only available with -fconcepts");
+                    "only available with %<-fconcepts%>");
        }
       else
        type = make_auto ();
@@ -19112,7 +19179,7 @@ cp_parser_namespace_definition (cp_parser* parser)
          if (cxx_dialect < cxx2a)
            pedwarn (cp_lexer_peek_token (parser->lexer)->location,
                     OPT_Wpedantic, "nested inline namespace definitions only "
-                    "available with -std=c++2a or -std=gnu++2a");
+                    "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
          cp_lexer_consume_token (parser->lexer);
        }
 
@@ -19141,8 +19208,8 @@ cp_parser_namespace_definition (cp_parser* parser)
   
       if (!nested_definition_count && cxx_dialect < cxx17)
         pedwarn (input_location, OPT_Wpedantic,
-                 "nested namespace definitions only available with "
-                 "-std=c++17 or -std=gnu++17");
+                "nested namespace definitions only available with "
+                "%<-std=c++17%> or %<-std=gnu++17%>");
 
       /* Nested namespace names can create new namespaces (unlike
         other qualified-ids).  */
@@ -19346,7 +19413,8 @@ cp_parser_using_declaration (cp_parser* parser,
                                                  /*is_declaration=*/true);
   if (!qscope)
     qscope = global_namespace;
-  else if (UNSCOPED_ENUM_P (qscope))
+  else if (UNSCOPED_ENUM_P (qscope)
+          && !TYPE_FUNCTION_SCOPE_P (qscope))
     qscope = CP_TYPE_CONTEXT (qscope);
 
   if (access_declaration_p && cp_parser_error_occurred (parser))
@@ -19377,7 +19445,7 @@ cp_parser_using_declaration (cp_parser* parser,
          && !in_system_header_at (ell->location))
        pedwarn (ell->location, 0,
                 "pack expansion in using-declaration only available "
-                "with -std=c++17 or -std=gnu++17");
+                "with %<-std=c++17%> or %<-std=gnu++17%>");
       qscope = make_pack_expansion (qscope);
     }
 
@@ -19439,7 +19507,7 @@ cp_parser_using_declaration (cp_parser* parser,
       if (cxx_dialect < cxx17)
        pedwarn (comma->location, 0,
                 "comma-separated list in using-declaration only available "
-                "with -std=c++17 or -std=gnu++17");
+                "with %<-std=c++17%> or %<-std=gnu++17%>");
       goto again;
     }
 
@@ -19699,6 +19767,8 @@ cp_parser_asm_definition (cp_parser* parser)
   location_t volatile_loc = UNKNOWN_LOCATION;
   location_t inline_loc = UNKNOWN_LOCATION;
   location_t goto_loc = UNKNOWN_LOCATION;
+  location_t first_loc = UNKNOWN_LOCATION;
+
   if (cp_parser_allow_gnu_extensions_p (parser))
     for (;;)
       {
@@ -19713,13 +19783,16 @@ cp_parser_asm_definition (cp_parser* parser)
                inform (volatile_loc, "first seen here");
              }
            else
-             volatile_loc = loc;
+             {
+               if (!parser->in_function_body)
+                 warning_at (loc, 0, "asm qualifier %qT ignored outside of "
+                                     "function body", token->u.value);
+               volatile_loc = loc;
+             }
            cp_lexer_consume_token (parser->lexer);
            continue;
 
          case RID_INLINE:
-           if (!parser->in_function_body)
-             break;
            if (inline_loc)
              {
                error_at (loc, "duplicate asm qualifier %qT", token->u.value);
@@ -19727,12 +19800,12 @@ cp_parser_asm_definition (cp_parser* parser)
              }
            else
              inline_loc = loc;
+           if (!first_loc)
+             first_loc = loc;
            cp_lexer_consume_token (parser->lexer);
            continue;
 
          case RID_GOTO:
-           if (!parser->in_function_body)
-             break;
            if (goto_loc)
              {
                error_at (loc, "duplicate asm qualifier %qT", token->u.value);
@@ -19740,6 +19813,8 @@ cp_parser_asm_definition (cp_parser* parser)
              }
            else
              goto_loc = loc;
+           if (!first_loc)
+             first_loc = loc;
            cp_lexer_consume_token (parser->lexer);
            continue;
 
@@ -19759,6 +19834,12 @@ cp_parser_asm_definition (cp_parser* parser)
   bool inline_p = (inline_loc != UNKNOWN_LOCATION);
   bool goto_p = (goto_loc != UNKNOWN_LOCATION);
 
+  if (!parser->in_function_body && (inline_p || goto_p))
+    {
+      error_at (first_loc, "asm qualifier outside of function body");
+      inline_p = goto_p = false;
+    }
+
   /* Look for the opening `('.  */
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return;
@@ -20045,7 +20126,7 @@ cp_parser_init_declarator (cp_parser* parser,
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                            flags, &ctor_dtor_or_conv_p,
                            /*parenthesized_p=*/NULL,
-                           member_p, friend_p);
+                           member_p, friend_p, /*static_p=*/false);
   /* Gather up the deferred checks.  */
   stop_deferring_access_checks ();
 
@@ -20463,7 +20544,9 @@ cp_parser_init_declarator (cp_parser* parser,
 
    MEMBER_P is true iff this declarator is a member-declarator.
 
-   FRIEND_P is true iff this declarator is a friend.  */
+   FRIEND_P is true iff this declarator is a friend.
+
+   STATIC_P is true iff the keyword static was seen.  */
 
 static cp_declarator *
 cp_parser_declarator (cp_parser* parser,
@@ -20471,7 +20554,7 @@ cp_parser_declarator (cp_parser* parser,
                      cp_parser_flags flags,
                      int* ctor_dtor_or_conv_p,
                      bool* parenthesized_p,
-                     bool member_p, bool friend_p)
+                     bool member_p, bool friend_p, bool static_p)
 {
   cp_declarator *declarator;
   enum tree_code code;
@@ -20513,7 +20596,7 @@ cp_parser_declarator (cp_parser* parser,
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         /*parenthesized_p=*/NULL,
                                         /*member_p=*/false,
-                                        friend_p);
+                                        friend_p, /*static_p=*/false);
 
       /* If we are parsing an abstract-declarator, we must handle the
         case where the dependent declarator is absent.  */
@@ -20532,7 +20615,7 @@ cp_parser_declarator (cp_parser* parser,
                                                   CPP_OPEN_PAREN);
       declarator = cp_parser_direct_declarator (parser, dcl_kind,
                                                flags, ctor_dtor_or_conv_p,
-                                               member_p, friend_p);
+                                               member_p, friend_p, static_p);
     }
 
   if (gnu_attributes && declarator && declarator != cp_error_declarator)
@@ -20568,7 +20651,7 @@ cp_parser_declarator (cp_parser* parser,
    of ambiguity we prefer an abstract declarator, as per
    [dcl.ambig.res].
    The parser flags FLAGS is used to control type-specifier parsing.
-   CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are
+   CTOR_DTOR_OR_CONV_P, MEMBER_P, FRIEND_P, and STATIC_P are
    as for cp_parser_declarator.  */
 
 static cp_declarator *
@@ -20576,7 +20659,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                             cp_parser_declarator_kind dcl_kind,
                             cp_parser_flags flags,
                             int* ctor_dtor_or_conv_p,
-                            bool member_p, bool friend_p)
+                            bool member_p, bool friend_p, bool static_p)
 {
   cp_token *token;
   cp_declarator *declarator = NULL;
@@ -20679,6 +20762,11 @@ cp_parser_direct_declarator (cp_parser* parser,
                  tree attrs;
                  bool memfn = (member_p || (pushed_scope
                                             && CLASS_TYPE_P (pushed_scope)));
+                 unsigned char local_variables_forbidden_p
+                   = parser->local_variables_forbidden_p;
+                 /* 'this' is not allowed in static member functions.  */
+                 if (static_p || friend_p)
+                   parser->local_variables_forbidden_p |= THIS_FORBIDDEN;
 
                  is_declarator = true;
 
@@ -20726,6 +20814,10 @@ cp_parser_direct_declarator (cp_parser* parser,
                     return type, so are not those of the declared
                     function.  */
                  parser->default_arg_ok_p = false;
+
+                 /* Restore the state of local_variables_forbidden_p.  */
+                 parser->local_variables_forbidden_p
+                   = local_variables_forbidden_p;
                }
 
              /* Remove the function parms from scope.  */
@@ -20756,7 +20848,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                = cp_parser_declarator (parser, dcl_kind, flags,
                                        ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL,
-                                       member_p, friend_p);
+                                       member_p, friend_p,
+                                       /*static_p=*/false);
              parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
              first = false;
              /* Expect a `)'.  */
@@ -21039,6 +21132,38 @@ cp_parser_direct_declarator (cp_parser* parser,
 
            if (pack_expansion_p)
              maybe_warn_variadic_templates ();
+
+           /* We're looking for this case in [temp.res]:
+              A qualified-id is assumed to name a type if [...]
+              - it is a decl-specifier of the decl-specifier-seq of a
+                parameter-declaration in a declarator of a function or
+                function template declaration, ... */
+           if (cxx_dialect >= cxx2a
+               && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL)
+               && declarator->kind == cdk_id
+               && !at_class_scope_p ()
+               && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+             {
+               /* ...whose declarator-id is qualified.  If it isn't, never
+                  assume the parameters to refer to types.  */
+               if (qualifying_scope == NULL_TREE)
+                 flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+               else
+                 {
+                   /* Now we have something like
+                      template <typename T> int C::x(S::p);
+                      which can be a function template declaration or a
+                      variable template definition.  If name lookup for
+                      the declarator-id C::x finds one or more function
+                      templates, assume S::p to name a type.  Otherwise,
+                      don't.  */
+                   tree decl
+                     = cp_parser_lookup_name_simple (parser, unqualified_name,
+                                                     token->location);
+                   if (!is_overloaded_fn (decl))
+                     flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+                 }
+             }
          }
 
        handle_declarator:;
@@ -21650,7 +21775,8 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
                            CP_PARSER_FLAGS_NONE, NULL,
                            /*parenthesized_p=*/NULL,
                            /*member_p=*/false,
-                           /*friend_p=*/false);
+                           /*friend_p=*/false,
+                           /*static_p=*/false);
   /* Check to see if there really was a declarator.  */
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
@@ -22235,7 +22361,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         parenthesized_p,
                                         /*member_p=*/false,
-                                        /*friend_p=*/false);
+                                        /*friend_p=*/false,
+                                        /*static_p=*/false);
       parser->default_arg_ok_p = saved_default_arg_ok_p;
       /* After the declarator, allow more attributes.  */
       decl_specifiers.attributes
@@ -22416,7 +22543,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
 {
   tree default_argument = NULL_TREE;
   bool saved_greater_than_is_operator_p;
-  bool saved_local_variables_forbidden_p;
+  unsigned char saved_local_variables_forbidden_p;
   bool non_constant_p, is_direct_init;
 
   /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
@@ -22426,7 +22553,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
   /* Local variable names (and the `this' keyword) may not
      appear in a default argument.  */
   saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
-  parser->local_variables_forbidden_p = true;
+  parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN;
   /* Parse the assignment-expression.  */
   if (template_parm_p)
     push_deferring_access_checks (dk_no_deferred);
@@ -22480,11 +22607,25 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser,
                                                  bool in_function_try_block)
 {
   tree body, list;
-  const bool check_body_p =
-     DECL_CONSTRUCTOR_P (current_function_decl)
-     && DECL_DECLARED_CONSTEXPR_P (current_function_decl);
+  const bool check_body_p
+     = (DECL_CONSTRUCTOR_P (current_function_decl)
+       && DECL_DECLARED_CONSTEXPR_P (current_function_decl));
   tree last = NULL;
 
+  if (in_function_try_block
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && cxx_dialect < cxx2a)
+    {
+      if (DECL_CONSTRUCTOR_P (current_function_decl))
+       pedwarn (input_location, 0,
+                "function-try-block body of %<constexpr%> constructor only "
+                "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
+      else
+       pedwarn (input_location, 0,
+                "function-try-block body of %<constexpr%> function only "
+                "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
+    }
+
   /* Begin the function body.  */
   body = begin_function_body ();
   /* Parse the optional ctor-initializer.  */
@@ -22644,9 +22785,11 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
   /* If it's not a `}', then there is a non-trivial initializer.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
     {
+      bool designated;
       /* Parse the initializer list.  */
       CONSTRUCTOR_ELTS (initializer)
-       = cp_parser_initializer_list (parser, non_constant_p);
+       = cp_parser_initializer_list (parser, non_constant_p, &designated);
+      CONSTRUCTOR_IS_DESIGNATED_INIT (initializer) = designated;
       /* A trailing `,' token is allowed.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
        cp_lexer_consume_token (parser->lexer);
@@ -22766,10 +22909,12 @@ cp_parser_array_designator_p (cp_parser *parser)
    Returns a vec of constructor_elt.  The VALUE of each elt is an expression
    for the initializer.  If the INDEX of the elt is non-NULL, it is the
    IDENTIFIER_NODE naming the field to initialize.  NON_CONSTANT_P is
-   as for cp_parser_initializer.  */
+   as for cp_parser_initializer.  Set *DESIGNATED to a boolean whether there
+   are any designators.  */
 
 static vec<constructor_elt, va_gc> *
-cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
+cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p,
+                           bool *designated)
 {
   vec<constructor_elt, va_gc> *v = NULL;
   bool first_p = true;
@@ -22799,7 +22944,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          if (cxx_dialect < cxx2a)
            pedwarn (loc, OPT_Wpedantic,
                     "C++ designated initializers only available with "
-                    "-std=c++2a or -std=gnu++2a");
+                    "%<-std=c++2a%> or %<-std=gnu++2a%>");
          /* Consume the `.'.  */
          cp_lexer_consume_token (parser->lexer);
          /* Consume the identifier.  */
@@ -22946,6 +23091,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          IDENTIFIER_MARKED (designator) = 0;
     }
 
+  *designated = first_designator != NULL_TREE;
   return v;
 }
 
@@ -23074,7 +23220,9 @@ cp_parser_class_name (cp_parser *parser,
   decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
 
   /* If this is a typename, create a TYPENAME_TYPE.  */
-  if (typename_p && decl != error_mark_node)
+  if (typename_p
+      && decl != error_mark_node
+      && !is_overloaded_fn (decl))
     {
       decl = make_typename_type (scope, decl, typename_type,
                                 /*complain=*/tf_error);
@@ -23170,7 +23318,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
   cp_ensure_no_oacc_routine (parser);
 
   /* Issue an error message if type-definitions are forbidden here.  */
-  cp_parser_check_type_definition (parser);
+  bool type_definition_ok_p = cp_parser_check_type_definition (parser);
   /* Remember that we are defining one more class.  */
   ++parser->num_classes_being_defined;
   /* Inside the class, surrounding template-parameter-lists do not
@@ -23365,7 +23513,7 @@ cp_parser_class_specifier_1 (cp_parser* parser)
       cp_default_arg_entry *e;
       tree save_ccp, save_ccr;
 
-      if (any_erroneous_template_args_p (type))
+      if (!type_definition_ok_p || any_erroneous_template_args_p (type))
        {
          /* Skip default arguments, NSDMIs, etc, in order to improve
             error recovery (c++/71169, c++/71832).  */
@@ -23890,8 +24038,11 @@ cp_parser_class_head (cp_parser* parser,
   cp_parser_check_class_key (class_key, type);
 
   /* If this type was already complete, and we see another definition,
-     that's an error.  */
-  if (type != error_mark_node && COMPLETE_TYPE_P (type))
+     that's an error.  Likewise if the type is already being defined:
+     this can happen, eg, when it's defined from within an expression 
+     (c++/84605).  */
+  if (type != error_mark_node
+      && (COMPLETE_TYPE_P (type) || TYPE_BEING_DEFINED (type)))
     {
       error_at (type_start_token->location, "redefinition of %q#T",
                type);
@@ -24010,7 +24161,7 @@ cp_parser_type_parameter_key (cp_parser* parser)
           by the standard until C++17.  */
        pedwarn (token->location, OPT_Wpedantic, 
                 "ISO C++ forbids typename key in template template parameter;"
-                " use -std=c++17 or -std=gnu++17");
+                " use %<-std=c++17%> or %<-std=gnu++17%>");
     }
   else
     cp_parser_error (parser, "expected %<class%> or %<typename%>");
@@ -24396,8 +24547,8 @@ cp_parser_member_declaration (cp_parser* parser)
                      && identifier != NULL_TREE)
                    pedwarn (loc, 0,
                             "default member initializers for bit-fields "
-                            "only available with -std=c++2a or "
-                            "-std=gnu++2a");
+                            "only available with %<-std=c++2a%> or "
+                            "%<-std=gnu++2a%>");
 
                  initializer = cp_parser_save_nsdmi (parser);
                  if (identifier == NULL_TREE)
@@ -24445,6 +24596,7 @@ cp_parser_member_declaration (cp_parser* parser)
              cp_declarator *declarator;
              tree asm_specification;
              int ctor_dtor_or_conv_p;
+             bool static_p = (decl_specifiers.storage_class == sc_static);
 
              /* Parse the declarator.  */
              declarator
@@ -24453,7 +24605,7 @@ cp_parser_member_declaration (cp_parser* parser)
                                        &ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL,
                                        /*member_p=*/true,
-                                       friend_p);
+                                       friend_p, static_p);
 
              /* If something went wrong parsing the declarator, make sure
                 that we at least consume some tokens.  */
@@ -25031,7 +25183,17 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
              parser->type_definition_forbidden_message
              = G_("types may not be defined in an exception-specification");
 
-             expr = cp_parser_constant_expression (parser);
+             bool non_constant_p;
+             expr
+               = cp_parser_constant_expression (parser,
+                                                /*allow_non_constant=*/true,
+                                                &non_constant_p);
+             if (non_constant_p
+                 && !require_potential_rvalue_constant_expression (expr))
+               {
+                 expr = NULL_TREE;
+                 return_cond = true;
+               }
 
              /* Restore the saved message.  */
              parser->type_definition_forbidden_message = saved_message;
@@ -25206,8 +25368,11 @@ cp_parser_try_block (cp_parser* parser)
 
   cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
   if (parser->in_function_body
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
-    error ("%<try%> in %<constexpr%> function");
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && cxx_dialect < cxx2a)
+    pedwarn (input_location, 0,
+            "%<try%> in %<constexpr%> function only "
+            "available with %<-std=c++2a%> or %<-std=gnu++2a%>");
 
   try_block = begin_try_block ();
   cp_parser_compound_statement (parser, NULL, BCS_TRY_BLOCK, false);
@@ -25334,7 +25499,8 @@ cp_parser_exception_declaration (cp_parser* parser)
                                       /*ctor_dtor_or_conv_p=*/NULL,
                                       /*parenthesized_p=*/NULL,
                                       /*member_p=*/false,
-                                      /*friend_p=*/false);
+                                      /*friend_p=*/false,
+                                      /*static_p=*/false);
 
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
@@ -25673,9 +25839,11 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
       /* Look for the two `(' tokens.  */
       matching_parens outer_parens;
-      outer_parens.require_open (parser);
+      if (!outer_parens.require_open (parser))
+       ok = false;
       matching_parens inner_parens;
-      inner_parens.require_open (parser);
+      if (!inner_parens.require_open (parser))
+       ok = false;
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -26083,7 +26251,7 @@ cp_parser_std_attribute_spec (cp_parser *parser)
                  && !in_system_header_at (input_location))
                pedwarn (input_location, 0,
                         "attribute using prefix only available "
-                        "with -std=c++17 or -std=gnu++17");
+                        "with %<-std=c++17%> or %<-std=gnu++17%>");
 
              cp_lexer_consume_token (parser->lexer);
              cp_lexer_consume_token (parser->lexer);
@@ -26406,7 +26574,7 @@ cp_parser_requires_clause_opt (cp_parser *parser)
          && tok->u.value == ridpointers[RID_REQUIRES])
        {
          error_at (cp_lexer_peek_token (parser->lexer)->location,
-                   "%<requires%> only available with -fconcepts");
+                   "%<requires%> only available with %<-fconcepts%>");
          /* Parse and discard the requires-clause.  */
          cp_lexer_consume_token (parser->lexer);
          cp_parser_requires_clause (parser);
@@ -27698,7 +27866,7 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
          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",
+                  "or single non-type parameter of class type",
                   decl);
          else
            error ("literal operator template %qD has invalid parameter list."
@@ -28579,7 +28747,7 @@ cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field)
 static void
 cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 {
-  bool saved_local_variables_forbidden_p;
+  unsigned char saved_local_variables_forbidden_p;
   tree parm, parmdecl;
 
   /* While we're parsing the default args, we might (due to the
@@ -28591,7 +28759,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
   /* Local variable names (and the `this' keyword) may not appear
      in a default argument.  */
   saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
-  parser->local_variables_forbidden_p = true;
+  parser->local_variables_forbidden_p = LOCAL_VARS_AND_THIS_FORBIDDEN;
 
   push_defarg_context (fn);
 
@@ -28865,14 +29033,15 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
 {
   decl_specs->any_specifiers_p = true;
 
-  /* If the user tries to redeclare bool, char16_t, char32_t, or wchar_t
-     (with, for example, in "typedef int wchar_t;") we remember that
+  /* If the user tries to redeclare bool, char8_t, char16_t, char32_t, or
+     wchar_t (with, for example, in "typedef int wchar_t;") we remember that
      this is what happened.  In system headers, we ignore these
      declarations so that G++ can work with system headers that are not
      C++-safe.  */
   if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)
       && !type_definition_p
       && (type_spec == boolean_type_node
+         || type_spec == char8_type_node
          || type_spec == char16_type_node
          || type_spec == char32_type_node
          || type_spec == wchar_type_node)
@@ -29670,7 +29839,8 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
                                            &ctor_dtor_or_conv_p,
                                            /*parenthesized_p=*/NULL,
                                            /*member_p=*/true,
-                                           /*friend_p=*/false);
+                                           /*friend_p=*/false,
+                                           /*static_p=*/false);
                      peek = cp_lexer_peek_token (parser->lexer);
                      if (cp_parser_error_occurred (parser))
                        break;
@@ -31037,7 +31207,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
                                        &ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL,
                                        /*member_p=*/false,
-                                       /*friend_p=*/false);
+                                       /*friend_p=*/false,
+                                       /*static_p=*/false);
            }
 
          /* Look for attributes that apply to the ivar.  */
@@ -31595,7 +31766,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
       /* Parse the declarator.  */
       declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                                         CP_PARSER_FLAGS_NONE,
-                                        NULL, NULL, false, false);
+                                        NULL, NULL, false, false, false);
 
       /* Look for attributes that apply to the ivar.  */
       attributes = cp_parser_attributes_opt (parser);
@@ -32487,13 +32658,14 @@ cp_parser_oacc_data_clause_deviceptr (cp_parser *parser, tree list)
    seq */
 
 static tree
-cp_parser_oacc_simple_clause (cp_parser * /* parser  */,
-                             enum omp_clause_code code,
-                             tree list, location_t location)
+cp_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
+                             tree list)
 {
-  check_no_duplicate_clause (list, code, omp_clause_code_name[code], location);
-  tree c = build_omp_clause (location, code);
+  check_no_duplicate_clause (list, code, omp_clause_code_name[code], loc);
+
+  tree c = build_omp_clause (loc, code);
   OMP_CLAUSE_CHAIN (c) = list;
+
   return c;
 }
 
@@ -32549,13 +32721,13 @@ cp_parser_oacc_single_int_clause (cp_parser *parser, omp_clause_code code,
 */
 
 static tree
-cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind,
+cp_parser_oacc_shape_clause (cp_parser *parser, location_t loc,
+                            omp_clause_code kind,
                             const char *str, tree list)
 {
   const char *id = "num";
   cp_lexer *lexer = parser->lexer;
   tree ops[2] = { NULL_TREE, NULL_TREE }, c;
-  location_t loc = cp_lexer_peek_token (lexer)->location;
 
   if (kind == OMP_CLAUSE_VECTOR)
     id = "length";
@@ -32759,17 +32931,23 @@ cp_parser_oacc_wait_list (cp_parser *parser, location_t clause_loc, tree list)
 }
 
 /* OpenACC:
-   wait ( int-expr-list ) */
+   wait [( int-expr-list )] */
 
 static tree
 cp_parser_oacc_clause_wait (cp_parser *parser, tree list)
 {
   location_t location = cp_lexer_peek_token (parser->lexer)->location;
 
-  if (cp_lexer_peek_token (parser->lexer)->type != CPP_OPEN_PAREN)
-    return list;
+  if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
+    list = cp_parser_oacc_wait_list (parser, location, list);
+  else
+    {
+      tree c = build_omp_clause (location, OMP_CLAUSE_WAIT);
 
-  list = cp_parser_oacc_wait_list (parser, location, list);
+      OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
+      OMP_CLAUSE_CHAIN (c) = list;
+      list = c;
+    }
 
   return list;
 }
@@ -34770,8 +34948,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "async";
          break;
        case PRAGMA_OACC_CLAUSE_AUTO:
-         clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_AUTO,
-                                                clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_AUTO,
+                                                 clauses);
          c_name = "auto";
          break;
        case PRAGMA_OACC_CLAUSE_COLLAPSE:
@@ -34815,8 +34993,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "device_resident";
          break;
        case PRAGMA_OACC_CLAUSE_FINALIZE:
-         clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_FINALIZE,
-                                                 clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_FINALIZE,
+                                                 clauses);
          c_name = "finalize";
          break;
        case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
@@ -34826,7 +35004,7 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          break;
        case PRAGMA_OACC_CLAUSE_GANG:
          c_name = "gang";
-         clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_GANG,
+         clauses = cp_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_GANG,
                                                 c_name, clauses);
          break;
        case PRAGMA_OACC_CLAUSE_HOST:
@@ -34838,15 +35016,13 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "if";
          break;
        case PRAGMA_OACC_CLAUSE_IF_PRESENT:
-         clauses = cp_parser_oacc_simple_clause (parser,
-                                                 OMP_CLAUSE_IF_PRESENT,
-                                                 clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_IF_PRESENT,
+                                                 clauses);
          c_name = "if_present";
          break;
        case PRAGMA_OACC_CLAUSE_INDEPENDENT:
-         clauses = cp_parser_oacc_simple_clause (parser,
-                                                 OMP_CLAUSE_INDEPENDENT,
-                                                 clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_INDEPENDENT,
+                                                 clauses);
          c_name = "independent";
          break;
        case PRAGMA_OACC_CLAUSE_LINK:
@@ -34881,8 +35057,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          c_name = "reduction";
          break;
        case PRAGMA_OACC_CLAUSE_SEQ:
-         clauses = cp_parser_oacc_simple_clause (parser, OMP_CLAUSE_SEQ,
-                                                clauses, here);
+         clauses = cp_parser_oacc_simple_clause (here, OMP_CLAUSE_SEQ,
+                                                 clauses);
          c_name = "seq";
          break;
        case PRAGMA_OACC_CLAUSE_TILE:
@@ -34896,7 +35072,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          break;
        case PRAGMA_OACC_CLAUSE_VECTOR:
          c_name = "vector";
-         clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_VECTOR,
+         clauses = cp_parser_oacc_shape_clause (parser, here,
+                                                OMP_CLAUSE_VECTOR,
                                                 c_name, clauses);
          break;
        case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
@@ -34911,7 +35088,8 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          break;
        case PRAGMA_OACC_CLAUSE_WORKER:
          c_name = "worker";
-         clauses = cp_parser_oacc_shape_clause (parser, OMP_CLAUSE_WORKER,
+         clauses = cp_parser_oacc_shape_clause (parser, here,
+                                                OMP_CLAUSE_WORKER,
                                                 c_name, clauses);
          break;
        default:
@@ -36228,7 +36406,8 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
                                         /*ctor_dtor_or_conv_p=*/NULL,
                                         /*parenthesized_p=*/NULL,
                                         /*member_p=*/false,
-                                        /*friend_p=*/false);
+                                        /*friend_p=*/false,
+                                        /*static_p=*/false);
       attributes = cp_parser_attributes_opt (parser);
       asm_specification = cp_parser_asm_specification_opt (parser);