static cp_token_cache *cp_token_cache_new
   (cp_token *, cp_token *);
 static tree cp_parser_late_noexcept_specifier
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree);
 static void noexcept_override_late_checks
   (tree, tree);
 
 static tree cp_parser_tx_qualifier_opt
   (cp_parser *);
 static tree cp_parser_late_return_type_opt
-  (cp_parser *, cp_declarator *, tree &, cp_cv_quals);
+  (cp_parser *, cp_declarator *, tree &);
 static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
 static tree cp_parser_throw_expression
   (cp_parser *);
 static tree cp_parser_exception_specification_opt
-  (cp_parser *, cp_parser_flags, cp_cv_quals);
+  (cp_parser *, cp_parser_flags);
 static tree cp_parser_type_id_list
   (cp_parser *);
 static tree cp_parser_noexcept_specification_opt
-  (cp_parser *, cp_parser_flags, bool, bool *, bool, cp_cv_quals);
+  (cp_parser *, cp_parser_flags, bool, bool *, bool);
 
 /* GNU Extensions */
 
 
       /* Parse optional exception specification.  */
       exception_spec
-       = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE,
-                                                quals);
+       = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE);
 
       std_attrs = cp_parser_std_attribute_spec_seq (parser);
 
                  ref_qual = cp_parser_ref_qualifier_opt (parser);
                  /* Parse the tx-qualifier.  */
                  tree tx_qual = cp_parser_tx_qualifier_opt (parser);
-                 /* And the exception-specification.  */
+
+                 tree save_ccp = current_class_ptr;
+                 tree save_ccr = current_class_ref;
+                 if (memfn)
+                   /* DR 1207: 'this' is in scope after the cv-quals.  */
+                   inject_this_parameter (current_class_type, cv_quals);
+
+                 /* Parse the exception-specification.  */
                  exception_specification
                    = cp_parser_exception_specification_opt (parser,
-                                                            flags,
-                                                            cv_quals);
+                                                            flags);
 
                  attrs = cp_parser_std_attribute_spec_seq (parser);
 
                  tree gnu_attrs = NULL_TREE;
                  tree requires_clause = NULL_TREE;
                  late_return = (cp_parser_late_return_type_opt
-                                (parser, declarator, requires_clause,
-                                 memfn ? cv_quals : -1));
+                                (parser, declarator, requires_clause));
 
                  /* Parse the virt-specifier-seq.  */
                  virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
                     function.  */
                  parser->default_arg_ok_p = false;
 
+                 current_class_ptr = save_ccp;
+                 current_class_ref = save_ccr;
+
                  /* Restore the state of local_variables_forbidden_p.  */
                  parser->local_variables_forbidden_p
                    = local_variables_forbidden_p;
 
 static tree
 cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
-                               tree& requires_clause, cp_cv_quals quals)
+                               tree& requires_clause)
 {
   cp_token *token;
   tree type = NULL_TREE;
       && !(declare_simd_p || oacc_routine_p))
     return NULL_TREE;
 
-  tree save_ccp = current_class_ptr;
-  tree save_ccr = current_class_ref;
-  if (quals >= 0)
-    {
-      /* DR 1207: 'this' is in scope in the trailing return type.  */
-      inject_this_parameter (current_class_type, quals);
-    }
-
   if (token->type == CPP_DEREF)
     {
       /* Consume the ->.  */
       = cp_parser_late_parsing_oacc_routine (parser,
                                             declarator->attributes);
 
-  if (quals >= 0)
-    {
-      current_class_ptr = save_ccp;
-      current_class_ref = save_ccr;
-    }
-
   return type;
 }
 
   tree args = DECL_ARGUMENTS (decl);
 
   do_push_parm_decls (decl, args, /*nonparms=*/NULL);
+
+  if (args && is_this_parameter (args))
+    {
+      gcc_checking_assert (current_class_ptr == NULL_TREE);
+      current_class_ptr = NULL_TREE;
+      current_class_ref = cp_build_fold_indirect_ref (args);
+      current_class_ptr = args;
+    }
 }
 
 /* Undo the effects of inject_parm_decls.  */
 pop_injected_parms (void)
 {
   pop_bindings_and_leave_scope ();
+  current_class_ptr = current_class_ref = NULL_TREE;
 }
 
 /* Parse a class-specifier.
            parser->local_variables_forbidden_p |= THIS_FORBIDDEN;
 
          /* Now we can parse the noexcept-specifier.  */
-         spec = cp_parser_late_noexcept_specifier (parser, spec, decl);
+         spec = cp_parser_late_noexcept_specifier (parser, spec);
 
          if (spec != error_mark_node)
            TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec);
    member function.  */
 
 static tree
-cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg,
-                                  tree decl)
+cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg)
 {
   /* Make sure we've gotten something that hasn't been parsed yet.  */
   gcc_assert (TREE_CODE (default_arg) == DEFERRED_PARSE);
   cp_token_cache *tokens = DEFPARSE_TOKENS (default_arg);
   cp_parser_push_lexer_for_tokens (parser, tokens);
 
-  /* We need to know if this member function was declared `const'.  Look
-     at the this parameter to figure that out.  */
-  cp_cv_quals quals = type_memfn_quals (TREE_TYPE (decl));
   /* Parse the cached noexcept-specifier.  */
   tree parsed_arg
     = cp_parser_noexcept_specification_opt (parser,
                                            CP_PARSER_FLAGS_NONE,
                                            /*require_constexpr=*/true,
                                            /*consumed_expr=*/NULL,
-                                           /*return_cond=*/false, quals);
+                                           /*return_cond=*/false);
 
   /* Revert to the main lexer.  */
   cp_parser_pop_lexer (parser);
                                      cp_parser_flags flags,
                                      bool require_constexpr,
                                      bool* consumed_expr,
-                                     bool return_cond,
-                                     cp_cv_quals quals)
+                                     bool return_cond)
 {
   cp_token *token;
   const char *saved_message;
          matching_parens parens;
          parens.consume_open (parser);
 
-         tree save_ccp = current_class_ptr;
-         tree save_ccr = current_class_ref;
-
-         if (current_class_type)
-           inject_this_parameter (current_class_type, quals);
-
          if (require_constexpr)
            {
              /* Types may not be defined in an exception-specification.  */
            }
 
          parens.require_close (parser);
-
-         current_class_ptr = save_ccp;
-         current_class_ref = save_ccr;
        }
       else
        {
 
 static tree
 cp_parser_exception_specification_opt (cp_parser* parser,
-                                      cp_parser_flags flags,
-                                      cp_cv_quals quals)
+                                      cp_parser_flags flags)
 {
   cp_token *token;
   tree type_id_list;
     = cp_parser_noexcept_specification_opt (parser, flags,
                                            /*require_constexpr=*/true,
                                            /*consumed_expr=*/NULL,
-                                           /*return_cond=*/false, quals);
+                                           /*return_cond=*/false);
   if (type_id_list != NULL_TREE)
     return type_id_list;
 
                                                 CP_PARSER_FLAGS_NONE,
                                                 /*require_constexpr=*/true,
                                                 /*consumed_expr=*/NULL,
-                                                /*return_cond=*/true,
-                                                TYPE_UNQUALIFIED);
+                                                /*return_cond=*/true);
 
   /* Keep track if we're in the lexical scope of an outer transaction.  */
   new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
                                               CP_PARSER_FLAGS_NONE,
                                               /*require_constexpr=*/false,
                                               &noex_expr,
-                                              /*return_cond=*/true,
-                                              TYPE_UNQUALIFIED);
+                                              /*return_cond=*/true);
 
   if (!noex || !noex_expr
       || cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)