]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/parser.c
c++: Don't try to parse a function declaration as deduction guide [PR97663]
[gcc.git] / gcc / cp / parser.c
index 16f2a32bc0bffc0946bd60d9f624c6bea242565f..64dde058dd32173f9d3a610ac576a92cf1ebb7d9 100644 (file)
@@ -570,8 +570,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);
@@ -2251,7 +2253,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);
@@ -2506,7 +2508,7 @@ static cp_expr cp_parser_simple_cast_expression
 static tree cp_parser_global_scope_opt
   (cp_parser *, bool);
 static bool cp_parser_constructor_declarator_p
-  (cp_parser *, bool);
+  (cp_parser *, cp_parser_flags, bool);
 static tree cp_parser_function_definition_from_specifiers_and_declarator
   (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *);
 static tree cp_parser_function_definition_after_declarator
@@ -2648,6 +2650,7 @@ static bool cp_parser_init_statement_p
   (cp_parser *);
 static bool cp_parser_skip_to_closing_square_bracket
   (cp_parser *);
+static size_t cp_parser_skip_balanced_tokens (cp_parser *, size_t);
 
 /* Concept-related syntactic transformations */
 
@@ -3054,8 +3057,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;
@@ -3288,7 +3292,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)
@@ -3322,17 +3326,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))
        {
@@ -4551,7 +4555,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)
@@ -5331,7 +5335,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
@@ -5976,6 +5980,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);
@@ -6038,9 +6043,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
@@ -6050,18 +6064,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
@@ -6152,7 +6166,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
@@ -6168,7 +6182,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);
@@ -6183,11 +6197,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:
@@ -7993,7 +8007,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;
@@ -8508,12 +8522,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.  */
@@ -8542,9 +8556,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);
 
@@ -8552,10 +8566,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
@@ -9433,6 +9446,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;
@@ -9496,12 +9510,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.  */
@@ -9547,12 +9563,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
@@ -10090,7 +10105,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;
   }
@@ -10380,17 +10395,17 @@ 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;
     }
-  else if (parser->in_template_argument_list_p)
+  else if (parser->in_template_argument_list_p || processing_template_parmlist)
     {
       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;
@@ -10438,6 +10453,10 @@ cp_parser_lambda_expression (cp_parser* parser)
     parser->implicit_template_scope = 0;
     parser->auto_is_implicit_function_template_parm_p = false;
 
+    /* The body of a lambda in a discarded statement is not discarded.  */
+    bool discarded = in_discarded_stmt;
+    in_discarded_stmt = 0;
+
     /* By virtue of defining a local class, a lambda expression has access to
        the private variables of enclosing classes.  */
 
@@ -10468,6 +10487,8 @@ cp_parser_lambda_expression (cp_parser* parser)
 
     type = finish_struct (type, /*attributes=*/NULL_TREE);
 
+    in_discarded_stmt = discarded;
+
     parser->num_template_parameter_lists = saved_num_template_parameter_lists;
     parser->in_statement = in_statement;
     parser->in_switch_statement_p = in_switch_statement_p;
@@ -10537,6 +10558,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;
@@ -10572,11 +10595,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;
        }
 
@@ -10587,24 +10613,28 @@ 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,
-                      /*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;
        }
 
       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;
        }
@@ -10643,7 +10673,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;
@@ -10709,8 +10739,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;
+               }
            }
        }
 
@@ -10729,11 +10772,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.elements ())
+       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.  */
@@ -10766,7 +10826,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;
@@ -10781,11 +10842,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);
 
@@ -10797,6 +10858,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       ++parser->num_template_parameter_lists;
     }
 
+  /* Committee discussion supports allowing attributes here.  */
+  lambda_specs.attributes = cp_parser_attributes_opt (parser);
+
   /* The parameter-declaration-clause is optional (unless
      template-parameter-list was given), but must begin with an
      opening parenthesis if present.  */
@@ -10825,7 +10889,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);
@@ -10842,7 +10907,12 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
       /* Parse optional exception specification.  */
       exception_spec = cp_parser_exception_specification_opt (parser);
 
-      attributes = cp_parser_std_attribute_spec_seq (parser);
+      /* GCC 8 accepted attributes here, and this is the place for standard
+        C++11 attributes that appertain to the function type.  */
+      if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+       gnu_attrs = cp_parser_gnu_attributes_opt (parser);
+      else
+       std_attrs = cp_parser_std_attribute_spec_seq (parser);
 
       /* Parse optional trailing return type.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
@@ -10851,6 +10921,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
           return_type = cp_parser_trailing_type_id (parser);
         }
 
+      /* Also allow GNU attributes at the very end of the declaration, the
+        usual place for GNU attributes.  */
+      if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+       gnu_attrs = chainon (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 ();
@@ -10880,7 +10955,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);
@@ -10897,11 +10973,11 @@ 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);
+                     chainon (gnu_attrs, lambda_specs.attributes));
     if (fco != error_mark_node)
       {
        DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
@@ -11060,7 +11136,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)
@@ -11069,13 +11145,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))
@@ -11107,14 +11189,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;
 
@@ -11122,7 +11204,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;
 
@@ -11132,12 +11214,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;
 
@@ -11158,11 +11240,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;
 
@@ -11239,7 +11321,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);
@@ -11269,7 +11351,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");
 }
@@ -11698,7 +11780,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 `('.  */
@@ -11725,7 +11807,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);
          }
 
@@ -12712,7 +12794,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;
            }
        }
@@ -12736,7 +12818,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
@@ -13420,7 +13502,7 @@ cp_parser_simple_declaration (cp_parser* parser,
            if ((decl != error_mark_node
                 && DECL_INITIAL (decl) != error_mark_node)
                || cp_parser_uncommitted_to_tentative_parse_p (parser))
-             cp_parser_error (parser, "expected %<,%> or %<;%>");
+             cp_parser_error (parser, "expected %<;%>");
            /* Skip tokens until we reach the end of the statement.  */
            cp_parser_skip_to_end_of_statement (parser);
            /* If the next token is now a `;', consume it.  */
@@ -13678,7 +13760,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);
@@ -13933,6 +14015,19 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
         case RID_CONCEPT:
           ds = ds_concept;
           cp_lexer_consume_token (parser->lexer);
+
+         if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+           break;
+
+         /* 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:
@@ -13951,6 +14046,10 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
          ds = ds_typedef;
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
+
+         if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+           break;
+
          /* A constructor declarator cannot appear in a typedef.  */
          constructor_possible_p = false;
          /* The "typedef" keyword can only occur in a declaration; we
@@ -14035,7 +14134,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
        = (!found_decl_spec
           && constructor_possible_p
           && (cp_parser_constructor_declarator_p
-              (parser, decl_spec_seq_has_spec_p (decl_specs, ds_friend))));
+              (parser, flags, decl_spec_seq_has_spec_p (decl_specs,
+                                                        ds_friend))));
 
       /* If we don't have a DECL_SPEC yet, then we must be looking at
         a type-specifier.  */
@@ -14045,6 +14145,9 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
          bool is_cv_qualifier;
          tree type_spec;
 
+         if (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
+           flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS;
+
          type_spec
            = cp_parser_type_specifier (parser, flags,
                                        decl_specs,
@@ -14215,8 +14318,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);
@@ -14384,7 +14487,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, "");
@@ -16645,7 +16748,17 @@ cp_parser_template_name (cp_parser* parser,
     {
       if (TREE_DEPRECATED (decl)
          && deprecated_state != DEPRECATED_SUPPRESS)
-       warn_deprecated_use (decl, NULL_TREE);
+       {
+         tree d = DECL_TEMPLATE_RESULT (decl);
+         tree attr;
+         if (TREE_CODE (d) == TYPE_DECL)
+           attr = lookup_attribute ("deprecated",
+                                    TYPE_ATTRIBUTES (TREE_TYPE (d)));
+         else
+           attr = lookup_attribute ("deprecated",
+                                    DECL_ATTRIBUTES (d));
+         warn_deprecated_use (decl, attr);
+       }
     }
   else
     {
@@ -17626,17 +17739,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 ();
@@ -18525,7 +18638,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (TREE_CODE (type) == TYPENAME_TYPE)
        warning (OPT_Wattributes,
                 "attributes ignored on uninstantiated type");
-      else if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+      else if (tag_type != enum_type
+              && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM
+              && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
               && ! processing_explicit_instantiation)
        warning (OPT_Wattributes,
                 "attributes ignored on template instantiation");
@@ -18599,9 +18714,7 @@ cp_parser_enum_specifier (cp_parser* parser)
   bool is_unnamed = false;
   tree underlying_type = NULL_TREE;
   cp_token *type_start_token = NULL;
-  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
-
-  parser->colon_corrects_to_scope_p = false;
+  temp_override<bool> cleanup (parser->colon_corrects_to_scope_p, false);
 
   /* Parse tentatively so that we can back up if we don't find a
      enum-specifier.  */
@@ -18641,24 +18754,24 @@ cp_parser_enum_specifier (cp_parser* parser)
 
   push_deferring_access_checks (dk_no_check);
   nested_name_specifier
-      = cp_parser_nested_name_specifier_opt (parser,
-                                            /*typename_keyword_p=*/true,
-                                            /*check_dependency_p=*/false,
-                                            /*type_p=*/false,
-                                            /*is_declaration=*/false);
+    = cp_parser_nested_name_specifier_opt (parser,
+                                          /*typename_keyword_p=*/true,
+                                          /*check_dependency_p=*/false,
+                                          /*type_p=*/false,
+                                          /*is_declaration=*/false);
 
   if (nested_name_specifier)
     {
       tree name;
 
       identifier = cp_parser_identifier (parser);
-      name =  cp_parser_lookup_name (parser, identifier,
-                                    enum_type,
-                                    /*is_template=*/false,
-                                    /*is_namespace=*/false,
-                                    /*check_dependency=*/true,
-                                    /*ambiguous_decls=*/NULL,
-                                    input_location);
+      name = cp_parser_lookup_name (parser, identifier,
+                                   enum_type,
+                                   /*is_template=*/false,
+                                   /*is_namespace=*/false,
+                                   /*check_dependency=*/true,
+                                   /*ambiguous_decls=*/NULL,
+                                   input_location);
       if (name && name != error_mark_node)
        {
          type = TREE_TYPE (name);
@@ -18738,23 +18851,21 @@ cp_parser_enum_specifier (cp_parser* parser)
     {
       if (cxx_dialect < cxx11 || (!scoped_enum_p && !underlying_type))
        {
+         if (has_underlying_type)
+           cp_parser_commit_to_tentative_parse (parser);
          cp_parser_error (parser, "expected %<{%>");
          if (has_underlying_type)
-           {
-             type = NULL_TREE;
-             goto out;
-           }
+           return error_mark_node;
        }
       /* An opaque-enum-specifier must have a ';' here.  */
       if ((scoped_enum_p || underlying_type)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
        {
+         if (has_underlying_type)
+           cp_parser_commit_to_tentative_parse (parser);
          cp_parser_error (parser, "expected %<;%> or %<{%>");
          if (has_underlying_type)
-           {
-             type = NULL_TREE;
-             goto out;
-           }
+           return error_mark_node;
        }
     }
 
@@ -18770,9 +18881,7 @@ cp_parser_enum_specifier (cp_parser* parser)
          push_scope (nested_name_specifier);
        }
       else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL)
-       {
-         push_nested_namespace (nested_name_specifier);
-       }
+       push_nested_namespace (nested_name_specifier);
     }
 
   /* Issue an error message if type-definitions are forbidden here.  */
@@ -18932,12 +19041,8 @@ cp_parser_enum_specifier (cp_parser* parser)
          pop_scope (nested_name_specifier);
        }
       else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL)
-       {
-         pop_nested_namespace (nested_name_specifier);
-       }
+       pop_nested_namespace (nested_name_specifier);
     }
- out:
-  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
   return type;
 }
 
@@ -19162,7 +19267,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);
        }
 
@@ -19191,8 +19296,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).  */
@@ -19396,7 +19501,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))
@@ -19427,7 +19533,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);
     }
 
@@ -19489,7 +19595,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;
     }
 
@@ -19749,8 +19855,9 @@ 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) && parser->in_function_body)
+  if (cp_parser_allow_gnu_extensions_p (parser))
     for (;;)
       {
        cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -19764,7 +19871,12 @@ 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;
 
@@ -19776,6 +19888,8 @@ cp_parser_asm_definition (cp_parser* parser)
              }
            else
              inline_loc = loc;
+           if (!first_loc)
+             first_loc = loc;
            cp_lexer_consume_token (parser->lexer);
            continue;
 
@@ -19787,6 +19901,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;
 
@@ -19806,6 +19922,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;
@@ -20147,6 +20269,7 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       /* Handle C++17 deduction guides.  */
       if (!decl_specifiers->type
+         && !decl_specifiers->any_type_specifiers_p
          && ctor_dtor_or_conv_p <= 0
          && cxx_dialect >= cxx17)
        {
@@ -21126,7 +21249,13 @@ cp_parser_direct_declarator (cp_parser* parser,
                    tree decl
                      = cp_parser_lookup_name_simple (parser, unqualified_name,
                                                      token->location);
-                   if (!is_overloaded_fn (decl))
+                   if (!is_overloaded_fn (decl)
+                       /* Allow
+                          template<typename T>
+                          A<T>::A(T::type) { }  */
+                       && !(MAYBE_CLASS_TYPE_P (qualifying_scope)
+                            && constructor_name_p (unqualified_name,
+                                                   qualifying_scope)))
                      flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
                  }
              }
@@ -21872,6 +22001,18 @@ cp_parser_type_specifier_seq (cp_parser* parser,
       /* Check for attributes first.  */
       if (cp_next_tokens_can_be_attribute_p (parser))
        {
+         /* GNU attributes at the end of a declaration apply to the
+            declaration as a whole, not to the trailing return type.  So look
+            ahead to see if these attributes are at the end.  */
+         if (seen_type_specifier && is_trailing_return
+             && cp_next_tokens_can_be_gnu_attribute_p (parser))
+           {
+             size_t n = cp_parser_skip_attributes_opt (parser, 1);
+             cp_token *tok = cp_lexer_peek_nth_token (parser->lexer, n);
+             if (tok->type == CPP_SEMICOLON || tok->type == CPP_COMMA
+                 || tok->type == CPP_EQ || tok->type == CPP_OPEN_BRACE)
+               break;
+           }
          type_specifier_seq->attributes
            = attr_chainon (type_specifier_seq->attributes,
                            cp_parser_attributes_opt (parser));
@@ -22573,11 +22714,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.  */
@@ -22737,9 +22892,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);
@@ -22859,10 +23016,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;
@@ -22892,7 +23051,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.  */
@@ -23039,6 +23198,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          IDENTIFIER_MARKED (designator) = 0;
     }
 
+  *designated = first_designator != NULL_TREE;
   return v;
 }
 
@@ -23167,7 +23327,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);
@@ -23983,8 +24145,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);
@@ -24103,7 +24268,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%>");
@@ -24489,8 +24654,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)
@@ -25125,7 +25290,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;
@@ -25300,8 +25475,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);
@@ -25768,9 +25946,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);
@@ -26041,6 +26221,17 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
       /* A GNU attribute that takes an identifier in parameter.  */
       attr_flag = id_attr;
 
+    const attribute_spec *as
+      = lookup_attribute_spec (TREE_PURPOSE (attribute));
+    if (as == NULL)
+      {
+       /* For unknown attributes, just skip balanced tokens instead of
+          trying to parse the arguments.  */
+       for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n)
+         cp_lexer_consume_token (parser->lexer);
+       return attribute;
+      }
+
     vec = cp_parser_parenthesized_expression_list
       (parser, attr_flag, /*cast_p=*/false,
        /*allow_expansion_p=*/true,
@@ -26178,7 +26369,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);
@@ -26501,7 +26692,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);
@@ -27307,10 +27498,12 @@ cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p)
 
 /* Returns TRUE if the upcoming token sequence is the start of a
    constructor declarator or C++17 deduction guide.  If FRIEND_P is true, the
-   declarator is preceded by the `friend' specifier.  */
+   declarator is preceded by the `friend' specifier.  The parser flags FLAGS
+   is used to control type-specifier parsing.  */
 
 static bool
-cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
+cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
+                                   bool friend_p)
 {
   bool constructor_p;
   bool outside_class_specifier_p;
@@ -27457,12 +27650,29 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
          /* 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)
+             /* GNU attributes can actually appear both at the start of
+                a parameter and parenthesized declarator.
+                S (__attribute__((unused)) int);
+                is a constructor, but
+                S (__attribute__((unused)) foo) (int);
+                is a function declaration.  */
+             || (cp_parser_allow_gnu_extensions_p (parser)
+                 && cp_next_tokens_can_be_gnu_attribute_p (parser)))
+         /* A parameter declaration can also begin with [[attribute]].  */
+         && !cp_next_tokens_can_be_std_attribute_p (parser))
        {
          tree type;
          tree pushed_scope = NULL_TREE;
          unsigned saved_num_template_parameter_lists;
 
+         if (cp_next_tokens_can_be_gnu_attribute_p (parser))
+           {
+             unsigned int n = cp_parser_skip_gnu_attributes_opt (parser, 1);
+             while (--n)
+               cp_lexer_consume_token (parser->lexer);
+           }
+
          /* Names appearing in the type-specifier should be looked up
             in the scope of the class.  */
          if (current_class_type)
@@ -27489,9 +27699,20 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
            = parser->num_template_parameter_lists;
          parser->num_template_parameter_lists = 0;
 
-         /* Look for the type-specifier.  */
+         /* Look for the type-specifier.  It's not optional, but its typename
+            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,
-                                   CP_PARSER_FLAGS_NONE,
+                                   (friend_p ? CP_PARSER_FLAGS_NONE
+                                    : (flags & ~CP_PARSER_FLAGS_OPTIONAL)),
                                    /*decl_specs=*/NULL,
                                    /*is_declarator=*/true,
                                    /*declares_class_or_enum=*/NULL,
@@ -27761,7 +27982,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.  */;
@@ -27775,7 +27999,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;
@@ -27793,7 +28017,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."
@@ -28790,7 +29014,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;
 
@@ -28803,11 +29027,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.  */
@@ -28864,10 +29088,9 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   --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
@@ -32314,6 +32537,14 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
            decl = TREE_OPERAND (decl, 0);
          cp_lexer_consume_token (parser->lexer);
        }
+      else if (cp_parser_is_keyword (token, RID_FUNCTION_NAME)
+              || cp_parser_is_keyword (token, RID_PRETTY_FUNCTION_NAME)
+              || cp_parser_is_keyword (token, RID_C99_FUNCTION_NAME))
+       {
+         cp_id_kind idk;
+         decl = cp_parser_primary_expression (parser, false, false, false,
+                                              &idk);
+       }
       else
        {
          name = cp_parser_id_expression (parser, /*template_p=*/false,
@@ -32342,6 +32573,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                                           token->location);
            }
        }
+      if (outer_automatic_var_p (decl))
+       decl = process_outer_var_ref (decl, tf_warning_or_error);
       if (decl == error_mark_node)
        ;
       else if (kind != 0)
@@ -32385,7 +32618,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                  parser->colon_corrects_to_scope_p = false;
                  cp_lexer_consume_token (parser->lexer);
                  if (!cp_lexer_next_token_is (parser->lexer, CPP_COLON))
-                   low_bound = cp_parser_expression (parser);
+                   {
+                     low_bound = cp_parser_expression (parser);
+                     /* Later handling is not prepared to see through these.  */
+                     gcc_checking_assert (!location_wrapper_p (low_bound));
+                   }
                  if (!colon)
                    parser->colon_corrects_to_scope_p
                      = saved_colon_corrects_to_scope_p;
@@ -32405,7 +32642,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                        cp_parser_commit_to_tentative_parse (parser);
                      if (!cp_lexer_next_token_is (parser->lexer,
                                                   CPP_CLOSE_SQUARE))
-                       length = cp_parser_expression (parser);
+                       {
+                         length = cp_parser_expression (parser);
+                         /* Later handling is not prepared to see through these.  */
+                         gcc_checking_assert (!location_wrapper_p (length));
+                       }
                    }
                  /* Look for the closing `]'.  */
                  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE,
@@ -32585,13 +32826,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;
 }
 
@@ -32647,13 +32889,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";
@@ -32857,17 +33099,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;
 }
@@ -34735,8 +34983,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;
 
@@ -34818,7 +35068,7 @@ cp_parser_oacc_clause_async (cp_parser *parser, tree list)
       matching_parens parens;
       parens.consume_open (parser);
 
-      t = cp_parser_expression (parser);
+      t = cp_parser_assignment_expression (parser);
       if (t == error_mark_node
          || !parens.require_close (parser))
        cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
@@ -34847,6 +35097,9 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
   tree clauses = NULL;
   bool first = true;
 
+  /* Don't create location wrapper nodes within OpenACC clauses.  */
+  auto_suppress_location_wrappers sentinel;
+
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
       location_t here;
@@ -34868,8 +35121,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:
@@ -34913,8 +35166,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:
@@ -34924,7 +35177,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:
@@ -34936,15 +35189,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:
@@ -34979,8 +35230,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:
@@ -34994,7 +35245,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:
@@ -35009,7 +35261,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:
@@ -37588,9 +37841,9 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
          cp_parser_end_omp_structured_block (parser, save);
          stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
                                      block);
-         OMP_PARALLEL_COMBINED (stmt) = 1;
          if (ret == NULL_TREE)
            return ret;
+         OMP_PARALLEL_COMBINED (stmt) = 1;
          return stmt;
        }
       else if (!flag_openmp)  /* flag_openmp_simd  */
@@ -38528,6 +38781,10 @@ check_clauses:
 static tree
 cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok)
 {
+  /* Don't create location wrapper nodes within 'OMP_CLAUSE__CACHE_'
+     clauses.  */
+  auto_suppress_location_wrappers sentinel;
+
   tree stmt, clauses;
 
   clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE__CACHE_, NULL_TREE);
@@ -39282,6 +39539,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
   combiner = cp_parser_expression (parser);
   finish_expr_stmt (combiner);
   block = finish_omp_structured_block (block);
+  if (processing_template_decl)
+    block = build_stmt (input_location, EXPR_STMT, block);
   add_stmt (block);
 
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
@@ -39386,6 +39645,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
 
       block = finish_omp_structured_block (block);
       cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
+      if (processing_template_decl)
+       block = build_stmt (input_location, EXPR_STMT, block);
       add_stmt (block);
 
       if (ctor)
@@ -40590,7 +40851,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)
This page took 0.124167 seconds and 5 git commands to generate.