This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: Do not use trees to represent declarators


This patch to the C++ front end stops using trees to represent
declarators, in favor of a separate data structure allocated on a
separate obstack.  In general, we should only be using trees for
semi-permanent data structures, not transient things like declarators.
This decreases total memory usage and, more importantly, the amount of
memory allocated in the GC system.  This is worth about 1% of GC-able
memory on average, based on an unscientific sample of a few
compilations.

The patch is big, but largely mechanical.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-06-21  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.def (NEW_EXPR): Add a fourth slot.
	* cp-tree.h (PARMLIST_ELLIPSIS_P): Remove.
	(TREE_PARMLIST): Likewise.
	(CALL_DECLARATOR_PARMS): Likewise.
	(CALL_DECLARATOR_QUALS): Likewise.
	(CALL_DECLARATOR_EXCEPTION_SPEC): Likewise.
	(cp_declarator_kind): New type.
	(cp_parameter_declarator): Likewise.
	(cp_declarator): Likewise.
	(cp_error_declarator): Likewise.
	(no_parameters): Likewise.
	(groktypename): Change prototype.
	(start_decl): Likewise.
	(start_handler_parms): Likewise.
	(get_scope_of_declarator): Likewise.
	(start_function): Likewise.
	(start_preparsed_function): New function.
	(start_function): Change prototype.
	(start_method): Likewise.
	(grokfield): Likewise.
	(grokbitfield): Likewise.
	(build_new): Likewise.
	(make_pointer_declarator): Remove.
	(make_reference_declarator): Likewise.
	(make_call_declarator): Likewise.
	(set_quals_and_spec): Likewise.
	(process_template_parm): Change prototype.
	(begin_function_definition): Remove.
	(finish_parmlist): Remove.
	* decl.c (groktypename): Do not use trees to represent
	declarators.
	(start_decl): Likewise.
	(start_handler_parms): Remove.
	(get_scope_of_declarator): Reimplement.
	(grokdeclarator): Do not use trees to represent	declarators.
	(grokparms): Likewise.
	(start_function): Likewise.
	(start_method): Likewise.
	(build_void_list_mode): Do not use TREE_PARMLIST.
	* decl.h (grokdeclarator): Change prototype.
	* decl2.c (grok_method_quals): Robustify.
	(grok_x_components): Do not use trees to represent declarators.
	(grokfield): Likewise.
	(grokbitfield): Likewise.
	(start_objects): Build FUNCTION_DECLs, not declarators.
	(start_static_storage_duration_function): Likewise.
	* init.c (build_new): Simplify.
	* lex.c (make_pointer_declarator): Remove.
	(make_reference_declarator): Likewise.
	(make_call_declarator): Likewise.
	(set_quals_and_spec): Likewise.
	* method.c (use_thunk): Use start_preparsed_function.
	(synthesize_method): Likewise.
	(implicitly_declare_fn): Build FUNCTION_DECLs, not declarators.
	* optimize.c (maybe_clone_body): Use start_preparsed_function.
	* parser.c (cp_error_declarator): New variable.
	(declarator_obstack): Likewise.
	(alloc_declarator): New function.
	(make_declarator): Likewise.
	(make_id_declarator): Likewise.
	(make_pointer_declarator): Likewise.
	(make_reference_declarator): Likewise.
	(make_ptrmem_declarator): Likewise.
	(make_call_declarator): Likewise.
	(make_array_declarator): Likewise.
	(no_parameters): New variable.
	(make_parameter_declarator): Likewise.
	(cp_parser_check_for_definition_in_return_type): Do not use trees
	to represent declarators.
	(cp_parser_translation_unit): Likewise.
	(cp_parser_new_expression): Likewise.
	(cp_parser_new_type_id): Likewise.
	(cp_parser_new_declarator_opt): Likewise.
	(cp_parser_direct_new_declarator): Likewise.
	(cp_parser_condition): Likewise.
	(cp_parser_declaration_statement): Likewise.
	(cp_parser_declaration): Likewise.
	(cp_parser_conversion_type_id): Likewise.
	(cp_parser_conversion_declarator_opt): Likewise.
	(cp_parser_template_parameter_list): Likewise.
	(cp_parser_template_parameter): Likewise.
	(cp_parser_explicit_instantiation): Likewise.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_declarator): Likewise.
	(cp_parser_direct_declarator): Likewise.
	(cp_parser_type_id): Likewise.
	(cp_parser_parameter_declaration_clause): Likewise.
	(cp_parser_parameter_declaration_list): Likewise.
	(cp_parser_parameter_declaration): Likewise.
	(cp_parser_member_declaration): Likewise.
	(cp_parser_exception_declaration): Likewise.
	(cp_parser_check_declarator_template_parameters): Likewise.
	(cp_parser_function_definition_from_specifiers_and_declarator):
	Likewise.
	(cp_parser_save_member_function_body): Likewise.
	* pt.c (process_template_parm): Add is_non_type parameter.
	(convert_template_argument): Adjust call to groktypename.
	(tsubst_call_declarator_parms): Remove use of TREE_PARMLIST.
	(tsubst): Do not expect declarators.
	(tsubst_copy_and_build): Adjust NEW_EXPR case to handle additional
	argument.
	(instantiate_decl): Use start_preparsed_function.
	* semantics.c (begin_function_definition): Remove.
	(finish_parmlist): Remove.
	* cp-mudflap.c (mflang_flush_calls): Build FUNCTION_DECLs, not
	declarators.

Index: cp/cp-mudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-mudflap.c,v
retrieving revision 1.3
diff -c -5 -p -r1.3 cp-mudflap.c
*** cp/cp-mudflap.c	16 Jun 2004 01:21:29 -0000	1.3
--- cp/cp-mudflap.c	22 Jun 2004 02:13:15 -0000
*************** mflang_lookup_decl (const char* name)
*** 61,89 ****
  
  void
  mflang_flush_calls (tree enqueued_call_stmt_chain)
  {
    tree fnname, fndecl, body;
  
    /* Short-circuit!  */
    if (enqueued_call_stmt_chain == NULL_TREE)
      return;
  
    /* Create a ctor function declaration.  */
    fnname = get_identifier ("__static_initialization_and_destruction_mudflap");
! 
!   start_function (void_list_node,
! 		  make_call_declarator (fnname, void_list_node, NULL_TREE,
! 					NULL_TREE),
! 		  NULL_TREE, SF_DEFAULT);
  
    TREE_PUBLIC (current_function_decl) = 0;
    TREE_USED (current_function_decl) = 1;
    DECL_ARTIFICIAL (current_function_decl) = 1;
    mf_mark (current_function_decl);
  
    /* Generate the body, one statement at a time.  */
    body = begin_compound_stmt (BCS_FN_BODY);
  
    while (enqueued_call_stmt_chain)
      {
        tree next = TREE_CHAIN (enqueued_call_stmt_chain);
--- 61,88 ----
  
  void
  mflang_flush_calls (tree enqueued_call_stmt_chain)
  {
    tree fnname, fndecl, body;
+   tree type;
  
    /* Short-circuit!  */
    if (enqueued_call_stmt_chain == NULL_TREE)
      return;
  
    /* Create a ctor function declaration.  */
    fnname = get_identifier ("__static_initialization_and_destruction_mudflap");
!   type = build_function_type (void_type_node, void_list_node);
!   fndecl = build_lang_decl (FUNCTION_DECL, fnname, type);
  
    TREE_PUBLIC (current_function_decl) = 0;
    TREE_USED (current_function_decl) = 1;
    DECL_ARTIFICIAL (current_function_decl) = 1;
    mf_mark (current_function_decl);
  
    /* Generate the body, one statement at a time.  */
+   start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
    body = begin_compound_stmt (BCS_FN_BODY);
  
    while (enqueued_call_stmt_chain)
      {
        tree next = TREE_CHAIN (enqueued_call_stmt_chain);
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.85
diff -c -5 -p -r1.85 cp-tree.def
*** cp/cp-tree.def	31 May 2004 08:42:31 -0000	1.85
--- cp/cp-tree.def	22 Jun 2004 02:13:15 -0000
*************** DEFTREECODE (OFFSET_REF, "offset_ref", '
*** 49,60 ****
     PTRMEM_CST_MEMBER is the _DECL for `Y'.  */
  DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 0)
  
  /* For NEW_EXPR, operand 0 is the placement list.
     Operand 1 is the new-declarator.
!    Operand 2 is the initializer.  */
! DEFTREECODE (NEW_EXPR, "nw_expr", 'e', 3)
  DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", 'e', 3)
  
  /* For DELETE_EXPR, operand 0 is the store to be destroyed.
     Operand 1 is the value to pass to the destroying function
     saying whether the store should be deallocated as well.  */
--- 49,61 ----
     PTRMEM_CST_MEMBER is the _DECL for `Y'.  */
  DEFTREECODE (PTRMEM_CST, "ptrmem_cst", 'c', 0)
  
  /* For NEW_EXPR, operand 0 is the placement list.
     Operand 1 is the new-declarator.
!    Operand 2 is the number of elements in the array.
!    Operand 3 is the initializer.  */
! DEFTREECODE (NEW_EXPR, "nw_expr", 'e', 4)
  DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", 'e', 3)
  
  /* For DELETE_EXPR, operand 0 is the store to be destroyed.
     Operand 1 is the value to pass to the destroying function
     saying whether the store should be deallocated as well.  */
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.979
diff -c -5 -p -r1.979 cp-tree.h
*** cp/cp-tree.h	17 Jun 2004 21:11:38 -0000	1.979
--- cp/cp-tree.h	22 Jun 2004 02:13:15 -0000
*************** struct diagnostic_context;
*** 43,53 ****
        TREE_INDIRECT_USING (in NAMESPACE_DECL).
        ICS_USER_FLAG (in _CONV)
        CLEANUP_P (in TRY_BLOCK)
        AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
        PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
-       PARMLIST_ELLIPSIS_P (in PARMLIST)
        DECL_PRETTY_FUNCTION_P (in VAR_DECL)
        KOENIG_LOOKUP_P (in CALL_EXPR)
        STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
        EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
        BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
--- 43,52 ----
*************** struct diagnostic_context;
*** 62,72 ****
        DECL_INITIALIZED_P (in VAR_DECL)
     2: IDENTIFIER_OPNAME_P.
        TYPE_POLYMORPHIC_P (in _TYPE)
        ICS_THIS_FLAG (in _CONV)
        BINFO_LOST_PRIMARY_P (in BINFO)
-       TREE_PARMLIST (in TREE_LIST)
        DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
        STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
     3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
        BINFO_VTABLE_PATH_MARKED.
        BINFO_PUSHDECLS_MARKED.
--- 61,70 ----
*************** struct lang_type GTY(())
*** 1563,1579 ****
  
  /* The function to call.  */
  #define BV_FN(NODE) (TREE_VALUE (NODE))
  
  
- /* Nonzero for TREE_LIST node means that this list of things
-    is a list of parameters, as opposed to a list of expressions.  */
- #define TREE_PARMLIST(NODE) (TREE_LANG_FLAG_2 (NODE))
- 
- /* Nonzero for a parmlist means that this parmlist ended in ...  */
- #define PARMLIST_ELLIPSIS_P(NODE) TREE_LANG_FLAG_0 (NODE)
- 
  /* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
     this type can raise.  Each TREE_VALUE is a _TYPE.  The TREE_VALUE
     will be NULL_TREE to indicate a throw specification of `()', or
     no exceptions allowed.  */
  #define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_BINFO (NODE)
--- 1561,1570 ----
*************** struct lang_decl GTY(())
*** 2937,2958 ****
  #define FN_TRY_BLOCK_P(NODE)    TREE_LANG_FLAG_3 (TRY_BLOCK_CHECK (NODE))
  #define HANDLER_PARMS(NODE)     TREE_OPERAND (HANDLER_CHECK (NODE), 0)
  #define HANDLER_BODY(NODE)      TREE_OPERAND (HANDLER_CHECK (NODE), 1)
  #define HANDLER_TYPE(NODE)	TREE_TYPE (HANDLER_CHECK (NODE))
  
- /* The parameters for a call-declarator.  */
- #define CALL_DECLARATOR_PARMS(NODE) \
-   (TREE_PURPOSE (TREE_OPERAND (NODE, 1)))
- 
- /* The cv-qualifiers for a call-declarator.  */
- #define CALL_DECLARATOR_QUALS(NODE) \
-   (TREE_VALUE (TREE_OPERAND (NODE, 1)))
- 
- /* The exception-specification for a call-declarator.  */
- #define CALL_DECLARATOR_EXCEPTION_SPEC(NODE) \
-   (TREE_TYPE (NODE))
- 
  /* An enumeration of the kind of tags that C++ accepts.  */
  enum tag_types { 
    none_type = 0, /* Not a tag type.  */
    record_type,   /* "struct" types.  */
    class_type,    /* "class" types.  */
--- 2928,2937 ----
*************** extern GTY(()) operator_name_info_t oper
*** 3513,3522 ****
--- 3492,3584 ----
    [(int) LAST_CPLUS_TREE_CODE];
  /* Similar, but for assignment operators.  */
  extern GTY(()) operator_name_info_t assignment_operator_name_info
    [(int) LAST_CPLUS_TREE_CODE];
  
+ /* The various kinds of declarators.  */
+ 
+ typedef enum cp_declarator_kind {
+   cdk_id,
+   cdk_function,
+   cdk_array,
+   cdk_pointer,
+   cdk_reference,
+   cdk_ptrmem,
+   cdk_error
+ } cp_declarator_kind;
+ 
+ /* A declarator.  */
+ 
+ typedef struct cp_declarator cp_declarator;
+ 
+ typedef struct cp_parameter_declarator cp_parameter_declarator;
+ 
+ /* A parameter, before it has been semantically analyzed.  */
+ struct cp_parameter_declarator {
+   /* The next parameter, or NULL_TREE if none.  */
+   cp_parameter_declarator *next;
+   /* The decl-specifiers-seq for the parameter.  */
+   tree decl_specifiers;
+   /* The declarator for the parameter.  */
+   cp_declarator *declarator;
+   /* The default-argument expression, or NULL_TREE, if none.  */
+   tree default_argument;
+   /* True iff this is the first parameter in the list and the
+      parameter sequence ends with an ellipsis.  */
+   bool ellipsis_p;
+ };
+ 
+ /* A declarator.  */
+ struct cp_declarator {
+   /* The kind of declarator.  */
+   cp_declarator_kind kind;
+   /* Attributes that apply to this declarator.  */
+   tree attributes;
+   /* For all but cdk_id and cdk_error, the contained declarator.  For
+      cdk_id and cdk_error, guaranteed to be NULL.  */
+   cp_declarator *declarator;
+   union {
+     /* For identifiers.  */
+     struct {
+       /* The name of the function -- an IDENTIFIER_NODE, BIT_NOT_EXPR,
+ 	 TEMPLATE_ID_EXPR, or SCOPE_REF.  */
+       tree name;
+       /* If this is the name of a function, what kind of special
+ 	 function (if any).  */
+       special_function_kind sfk;
+     } id;
+     /* For functions.  */
+     struct {
+       /* The parameters to the function.  */
+       cp_parameter_declarator *parameters;
+       /* The cv-qualifiers for the function.  */
+       tree qualifiers;
+       /* The exception-specification for the function.  */
+       tree exception_specification;
+     } function;
+     /* For arrays.  */
+     struct {
+       /* The bounds to the array.  */
+       tree bounds;
+     } array;
+     /* For cdk_pointer, cdk_reference, and cdk_ptrmem.  */
+     struct {
+       /* The cv-qualifiers for the pointer.  */
+       tree qualifiers;
+       /* For cdk_ptrmem, the class type containing the member.  */
+       tree class_type;
+     } pointer;
+   } u;
+ };
+ 
+ /* An erroneous declarator.  */
+ extern cp_declarator *cp_error_declarator;
+ 
+ /* A parameter list indicating for a function with no parameters,
+    e.g  "int f(void)".  */
+ extern cp_parameter_declarator *no_parameters;
+ 
  /* in call.c */
  extern bool check_dtor_name (tree, tree);
  
  extern tree build_vfield_ref			(tree, tree);
  extern tree build_conditional_expr		(tree, tree, tree);
*************** extern tree push_library_fn			(tree, tre
*** 3658,3694 ****
  extern tree push_void_library_fn		(tree, tree);
  extern tree push_throw_library_fn		(tree, tree);
  extern int init_type_desc			(void);
  extern tree check_tag_decl			(tree);
  extern tree shadow_tag				(tree);
! extern tree groktypename			(tree);
! extern tree start_decl				(tree, tree, int, tree, tree);
  extern void start_decl_1			(tree);
  extern void cp_finish_decl			(tree, tree, tree, int);
  extern void finish_decl				(tree, tree, tree);
  extern void maybe_inject_for_scope_var          (tree);
- extern tree start_handler_parms                 (tree, tree);
  extern int complete_array_type			(tree, tree, int);
  extern tree build_ptrmemfunc_type		(tree);
  extern tree build_ptrmem_type                   (tree, tree);
  /* the grokdeclarator prototype is in decl.h */
  extern int copy_fn_p				(tree);
! extern tree get_scope_of_declarator             (tree);
  extern void grok_special_member_properties	(tree);
  extern int grok_ctor_properties			(tree, tree);
  extern bool grok_op_properties			(tree, int, bool);
  extern tree xref_tag				(enum tag_types, tree, bool, bool);
  extern tree xref_tag_from_type			(tree, tree, int);
  extern void xref_basetypes			(tree, tree);
  extern tree start_enum				(tree);
  extern void finish_enum				(tree);
  extern void build_enumerator			(tree, tree, tree);
! extern int start_function			(tree, tree, tree, int);
  extern tree begin_function_body			(void);
  extern void finish_function_body		(tree);
  extern tree finish_function			(int);
! extern tree start_method			(tree, tree, tree);
  extern tree finish_method			(tree);
  extern void maybe_register_incomplete_var       (tree);
  extern void complete_vars			(tree);
  extern void finish_stmt				(void);
  extern void print_other_binding_stack		(struct cp_binding_level *);
--- 3720,3756 ----
  extern tree push_void_library_fn		(tree, tree);
  extern tree push_throw_library_fn		(tree, tree);
  extern int init_type_desc			(void);
  extern tree check_tag_decl			(tree);
  extern tree shadow_tag				(tree);
! extern tree groktypename			(tree, const cp_declarator *);
! extern tree start_decl				(const cp_declarator *, tree, int, tree, tree);
  extern void start_decl_1			(tree);
  extern void cp_finish_decl			(tree, tree, tree, int);
  extern void finish_decl				(tree, tree, tree);
  extern void maybe_inject_for_scope_var          (tree);
  extern int complete_array_type			(tree, tree, int);
  extern tree build_ptrmemfunc_type		(tree);
  extern tree build_ptrmem_type                   (tree, tree);
  /* the grokdeclarator prototype is in decl.h */
  extern int copy_fn_p				(tree);
! extern tree get_scope_of_declarator             (const cp_declarator *);
  extern void grok_special_member_properties	(tree);
  extern int grok_ctor_properties			(tree, tree);
  extern bool grok_op_properties			(tree, int, bool);
  extern tree xref_tag				(enum tag_types, tree, bool, bool);
  extern tree xref_tag_from_type			(tree, tree, int);
  extern void xref_basetypes			(tree, tree);
  extern tree start_enum				(tree);
  extern void finish_enum				(tree);
  extern void build_enumerator			(tree, tree, tree);
! extern void start_preparsed_function            (tree, tree, int);
! extern int start_function			(tree, const cp_declarator *, tree);
  extern tree begin_function_body			(void);
  extern void finish_function_body		(tree);
  extern tree finish_function			(int);
! extern tree start_method			(tree, const cp_declarator *, tree);
  extern tree finish_method			(tree);
  extern void maybe_register_incomplete_var       (tree);
  extern void complete_vars			(tree);
  extern void finish_stmt				(void);
  extern void print_other_binding_stack		(struct cp_binding_level *);
*************** extern void maybe_make_one_only	(tree);
*** 3733,3744 ****
  extern void grokclassfn	(tree, tree, enum overload_flags, tree);
  extern tree grok_array_decl (tree, tree);
  extern tree delete_sanity (tree, tree, bool, int);
  extern tree check_classfn (tree, tree, tree);
  extern void check_member_template (tree);
! extern tree grokfield (tree, tree, tree, tree, tree);
! extern tree grokbitfield (tree, tree, tree);
  extern tree groktypefield			(tree, tree);
  extern void cplus_decl_attributes (tree *, tree, int);
  extern void finish_anon_union (tree);
  extern tree finish_table (tree, tree, tree, int);
  extern tree coerce_new_type (tree);
--- 3795,3806 ----
  extern void grokclassfn	(tree, tree, enum overload_flags, tree);
  extern tree grok_array_decl (tree, tree);
  extern tree delete_sanity (tree, tree, bool, int);
  extern tree check_classfn (tree, tree, tree);
  extern void check_member_template (tree);
! extern tree grokfield (const cp_declarator *, tree, tree, tree, tree);
! extern tree grokbitfield (const cp_declarator *, tree, tree);
  extern tree groktypefield			(tree, tree);
  extern void cplus_decl_attributes (tree *, tree, int);
  extern void finish_anon_union (tree);
  extern tree finish_table (tree, tree, tree, int);
  extern tree coerce_new_type (tree);
*************** extern tree build_init				(tree, tree, i
*** 3812,3840 ****
  extern int is_aggr_type				(tree, int);
  extern tree get_aggr_from_typedef		(tree, int);
  extern tree get_type_value			(tree);
  extern tree build_zero_init       		(tree, tree, bool);
  extern tree build_offset_ref			(tree, tree, bool);
! extern tree build_new				(tree, tree, tree, int);
  extern tree build_vec_init			(tree, tree, tree, int);
  extern tree build_x_delete			(tree, int, tree);
  extern tree build_delete			(tree, tree, special_function_kind, int, int);
  extern void push_base_cleanups			(void);
  extern tree build_vbase_delete			(tree, tree);
  extern tree build_vec_delete			(tree, tree, special_function_kind, int);
  extern tree create_temporary_var                (tree);
  extern void initialize_vtbl_ptrs                (tree);
  extern tree build_java_class_ref                (tree);
  
- /* in input.c */
- 
  /* in lex.c */
  extern void cxx_dup_lang_specific_decl		(tree);
- extern tree make_pointer_declarator		(tree, tree);
- extern tree make_reference_declarator		(tree, tree);
- extern tree make_call_declarator		(tree, tree, tree, tree);
- extern void set_quals_and_spec			(tree, tree, tree);
  extern void print_parse_statistics		(void);
  extern void do_pending_inlines			(void);
  extern void yyungetc				(int, int);
  extern void snarf_method			(tree);
  
--- 3874,3896 ----
  extern int is_aggr_type				(tree, int);
  extern tree get_aggr_from_typedef		(tree, int);
  extern tree get_type_value			(tree);
  extern tree build_zero_init       		(tree, tree, bool);
  extern tree build_offset_ref			(tree, tree, bool);
! extern tree build_new				(tree, tree, tree, tree, int);
  extern tree build_vec_init			(tree, tree, tree, int);
  extern tree build_x_delete			(tree, int, tree);
  extern tree build_delete			(tree, tree, special_function_kind, int, int);
  extern void push_base_cleanups			(void);
  extern tree build_vbase_delete			(tree, tree);
  extern tree build_vec_delete			(tree, tree, special_function_kind, int);
  extern tree create_temporary_var                (tree);
  extern void initialize_vtbl_ptrs                (tree);
  extern tree build_java_class_ref                (tree);
  
  /* in lex.c */
  extern void cxx_dup_lang_specific_decl		(tree);
  extern void print_parse_statistics		(void);
  extern void do_pending_inlines			(void);
  extern void yyungetc				(int, int);
  extern void snarf_method			(tree);
  
*************** extern void begin_specialization        
*** 3877,3887 ****
  extern void reset_specialization                (void);
  extern void end_specialization                  (void);
  extern void begin_explicit_instantiation        (void);
  extern void end_explicit_instantiation          (void);
  extern tree check_explicit_specialization       (tree, tree, int, int);
! extern tree process_template_parm		(tree, tree);
  extern tree end_template_parm_list		(tree);
  extern void end_template_decl			(void);
  extern tree current_template_args		(void);
  extern tree push_template_decl			(tree);
  extern tree push_template_decl_real             (tree, int);
--- 3933,3943 ----
  extern void reset_specialization                (void);
  extern void end_specialization                  (void);
  extern void begin_explicit_instantiation        (void);
  extern void end_explicit_instantiation          (void);
  extern tree check_explicit_specialization       (tree, tree, int, int);
! extern tree process_template_parm		(tree, tree, bool);
  extern tree end_template_parm_list		(tree);
  extern void end_template_decl			(void);
  extern tree current_template_args		(void);
  extern tree push_template_decl			(tree);
  extern tree push_template_decl_real             (tree, int);
*************** extern tree finish_increment_expr       
*** 4079,4093 ****
  extern tree finish_this_expr                    (void);
  extern tree finish_pseudo_destructor_expr       (tree, tree, tree);
  extern tree finish_unary_op_expr                (enum tree_code, tree);
  extern tree finish_compound_literal             (tree, tree);
  extern tree finish_fname                        (tree);
- extern int begin_function_definition            (tree, tree, tree);
  extern void finish_translation_unit             (void);
  extern tree finish_template_type_parm           (tree, tree);
  extern tree finish_template_template_parm       (tree, tree);
- extern tree finish_parmlist                     (tree, int);
  extern tree begin_class_definition              (tree);
  extern void finish_default_args                 (void);
  extern tree finish_member_class_template        (tree);
  extern void finish_template_decl                (tree);
  extern tree finish_template_type                (tree, tree, int);
--- 4135,4147 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1220
diff -c -5 -p -r1.1220 decl.c
*** cp/decl.c	17 Jun 2004 01:24:03 -0000	1.1220
--- cp/decl.c	22 Jun 2004 02:13:16 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 51,61 ****
  #include "diagnostic.h"
  #include "debug.h"
  #include "timevar.h"
  #include "tree-flow.h"
  
! static tree grokparms (tree, tree *);
  static const char *redeclaration_error_message (tree, tree);
  
  static int decl_jump_unsafe (tree);
  static void require_complete_types_for_parms (tree);
  static int ambi_op_p (enum tree_code);
--- 51,61 ----
  #include "diagnostic.h"
  #include "debug.h"
  #include "timevar.h"
  #include "tree-flow.h"
  
! static tree grokparms (const cp_parameter_declarator *, tree *);
  static const char *redeclaration_error_message (tree, tree);
  
  static int decl_jump_unsafe (tree);
  static void require_complete_types_for_parms (tree);
  static int ambi_op_p (enum tree_code);
*************** shadow_tag (tree declspecs)
*** 3564,3594 ****
      {
        fixup_anonymous_aggr (t);
  
        if (TYPE_FIELDS (t))
  	{
! 	  tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
! 				      NULL);
  	  finish_anon_union (decl);
  	}
      }
  
    return t;
  }
  
  /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
  
  tree
! groktypename (tree typename)
  {
    tree specs, attrs;
    tree type;
!   if (TREE_CODE (typename) != TREE_LIST)
!     return typename;
!   split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
!   type = grokdeclarator (TREE_VALUE (typename), specs,
! 			 TYPENAME, 0, &attrs);
    if (attrs)
      cplus_decl_attributes (&type, attrs, 0);
    return type;
  }
  
--- 3564,3591 ----
      {
        fixup_anonymous_aggr (t);
  
        if (TYPE_FIELDS (t))
  	{
! 	  tree decl = grokdeclarator (/*declarator=*/NULL, 
! 				      declspecs, NORMAL, 0, NULL);
  	  finish_anon_union (decl);
  	}
      }
  
    return t;
  }
  
  /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
  
  tree
! groktypename (tree type_specifiers, const cp_declarator *declarator)
  {
    tree specs, attrs;
    tree type;
!   split_specs_attrs (type_specifiers, &specs, &attrs);
!   type = grokdeclarator (declarator, specs, TYPENAME, 0, &attrs);
    if (attrs)
      cplus_decl_attributes (&type, attrs, 0);
    return type;
  }
  
*************** groktypename (tree typename)
*** 3606,3616 ****
     instead.  However, external and forward declarations of functions
     do go through here.  Structure field declarations are done by
     grokfield and not through here.  */
  
  tree
! start_decl (tree declarator, 
              tree declspecs, 
              int initialized, 
              tree attributes, 
              tree prefix_attributes)
  {
--- 3603,3613 ----
     instead.  However, external and forward declarations of functions
     do go through here.  Structure field declarations are done by
     grokfield and not through here.  */
  
  tree
! start_decl (const cp_declarator *declarator, 
              tree declspecs, 
              int initialized, 
              tree attributes, 
              tree prefix_attributes)
  {
*************** start_cleanup_fn (void)
*** 5122,5132 ****
        TREE_USED (parmdecl) = 1;
        DECL_ARGUMENTS (fndecl) = parmdecl;
      }
  
    pushdecl (fndecl);
!   start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED);
  
    interface_unknown = old_interface_unknown;
    interface_only = old_interface_only;
  
    pop_lang_context ();
--- 5119,5129 ----
        TREE_USED (parmdecl) = 1;
        DECL_ARGUMENTS (fndecl) = parmdecl;
      }
  
    pushdecl (fndecl);
!   start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
  
    interface_unknown = old_interface_unknown;
    interface_only = old_interface_only;
  
    pop_lang_context ();
*************** expand_static_init (tree decl, tree init
*** 5284,5312 ****
      }
    else
      static_aggregates = tree_cons (init, decl, static_aggregates);
  }
  
- /* Finish the declaration of a catch-parameter.  */
- 
- tree
- start_handler_parms (tree declspecs, tree declarator)
- {
-   tree decl;
-   if (declspecs)
-     {
-       decl = grokdeclarator (declarator, declspecs, CATCHPARM,
- 			     1, NULL);
-       if (decl == NULL_TREE)
- 	error ("invalid catch parameter");
-     }
-   else
-     decl = NULL_TREE;
- 
-   return decl;
- }
- 
  
  /* Make TYPE a complete type based on INITIAL_VALUE.
     Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
     2 if there was no information (in which case assume 0 if DO_DEFAULT).  */
  
--- 5281,5290 ----
*************** compute_array_index_type (tree name, tre
*** 6146,6189 ****
  /* Returns the scope (if any) in which the entity declared by
     DECLARATOR will be located.  If the entity was declared with an
     unqualified name, NULL_TREE is returned.  */
  
  tree
! get_scope_of_declarator (tree declarator)
  {
!   if (!declarator)
!     return NULL_TREE;
!   
!   switch (TREE_CODE (declarator))
!     {
!     case CALL_EXPR:
!     case ARRAY_REF:
!     case INDIRECT_REF:
!     case ADDR_EXPR:
!       /* For any of these, the main declarator is the first operand.  */
!       return get_scope_of_declarator (TREE_OPERAND
! 				      (declarator, 0));
! 
!     case SCOPE_REF:
!       /* For a pointer-to-member, continue descending.  */
!       if (TREE_CODE (TREE_OPERAND (declarator, 1))
! 	  == INDIRECT_REF)
! 	return get_scope_of_declarator (TREE_OPERAND
! 					(declarator, 1));
!       /* Otherwise, if the declarator-id is a SCOPE_REF, the scope in
! 	 which the declaration occurs is the first operand.  */
!       return TREE_OPERAND (declarator, 0);
! 
!     case TREE_LIST:
!       /* Attributes to be applied. The declarator is TREE_VALUE.  */
!       return get_scope_of_declarator (TREE_VALUE (declarator));
!       
!     default:
!       /* Otherwise, we have a declarator-id which is not a qualified
! 	 name; the entity will be declared in the current scope.  */
!       return NULL_TREE;
!     }
  }
  
  /* Returns an ARRAY_TYPE for an array with SIZE elements of the
     indicated TYPE.  If non-NULL, NAME is the NAME of the declaration
     with this type.  */
--- 6124,6148 ----
  /* Returns the scope (if any) in which the entity declared by
     DECLARATOR will be located.  If the entity was declared with an
     unqualified name, NULL_TREE is returned.  */
  
  tree
! get_scope_of_declarator (const cp_declarator *declarator)
  {
!   while (declarator && declarator->kind != cdk_id)
!     declarator = declarator->declarator;
! 
!   /* If the declarator-id is a SCOPE_REF, the scope in which the
!      declaration occurs is the first operand.  */
!   if (declarator
!       && declarator->u.id.name
!       && TREE_CODE (declarator->u.id.name) == SCOPE_REF)
!     return TREE_OPERAND (declarator->u.id.name, 0);
! 
!   /* Otherwise, the declarator is not a quablified name; the entity will
!      be declared in the current scope.  */
!   return NULL_TREE;
  }
  
  /* Returns an ARRAY_TYPE for an array with SIZE elements of the
     indicated TYPE.  If non-NULL, NAME is the NAME of the declaration
     with this type.  */
*************** check_special_function_return_type (spec
*** 6338,6348 ****
  
     when grokdeclarator is called for `S::f', the CURRENT_CLASS_TYPE
     should not be `S'.  */
  
  tree
! grokdeclarator (tree declarator,
                  tree declspecs,
                  enum decl_context decl_context,
                  int initialized,
                  tree* attrlist)
  {
--- 6297,6307 ----
  
     when grokdeclarator is called for `S::f', the CURRENT_CLASS_TYPE
     should not be `S'.  */
  
  tree
! grokdeclarator (const cp_declarator *declarator,
                  tree declspecs,
                  enum decl_context decl_context,
                  int initialized,
                  tree* attrlist)
  {
*************** grokdeclarator (tree declarator,
*** 6358,6371 ****
    int defaulted_int = 0;
    int extern_langp = 0;
    tree dependant_name = NULL_TREE;
    
    tree typedef_decl = NULL_TREE;
!   const char *name;
    tree typedef_type = NULL_TREE;
    int funcdef_flag = 0;
!   enum tree_code innermost_code = ERROR_MARK;
    int bitfield = 0;
  #if 0
    /* See the code below that used this.  */
    tree decl_attr = NULL_TREE;
  #endif
--- 6317,6330 ----
    int defaulted_int = 0;
    int extern_langp = 0;
    tree dependant_name = NULL_TREE;
    
    tree typedef_decl = NULL_TREE;
!   const char *name = NULL;
    tree typedef_type = NULL_TREE;
    int funcdef_flag = 0;
!   cp_declarator_kind innermost_code = cdk_error;
    int bitfield = 0;
  #if 0
    /* See the code below that used this.  */
    tree decl_attr = NULL_TREE;
  #endif
*************** grokdeclarator (tree declarator,
*** 6374,6393 ****
       so that we can warn about default return values, or explicit
       return values which do not match prescribed defaults.  */
    special_function_kind sfk = sfk_none;
  
    tree dname = NULL_TREE;
-   tree ctype = current_class_type;
    tree ctor_return_type = NULL_TREE;
    enum overload_flags flags = NO_SPECIAL;
    tree quals = NULL_TREE;
    tree raises = NULL_TREE;
    int template_count = 0;
-   tree in_namespace = NULL_TREE;
    tree returned_attrs = NULL_TREE;
-   tree scope = NULL_TREE;
    tree parms = NULL_TREE;
  
    RIDBIT_RESET_ALL (specbits);
    if (decl_context == FUNCDEF)
      funcdef_flag = 1, decl_context = NORMAL;
    else if (decl_context == MEMFUNCDEF)
--- 6333,6363 ----
       so that we can warn about default return values, or explicit
       return values which do not match prescribed defaults.  */
    special_function_kind sfk = sfk_none;
  
    tree dname = NULL_TREE;
    tree ctor_return_type = NULL_TREE;
    enum overload_flags flags = NO_SPECIAL;
    tree quals = NULL_TREE;
    tree raises = NULL_TREE;
    int template_count = 0;
    tree returned_attrs = NULL_TREE;
    tree parms = NULL_TREE;
+   const cp_declarator *id_declarator;
+   /* The unqualified name of the declarator; either an
+      IDENTIFIER_NODE, BIT_NOT_EXPR, or TEMPLATE_ID_EXPR.  */
+   tree unqualified_id;
+   /* The class type, if any, in which this entity is located,
+      or NULL_TREE if none.  Note that this value may be different from
+      the current class type; for example if an attempt is made to declare
+      "A::f" inside "B", this value will be "A".  */
+   tree ctype = current_class_type;
+   /* The NAMESPACE_DECL for the namespace in which this entity is
+      located.  If an unqualified name is used to declare the entity,
+      this value will be NULL_TREE, even if the entity is located at
+      namespace scope.  */ 
+   tree in_namespace = NULL_TREE;
  
    RIDBIT_RESET_ALL (specbits);
    if (decl_context == FUNCDEF)
      funcdef_flag = 1, decl_context = NORMAL;
    else if (decl_context == MEMFUNCDEF)
*************** grokdeclarator (tree declarator,
*** 6395,6680 ****
    else if (decl_context == BITFIELD)
      bitfield = 1, decl_context = FIELD;
  
    /* Look inside a declarator for the name being declared
       and get it as a string, for an error message.  */
!   {
!     tree *next = &declarator;
!     tree decl;
!     name = NULL;
! 
!     while (next && *next)
!       {
! 	decl = *next;
! 	switch (TREE_CODE (decl))
! 	  {
! 	  case TREE_LIST:
! 	    /* For attributes.  */
! 	    next = &TREE_VALUE (decl);
! 	    break;
! 
! 	  case COND_EXPR:
! 	    ctype = NULL_TREE;
! 	    next = &TREE_OPERAND (decl, 0);
! 	    break;
! 
! 	  case BIT_NOT_EXPR:	/* For C++ destructors!  */
! 	    {
! 	      tree name = TREE_OPERAND (decl, 0);
! 	      tree rename = NULL_TREE;
! 
! 	      my_friendly_assert (flags == NO_SPECIAL, 152);
! 	      flags = DTOR_FLAG;
! 	      sfk = sfk_destructor;
! 	      if (TYPE_P (name))
! 		TREE_OPERAND (decl, 0) = name = constructor_name (name);
! 	      my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
! 	      if (ctype == NULL_TREE)
! 		{
! 		  if (current_class_type == NULL_TREE)
! 		    {
! 		      error ("destructors must be member functions");
! 		      flags = NO_SPECIAL;
! 		    }
! 		  else
! 		    {
! 		      tree t = constructor_name (current_class_type);
! 		      if (t != name)
! 			rename = t;
! 		    }
! 		}
! 	      else
! 		{
! 		  tree t = constructor_name (ctype);
! 		  if (t != name)
! 		    rename = t;
! 		}
! 
! 	      if (rename)
! 		{
! 		  error ("destructor `%T' must match class name `%T'",
! 			    name, rename);
! 		  TREE_OPERAND (decl, 0) = rename;
! 		}
! 	      next = &name;
  	    }
! 	    break;
! 
! 	  case ADDR_EXPR:	/* C++ reference declaration */
! 	    /* Fall through.  */
! 	  case ARRAY_REF:
! 	  case INDIRECT_REF:
! 	    ctype = NULL_TREE;
! 	    innermost_code = TREE_CODE (decl);
! 	    next = &TREE_OPERAND (decl, 0);
! 	    break;
! 
! 	  case CALL_EXPR:
! 	    innermost_code = TREE_CODE (decl);
! 	    if (decl_context == FIELD && ctype == NULL_TREE)
! 	      ctype = current_class_type;
! 	    if (ctype
! 		&& TREE_OPERAND (decl, 0)
! 		&& (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
! 		    && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 0)),
! 					   ctype)))
! 	      TREE_OPERAND (decl, 0) = constructor_name (ctype);
! 	    next = &TREE_OPERAND (decl, 0);
! 	    decl = *next;
! 	    if (ctype != NULL_TREE
! 		&& decl != NULL_TREE && flags != DTOR_FLAG
! 		&& constructor_name_p (decl, ctype))
! 	      {
! 		sfk = sfk_constructor;
! 		ctor_return_type = ctype;
! 	      }
! 	    ctype = NULL_TREE;
! 	    break;
! 
! 	  case TEMPLATE_ID_EXPR:
! 	      {
! 		tree fns = TREE_OPERAND (decl, 0);
! 
! 		dname = fns;
! 		if (TREE_CODE (dname) == COMPONENT_REF)
! 		  dname = TREE_OPERAND (dname, 1);
! 		if (TREE_CODE (dname) != IDENTIFIER_NODE)
! 		  {
! 		    my_friendly_assert (is_overloaded_fn (dname),
! 					19990331);
! 		    dname = DECL_NAME (get_first_fn (dname));
! 		  }
! 	      }
! 	  /* Fall through.  */
! 
! 	  case IDENTIFIER_NODE:
! 	    if (TREE_CODE (decl) == IDENTIFIER_NODE)
! 	      dname = decl;
! 
! 	    next = 0;
  
! 	    if (C_IS_RESERVED_WORD (dname))
! 	      {
! 		error ("declarator-id missing; using reserved word `%D'",
! 			  dname);
! 		name = IDENTIFIER_POINTER (dname);
! 	      }
! 	    else if (!IDENTIFIER_TYPENAME_P (dname))
! 	      name = IDENTIFIER_POINTER (dname);
! 	    else
  	      {
! 		my_friendly_assert (flags == NO_SPECIAL, 154);
! 		flags = TYPENAME_FLAG;
! 		ctor_return_type = TREE_TYPE (dname);
! 		sfk = sfk_conversion;
! 		if (is_typename_at_global_scope (dname))
! 		  name = IDENTIFIER_POINTER (dname);
! 		else
! 		  name = "<invalid operator>";
! 	      }
! 	    break;
! 
! 	    /* C++ extension */
! 	  case SCOPE_REF:
! 	    {
! 	      /* Perform error checking, and decide on a ctype.  */
! 	      tree cname = TREE_OPERAND (decl, 0);
! 	      if (cname == NULL_TREE)
! 		ctype = NULL_TREE;
! 	      else if (TREE_CODE (cname) == NAMESPACE_DECL)
! 		{
! 		  ctype = NULL_TREE;
! 		  in_namespace = TREE_OPERAND (decl, 0);
! 		}
! 	      else if (! is_aggr_type (cname, 1))
! 		ctype = NULL_TREE;
! 	      /* Must test TREE_OPERAND (decl, 1), in case user gives
! 		 us `typedef (class::memfunc)(int); memfunc *memfuncptr;'  */
! 	      else if (TREE_OPERAND (decl, 1)
! 		       && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
! 		ctype = cname;
! 	      else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
! 		       || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
! 		{
! 	  	  /* This might be declaring a member of a template
! 		     parm to be a friend.  */
! 		  ctype = cname;
! 		  dependant_name = TREE_OPERAND (decl, 1);
! 		}
! 	      else if (ctype == NULL_TREE)
! 		ctype = cname;
! 	      else if (TREE_COMPLEXITY (decl) == current_class_depth)
! 		;
! 	      else
! 		{
! 		  if (! UNIQUELY_DERIVED_FROM_P (cname, ctype))
! 		    {
! 		      error ("type `%T' is not derived from type `%T'",
! 				cname, ctype);
! 		      ctype = NULL_TREE;
! 		    }
! 		  else
! 		    ctype = cname;
! 		}
! 
! 	      /* It is valid to write:
  
  		   class C { void f(); };
  		   typedef C D;
  		   void D::f();
  
  		 The standard is not clear about whether `typedef const C D' is
  		 legal; as of 2002-09-15 the committee is considering
  		 that question.  EDG 3.0 allows that syntax.
  		 Therefore, we do as well.  */
! 	      if (ctype)
! 		ctype = TYPE_MAIN_VARIANT (ctype);
! 	      /* Update the declarator so that when we process it
! 		 again the correct type is present.  */
! 	      TREE_OPERAND (decl, 0) = ctype;
! 
! 	      if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
! 		  && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)),
! 					 ctype))
! 		TREE_OPERAND (decl, 1) = constructor_name (ctype);
! 	      next = &TREE_OPERAND (decl, 1);
! 	      decl = *next;
! 	      if (ctype)
  		{
! 		  tree name = decl;
  
! 		  if (TREE_CODE (name) == BIT_NOT_EXPR)
! 		    name = TREE_OPERAND (name, 0);
  
! 		  if (!constructor_name_p (decl, ctype))
! 		    ;
! 		  else if (decl == name)
! 		    {
! 		      sfk = sfk_constructor;
! 		      ctor_return_type = ctype;
! 		    }
! 		  else
  		    {
! 		      sfk = sfk_destructor;
! 		      ctor_return_type = ctype;
! 		      flags = DTOR_FLAG;
! 		      TREE_OPERAND (decl, 0) = constructor_name (ctype);
! 		      next = &TREE_OPERAND (decl, 0);
  		    }
  		}
! 	    }
! 	    break;
  
! 	  case ERROR_MARK:
! 	    next = 0;
! 	    break;
  
! 	  case TYPE_DECL:
! 	    /* Parse error puts this typespec where
! 	       a declarator should go.  */
! 	    error ("`%T' specified as declarator-id", DECL_NAME (decl));
! 	    if (TREE_TYPE (decl) == current_class_type)
! 	      error ("  perhaps you want `%T' for a constructor",
! 			current_class_name);
! 	    dname = DECL_NAME (decl);
! 	    name = IDENTIFIER_POINTER (dname);
! 
! 	    /* Avoid giving two errors for this.  */
! 	    IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
! 
! 	    declspecs = tree_cons (NULL_TREE, integer_type_node, declspecs);
! 	    *next = dname;
! 	    next = 0;
  	    break;
  
! 	  case BASELINK:
! 	    next = &BASELINK_FUNCTIONS (decl);
  	    break;
  
! 	  case TEMPLATE_DECL:
! 	    /* Sometimes, we see a template-name used as part of a 
! 	       decl-specifier like in 
! 	          std::allocator alloc;
! 	       Handle that gracefully.  */
! 	    error ("invalid use of template-name '%E' in a declarator", decl);
! 	    return error_mark_node;
  	    break;
! 	    
  	  default:
! 	    my_friendly_assert (0, 20020917);
  	  }
!       }
!   }
  
    /* A function definition's declarator must have the form of
       a function declarator.  */
  
!   if (funcdef_flag && innermost_code != CALL_EXPR)
      return 0;
  
    if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
!       && innermost_code != CALL_EXPR
        && ! (ctype && declspecs == NULL_TREE))
      {
        error ("declaration of `%D' as non-function", dname);
        return void_type_node;
      }
--- 6365,6518 ----
    else if (decl_context == BITFIELD)
      bitfield = 1, decl_context = FIELD;
  
    /* Look inside a declarator for the name being declared
       and get it as a string, for an error message.  */
!   for (id_declarator = declarator; 
!        id_declarator; 
!        id_declarator = id_declarator->declarator)
!     {
!       if (id_declarator->kind != cdk_id)
! 	innermost_code = id_declarator->kind;
! 
!       switch (id_declarator->kind)
! 	{
! 	case cdk_function:
! 	  if (id_declarator->declarator
! 	      && id_declarator->declarator->kind == cdk_id)
! 	    {
! 	      sfk = id_declarator->declarator->u.id.sfk;
! 	      if (sfk == sfk_destructor)
! 		flags = DTOR_FLAG;
  	    }
! 	  break;
  
! 	case cdk_id:
! 	  {
! 	    tree decl = id_declarator->u.id.name;
! 	    if (!decl)
! 	      break;
! 	    if (TREE_CODE (decl) == SCOPE_REF)
  	      {
! 		tree qualifying_scope = TREE_OPERAND (decl, 0);
! ;
! 		/* It is valid to write:
  
  		   class C { void f(); };
  		   typedef C D;
  		   void D::f();
  
  		 The standard is not clear about whether `typedef const C D' is
  		 legal; as of 2002-09-15 the committee is considering
  		 that question.  EDG 3.0 allows that syntax.
  		 Therefore, we do as well.  */
! 		if (qualifying_scope && TYPE_P (qualifying_scope))
! 		  {
! 		    ctype = TYPE_MAIN_VARIANT (qualifying_scope); 
! 		    if (innermost_code != cdk_function
! 			&& current_class_type
! 			&& !UNIQUELY_DERIVED_FROM_P (ctype, 
! 						     current_class_type))
! 		      {
! 			error ("type `%T' is not derived from type `%T'",
! 			       ctype, current_class_type);
! 			ctype = NULL_TREE;
! 		      }
! 		    TREE_OPERAND (decl, 0) = ctype; 
! 		  }
! 		else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
! 		  in_namespace = qualifying_scope;
! 		decl = TREE_OPERAND (decl, 1);
! 	      }
! 	    if (TREE_CODE (decl) == BASELINK)
! 	      decl = BASELINK_FUNCTIONS (decl);
! 	    switch (TREE_CODE (decl))
! 	      {
! 	      case BIT_NOT_EXPR:
  		{
! 		  tree type = TREE_OPERAND (decl, 0);
! 		  type = constructor_name (type);
! 		  name = IDENTIFIER_POINTER (type);
! 		}
! 		break;
  
! 	      case TEMPLATE_ID_EXPR:
! 		{
! 		  tree fns = TREE_OPERAND (decl, 0);
  
! 		  dname = fns;
! 		  if (TREE_CODE (dname) == COMPONENT_REF)
! 		    dname = TREE_OPERAND (dname, 1);
! 		  if (TREE_CODE (dname) != IDENTIFIER_NODE)
  		    {
! 		      my_friendly_assert (is_overloaded_fn (dname),
! 					  19990331);
! 		      dname = DECL_NAME (get_first_fn (dname));
  		    }
  		}
! 		/* Fall through.  */
  
! 	      case IDENTIFIER_NODE:
! 		if (TREE_CODE (decl) == IDENTIFIER_NODE)
! 		  dname = decl;
! 
! 		if (C_IS_RESERVED_WORD (dname))
! 		  {
! 		    error ("declarator-id missing; using reserved word `%D'",
! 			   dname);
! 		    name = IDENTIFIER_POINTER (dname);
! 		  }
! 		else if (!IDENTIFIER_TYPENAME_P (dname))
! 		  name = IDENTIFIER_POINTER (dname);
! 		else
! 		  {
! 		    my_friendly_assert (flags == NO_SPECIAL, 154);
! 		    flags = TYPENAME_FLAG;
! 		    ctor_return_type = TREE_TYPE (dname);
! 		    sfk = sfk_conversion;
! 		    if (is_typename_at_global_scope (dname))
! 		      name = IDENTIFIER_POINTER (dname);
! 		    else
! 		      name = "<invalid operator>";
! 		  }
! 		break;
! 
! 	      case TYPE_DECL:
! 		dname = constructor_name (TREE_TYPE (decl));
! 		name = IDENTIFIER_POINTER (dname);
! 		break;
  
! 	      default:
! 		abort ();
! 	      }
  	    break;
  
! 	  case cdk_array:
! 	  case cdk_pointer:
! 	  case cdk_reference:
! 	  case cdk_ptrmem:
  	    break;
  
! 	  case cdk_error:
  	    break;
! 
  	  default:
! 	    abort ();
  	  }
! 	}
!       if (id_declarator->kind == cdk_id)
! 	break;
!     }
  
    /* A function definition's declarator must have the form of
       a function declarator.  */
  
!   if (funcdef_flag && innermost_code != cdk_function)
      return 0;
  
    if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
!       && innermost_code != cdk_function
        && ! (ctype && declspecs == NULL_TREE))
      {
        error ("declaration of `%D' as non-function", dname);
        return void_type_node;
      }
*************** grokdeclarator (tree declarator,
*** 7149,7162 ****
  	      int op = 0;
  
  	      if (declarator)
  		{
  		  /* Avoid trying to get an operand off an identifier node.  */
! 		  if (TREE_CODE (declarator) == IDENTIFIER_NODE)
! 		    tmp = declarator;
  		  else
! 		    tmp = TREE_OPERAND (declarator, 0);
  		  op = IDENTIFIER_OPNAME_P (tmp);
  		  if (IDENTIFIER_TYPENAME_P (tmp))
  		    {
  		      if (is_typename_at_global_scope (tmp))
  			name = IDENTIFIER_POINTER (tmp);
--- 6987,7000 ----
  	      int op = 0;
  
  	      if (declarator)
  		{
  		  /* Avoid trying to get an operand off an identifier node.  */
! 		  if (declarator->kind != cdk_id)
! 		    tmp = declarator->declarator->u.id.name;
  		  else
! 		    tmp = declarator->u.id.name;
  		  op = IDENTIFIER_OPNAME_P (tmp);
  		  if (IDENTIFIER_TYPENAME_P (tmp))
  		    {
  		      if (is_typename_at_global_scope (tmp))
  			name = IDENTIFIER_POINTER (tmp);
*************** grokdeclarator (tree declarator,
*** 7211,7328 ****
      }
  
    if (nclasses > 0 && friendp)
      error ("storage class specifiers invalid in friend function declarations");
  
!   scope = get_scope_of_declarator (declarator);
! 
!   /* Now figure out the structure of the declarator proper.
!      Descend through it, creating more complex types, until we reach
!      the declared identifier (or NULL_TREE, in an abstract declarator).  */
! 
!   while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
! 	 && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
!     {
!       /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
! 	 an INDIRECT_REF (for *...),
! 	 a CALL_EXPR (for ...(...)),
! 	 an identifier (for the name being declared)
! 	 or a null pointer (for the place in an absolute declarator
! 	 where the name was omitted).
! 	 For the last two cases, we have just exited the loop.
! 
! 	 For C++ it could also be
! 	 a SCOPE_REF (for class :: ...).  In this case, we have converted
! 	 sensible names to types, and those are the values we use to
! 	 qualify the member name.
! 	 an ADDR_EXPR (for &...),
! 	 a BIT_NOT_EXPR (for destructors)
! 
! 	 At this point, TYPE is the type of elements of an array,
! 	 or for a function to return, or for a pointer to point to.
! 	 After this sequence of ifs, TYPE is the type of the
! 	 array or function or pointer, and DECLARATOR has had its
! 	 outermost layer removed.  */
! 
!       if (type == error_mark_node)
! 	{
! 	  if (declarator == error_mark_node)
! 	    return error_mark_node;
! 	  else if (TREE_CODE (declarator) == SCOPE_REF)
! 	    declarator = TREE_OPERAND (declarator, 1);
! 	  else
! 	    declarator = TREE_OPERAND (declarator, 0);
! 	  continue;
! 	}
!       if (quals != NULL_TREE
! 	  && (declarator == NULL_TREE
! 	      || TREE_CODE (declarator) != SCOPE_REF))
  	{
! 	  if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE)
! 	    ctype = TYPE_METHOD_BASETYPE (type);
! 	  if (ctype != NULL_TREE)
! 	    {
! 	      tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
! 	      grok_method_quals (ctype, dummy, quals);
! 	      type = TREE_TYPE (dummy);
! 	      quals = NULL_TREE;
! 	    }
! 	}
  
!       switch (TREE_CODE (declarator))
! 	{
! 	case TREE_LIST:
! 	  {
! 	    /* We encode a declarator with embedded attributes using
! 	       a TREE_LIST.  */
! 	    tree attrs = TREE_PURPOSE (declarator);
! 	    tree inner_decl;
! 	    int attr_flags;
! 
! 	    declarator = TREE_VALUE (declarator);
! 	    inner_decl = declarator;
! 	    while (inner_decl != NULL_TREE
! 		   && TREE_CODE (inner_decl) == TREE_LIST)
! 	      inner_decl = TREE_VALUE (inner_decl);
! 	    attr_flags = 0;
! 	    if (inner_decl == NULL_TREE
! 		|| TREE_CODE (inner_decl) == IDENTIFIER_NODE)
! 	      attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
! 	    if (TREE_CODE (inner_decl) == CALL_EXPR)
! 	      attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
! 	    if (TREE_CODE (inner_decl) == ARRAY_REF)
! 	      attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
! 	    returned_attrs = decl_attributes (&type,
! 					      chainon (returned_attrs, attrs),
! 					      attr_flags);
! 	  }
  	  break;
  
! 	case ARRAY_REF:
! 	  {
! 	    tree size = TREE_OPERAND (declarator, 1);
! 	    declarator = TREE_OPERAND (declarator, 0);
  
! 	    type = create_array_type_for_decl (dname, type, size);
  
! 	    if (declarator
! 		&& (TREE_CODE (declarator) == INDIRECT_REF
! 		    || TREE_CODE (declarator) == ADDR_EXPR))
! 	      /* We can never complete an array type which is the target of a
! 		 pointer, so go ahead and lay it out.  */
! 	      layout_type (type);
  
! 	    ctype = NULL_TREE;
! 	  }
  	  break;
  
! 	case CALL_EXPR:
  	  {
  	    tree arg_types;
  	    int funcdecl_p;
- 	    tree inner_parms = CALL_DECLARATOR_PARMS (declarator);
- 	    tree inner_decl = TREE_OPERAND (declarator, 0);
  
  	    /* Declaring a function type.
  	       Make sure we have a valid type for the function to return.  */
  
  	    /* We now know that the TYPE_QUALS don't apply to the
--- 7049,7137 ----
      }
  
    if (nclasses > 0 && friendp)
      error ("storage class specifiers invalid in friend function declarations");
  
!   if (!id_declarator)
!     unqualified_id = NULL_TREE;
!   else
!     {
!       unqualified_id = id_declarator->u.id.name;
!       if (TREE_CODE (unqualified_id) == SCOPE_REF)
! 	unqualified_id = TREE_OPERAND (unqualified_id, 1);
!       if (TREE_CODE (unqualified_id) == BASELINK)
! 	unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
!       switch (TREE_CODE (unqualified_id))
  	{
! 	case BIT_NOT_EXPR:
! 	  unqualified_id 
! 	    = constructor_name (TREE_OPERAND (unqualified_id, 0));
! 	  break;
! 	  
! 	case TYPE_DECL:
! 	  unqualified_id 
! 	    = constructor_name (TREE_TYPE (unqualified_id));
! 	  break;
  
! 	case IDENTIFIER_NODE:
! 	case TEMPLATE_ID_EXPR:
  	  break;
+ 	
+ 	default:
+ 	  abort ();
+ 	}
+     }
  
!   /* Determine the type of the entity declared by recurring on the
!      declarator.  */
!   for (; 
!        declarator && declarator->kind != cdk_id;
!        declarator = declarator->declarator)
!     {
!       const cp_declarator *inner_declarator;
!       tree attrs;
  
!       if (type == error_mark_node)
! 	return error_mark_node;
  
!       inner_declarator = declarator->declarator;
  
!       attrs = declarator->attributes;
!       if (attrs)
! 	{
! 	  int attr_flags;
! 	  
! 	  attr_flags = 0;
! 	  if (declarator == NULL || declarator->kind == cdk_id)
! 	    attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
! 	  if (declarator->kind == cdk_function)
! 	    attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
! 	  if (declarator->kind == cdk_array)
! 	    attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
! 	  returned_attrs = decl_attributes (&type,
! 					    chainon (returned_attrs, attrs),
! 					    attr_flags);
! 	}
! 
!       switch (declarator->kind)
! 	{
! 	case cdk_array:
! 	  type = create_array_type_for_decl (dname, type, 
! 					     declarator->u.array.bounds);
! 	  if (inner_declarator
! 	      && (inner_declarator->kind == cdk_pointer
! 		  || inner_declarator->kind == cdk_reference
! 		  || inner_declarator->kind == cdk_ptrmem))
! 	    /* We can never complete an array type which is the
! 	       target of a pointer, so go ahead and lay it out.  */
! 	    layout_type (type);
  	  break;
  
! 	case cdk_function:
  	  {
  	    tree arg_types;
  	    int funcdecl_p;
  
  	    /* Declaring a function type.
  	       Make sure we have a valid type for the function to return.  */
  
  	    /* We now know that the TYPE_QUALS don't apply to the
*************** grokdeclarator (tree declarator,
*** 7340,7378 ****
  	      {
  		error ("`%s' declared as function returning an array", name);
  		type = integer_type_node;
  	      }
  
- 	    if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
- 	      inner_decl = TREE_OPERAND (inner_decl, 1);
- 
- 	    if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR)
- 	      inner_decl = dname;
- 
  	    /* Pick up type qualifiers which should be applied to `this'.  */
! 	    quals = CALL_DECLARATOR_QUALS (declarator);
  
  	    /* Pick up the exception specifications.  */
! 	    raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator);
  
  	    /* Say it's a definition only for the CALL_EXPR
  	       closest to the identifier.  */
! 	    funcdecl_p
! 	      = inner_decl
! 	      && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
! 		  || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR
! 		  || TREE_CODE (inner_decl) == BIT_NOT_EXPR);
  
  	    if (ctype == NULL_TREE
  		&& decl_context == FIELD
  		&& funcdecl_p
  		&& (friendp == 0 || dname == current_class_name))
  	      ctype = current_class_type;
  
  	    if (ctype && sfk == sfk_conversion)
  	      TYPE_HAS_CONVERSION (ctype) = 1;
! 	    if (ctype && constructor_name_p (dname, ctype))
  	      {
  		/* We are within a class's scope. If our declarator name
  		   is the same as the class name, and we are defining
  		   a function, then it is a constructor/destructor, and
  		   therefore returns a void type.  */
--- 7149,7178 ----
  	      {
  		error ("`%s' declared as function returning an array", name);
  		type = integer_type_node;
  	      }
  
  	    /* Pick up type qualifiers which should be applied to `this'.  */
! 	    quals = declarator->u.function.qualifiers;
  
  	    /* Pick up the exception specifications.  */
! 	    raises = declarator->u.function.exception_specification;
  
  	    /* Say it's a definition only for the CALL_EXPR
  	       closest to the identifier.  */
! 	    funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
  
  	    if (ctype == NULL_TREE
  		&& decl_context == FIELD
  		&& funcdecl_p
  		&& (friendp == 0 || dname == current_class_name))
  	      ctype = current_class_type;
  
  	    if (ctype && sfk == sfk_conversion)
  	      TYPE_HAS_CONVERSION (ctype) = 1;
! 	    if (ctype && (sfk == sfk_constructor
! 			  || sfk == sfk_destructor))
  	      {
  		/* We are within a class's scope. If our declarator name
  		   is the same as the class name, and we are defining
  		   a function, then it is a constructor/destructor, and
  		   therefore returns a void type.  */
*************** grokdeclarator (tree declarator,
*** 7457,7543 ****
  		if (current_function_decl && funcdef_flag)
  		  error ("can't define friend function `%s' in a local class definition",
  			    name);
  	      }
  
! 	    /* Construct the function type and go to the next
! 	       inner layer of declarator.  */
! 
! 	    declarator = TREE_OPERAND (declarator, 0);
  
! 	    arg_types = grokparms (inner_parms, &parms);
! 
! 	    if (declarator && flags == DTOR_FLAG)
  	      {
! 		/* A destructor declared in the body of a class will
! 		   be represented as a BIT_NOT_EXPR.  But, we just
! 		   want the underlying IDENTIFIER.  */
! 		if (TREE_CODE (declarator) == BIT_NOT_EXPR)
! 		  declarator = TREE_OPERAND (declarator, 0);
! 
!                 if (arg_types != void_list_node)
! 		  {
! 		    error ("destructors may not have parameters");
! 		    arg_types = void_list_node;
! 		    parms = NULL_TREE;
! 		  }
  	      }
! 
! 	    /* ANSI says that `const int foo ();'
! 	       does not make the function foo const.  */
  	    type = build_function_type (type, arg_types);
  	  }
  	  break;
  
! 	case ADDR_EXPR:
! 	case INDIRECT_REF:
  	  /* Filter out pointers-to-references and references-to-references.
  	     We can get these if a TYPE_DECL is used.  */
  
  	  if (TREE_CODE (type) == REFERENCE_TYPE)
  	    {
! 	      error (TREE_CODE (declarator) == ADDR_EXPR
  		     ? "cannot declare reference to `%#T'"
  		     : "cannot declare pointer to `%#T'", type);
  	      type = TREE_TYPE (type);
  	    }
! 	  else if (VOID_TYPE_P (type)
! 		   && (ctype || TREE_CODE (declarator) == ADDR_EXPR))
! 	    error (ctype ? "cannot declare pointer to `%#T' member"
! 		     : "cannot declare reference to `%#T'", type);
! 
! 	  /* Merge any constancy or volatility into the target type
! 	     for the pointer.  */
  
  	  /* We now know that the TYPE_QUALS don't apply to the decl,
  	     but to the target of the pointer.  */
  	  type_quals = TYPE_UNQUALIFIED;
  
! 	  if (TREE_CODE (declarator) == ADDR_EXPR)
  	    {
  	      if (!VOID_TYPE_P (type))
  		type = build_reference_type (type);
  	    }
  	  else if (TREE_CODE (type) == METHOD_TYPE)
  	    type = build_ptrmemfunc_type (build_pointer_type (type));
! 	  else if (ctype)
! 	    type = build_ptrmem_type (ctype, type);
  	  else
  	    type = build_pointer_type (type);
  
  	  /* Process a list of type modifier keywords (such as
  	     const or volatile) that were given inside the `*' or `&'.  */
  
! 	  if (TREE_TYPE (declarator))
  	    {
  	      tree typemodlist;
  	      int erred = 0;
  	      int constp = 0;
  	      int volatilep = 0;
  	      int restrictp = 0;
  	      
! 	      for (typemodlist = TREE_TYPE (declarator); typemodlist;
  		   typemodlist = TREE_CHAIN (typemodlist))
  		{
  		  tree qualifier = TREE_VALUE (typemodlist);
  
  		  if (qualifier == ridpointers[(int) RID_CONST])
--- 7257,7344 ----
  		if (current_function_decl && funcdef_flag)
  		  error ("can't define friend function `%s' in a local class definition",
  			    name);
  	      }
  
! 	    arg_types = grokparms (declarator->u.function.parameters, 
! 				   &parms);
  
! 	    if (inner_declarator
! 		&& inner_declarator->kind == cdk_id
! 		&& inner_declarator->u.id.sfk == sfk_destructor
! 		&& arg_types != void_list_node)
  	      {
! 		error ("destructors may not have parameters");
! 		arg_types = void_list_node;
! 		parms = NULL_TREE;
  	      }
! 	    
  	    type = build_function_type (type, arg_types);
  	  }
  	  break;
  
! 	case cdk_pointer:
! 	case cdk_reference:
! 	case cdk_ptrmem:
  	  /* Filter out pointers-to-references and references-to-references.
  	     We can get these if a TYPE_DECL is used.  */
  
  	  if (TREE_CODE (type) == REFERENCE_TYPE)
  	    {
! 	      error (declarator->kind == cdk_reference
  		     ? "cannot declare reference to `%#T'"
  		     : "cannot declare pointer to `%#T'", type);
  	      type = TREE_TYPE (type);
  	    }
! 	  else if (VOID_TYPE_P (type))
! 	    {
! 	      if (declarator->kind == cdk_reference)
! 		error ("cannot declare reference to `%#T'", type);
! 	      else if (declarator->kind == cdk_ptrmem)
! 		error ("cannot declare pointer to `%#T' member", type);
! 	    }
  
  	  /* We now know that the TYPE_QUALS don't apply to the decl,
  	     but to the target of the pointer.  */
  	  type_quals = TYPE_UNQUALIFIED;
  
! 	  if (declarator->kind == cdk_ptrmem
! 	      && (TREE_CODE (type) == FUNCTION_TYPE
! 		  || (quals && TREE_CODE (type) == METHOD_TYPE)))
! 	    {
! 	      tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
! 	      grok_method_quals (declarator->u.pointer.class_type, 
! 				 dummy, quals);
! 	      type = TREE_TYPE (dummy);
! 	      quals = NULL_TREE;
! 	    }
! 
! 	  if (declarator->kind == cdk_reference)
  	    {
  	      if (!VOID_TYPE_P (type))
  		type = build_reference_type (type);
  	    }
  	  else if (TREE_CODE (type) == METHOD_TYPE)
  	    type = build_ptrmemfunc_type (build_pointer_type (type));
! 	  else if (declarator->kind == cdk_ptrmem)
! 	    type = build_ptrmem_type (declarator->u.pointer.class_type, 
! 				      type);
  	  else
  	    type = build_pointer_type (type);
  
  	  /* Process a list of type modifier keywords (such as
  	     const or volatile) that were given inside the `*' or `&'.  */
  
! 	  if (declarator->u.pointer.qualifiers)
  	    {
  	      tree typemodlist;
  	      int erred = 0;
  	      int constp = 0;
  	      int volatilep = 0;
  	      int restrictp = 0;
  	      
! 	      for (typemodlist = declarator->u.pointer.qualifiers; typemodlist;
  		   typemodlist = TREE_CHAIN (typemodlist))
  		{
  		  tree qualifier = TREE_VALUE (typemodlist);
  
  		  if (qualifier == ridpointers[(int) RID_CONST])
*************** grokdeclarator (tree declarator,
*** 7568,7729 ****
  	      if (restrictp > 1)
  		pedwarn ("duplicate `restrict'");
  	      type = cp_build_qualified_type (type, type_quals);
  	      type_quals = cp_type_quals (type);
  	    }
- 	  declarator = TREE_OPERAND (declarator, 0);
  	  ctype = NULL_TREE;
  	  break;
  
! 	case SCOPE_REF:
! 	  {
! 	    /* We have converted type names to NULL_TREE if the
! 	       name was bogus, or to a _TYPE node, if not.
! 
! 	       The variable CTYPE holds the type we will ultimately
! 	       resolve to.  The code here just needs to build
! 	       up appropriate member types.  */
! 	    tree sname = TREE_OPERAND (declarator, 1);
! 	    tree t;
! 
! 	    /* Destructors can have their visibilities changed as well.  */
! 	    if (TREE_CODE (sname) == BIT_NOT_EXPR)
! 	      sname = TREE_OPERAND (sname, 0);
! 
! 	    if (TREE_OPERAND (declarator, 0) == NULL_TREE)
! 	      {
! 		/* We had a reference to a global decl, or
! 		   perhaps we were given a non-aggregate typedef,
! 		   in which case we cleared this out, and should just
! 		   keep going as though it wasn't there.  */
! 		declarator = sname;
! 		continue;
! 	      }
! 	    ctype = TREE_OPERAND (declarator, 0);
! 
! 	    t = ctype;
! 	    if (TREE_CODE (TREE_OPERAND (declarator, 1)) != INDIRECT_REF)
! 	      while (t != NULL_TREE && CLASS_TYPE_P (t))
! 		{
! 		  /* You're supposed to have one `template <...>'
! 		     for every template class, but you don't need one
! 		     for a full specialization.  For example:
! 		     
! 		     template <class T> struct S{};
! 		     template <> struct S<int> { void f(); };
! 		     void S<int>::f () {}
! 		     
! 		     is correct; there shouldn't be a `template <>' for
! 		     the definition of `S<int>::f'.  */
! 		  if (CLASSTYPE_TEMPLATE_INFO (t)
! 		      && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
! 			  || uses_template_parms (CLASSTYPE_TI_ARGS (t)))
! 		      && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
! 		    template_count += 1;
! 		  
! 		  t = TYPE_MAIN_DECL (t);
! 		  t = DECL_CONTEXT (t);
! 		}
! 
! 	    if (sname == NULL_TREE)
! 	      goto done_scoping;
! 
! 	    if (TREE_CODE (sname) == IDENTIFIER_NODE)
! 	      {
! 		/* This is the `standard' use of the scoping operator:
! 		   basetype :: member .  */
! 
! 		if (ctype == current_class_type)
! 		  {
! 		    /* class A {
! 		         void A::f ();
! 		       };
! 
! 		       Is this ill-formed?  */
! 
! 		    if (pedantic)
! 		      pedwarn ("extra qualification `%T::' on member `%s' ignored",
! 				  ctype, name);
! 		  }
! 		else if (TREE_CODE (type) == FUNCTION_TYPE)
! 		  {
! 		    if (NEW_DELETE_OPNAME_P (sname))
! 		      /* Overloaded operator new and operator delete
! 			 are always static functions.  */
! 		      ;
! 		    else if (current_class_type == NULL_TREE || friendp)
! 		      type 
! 			= build_method_type_directly (ctype, 
! 						      TREE_TYPE (type),
! 						      TYPE_ARG_TYPES (type));
! 		    else
! 		      {
! 			error ("cannot declare member function `%T::%s' within `%T'",
! 				  ctype, name, current_class_type);
! 			return error_mark_node;
! 		      }
! 		  }
! 		else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
! 			 || COMPLETE_TYPE_P (complete_type (ctype)))
! 		  {
! 		    /* Have to move this code elsewhere in this function.
! 		       this code is used for i.e., typedef int A::M; M *pm;
! 
! 		       It is?  How? jason 10/2/94 */
! 
! 		    if (current_class_type)
! 		      {
! 			error ("cannot declare member `%T::%s' within `%T'",
! 				  ctype, name, current_class_type);
! 			return void_type_node;
! 		      }
! 		  }
! 		else
! 	          {
! 	            cxx_incomplete_type_error (NULL_TREE, ctype);
! 	            return error_mark_node;
! 		  }
! 
! 		declarator = sname;
! 	      }
! 	    else if (TREE_CODE (sname) == SCOPE_REF)
! 	      abort ();
! 	    else
! 	      {
! 	      done_scoping:
! 		declarator = TREE_OPERAND (declarator, 1);
! 		if (declarator && TREE_CODE (declarator) == CALL_EXPR)
! 		  /* In this case, we will deal with it later.  */
! 		  ;
! 		else if (TREE_CODE (type) == FUNCTION_TYPE)
! 		  type = build_method_type_directly (ctype, 
! 						     TREE_TYPE (type),
! 						     TYPE_ARG_TYPES (type));
! 	      }
! 	  }
  	  break;
  
! 	case BIT_NOT_EXPR:
! 	  declarator = TREE_OPERAND (declarator, 0);
! 	  break;
! 
! 	case BASELINK:
! 	  declarator = BASELINK_FUNCTIONS (declarator);
! 	  break;
  
! 	case RECORD_TYPE:
! 	case UNION_TYPE:
! 	case ENUMERAL_TYPE:
! 	  declarator = NULL_TREE;
! 	  break;
  
! 	case ERROR_MARK:
! 	  declarator = NULL_TREE;
! 	  break;
  
! 	default:
! 	  abort ();
  	}
      }
  
    if (returned_attrs)
      {
--- 7369,7487 ----
  	      if (restrictp > 1)
  		pedwarn ("duplicate `restrict'");
  	      type = cp_build_qualified_type (type, type_quals);
  	      type_quals = cp_type_quals (type);
  	    }
  	  ctype = NULL_TREE;
  	  break;
  
! 	case cdk_error:
  	  break;
  
! 	default:
! 	  abort ();
! 	}
!     }
!   
!   if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
!       && TREE_CODE (type) != FUNCTION_TYPE
!       && TREE_CODE (type) != METHOD_TYPE)
!     {
!       error ("template-id `%D' used as a declarator", 
! 	     unqualified_id);
!       unqualified_id = dname;
!     }
! 
!   /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
!      otherwise, we would not have exited the loop above.  */
!   if (declarator 
!       && TREE_CODE (declarator->u.id.name) == SCOPE_REF
!       /* If the qualifying scope was invalid, it will have been set to
! 	 NULL_TREE above.  */
!       && TREE_OPERAND (declarator->u.id.name, 0)
!       && TYPE_P (TREE_OPERAND (declarator->u.id.name, 0)))
!     {
!       tree t;
! 
!       ctype = TREE_OPERAND (declarator->u.id.name, 0);
!       if (TYPE_P (ctype))
! 	ctype = TYPE_MAIN_VARIANT (ctype);
!       t = ctype;
!       while (t != NULL_TREE && CLASS_TYPE_P (t))
! 	{
! 	  /* You're supposed to have one `template <...>' for every
! 	     template class, but you don't need one for a full
! 	     specialization.  For example:
! 
! 	       template <class T> struct S{};
! 	       template <> struct S<int> { void f(); };
! 	       void S<int>::f () {}
! 
! 	     is correct; there shouldn't be a `template <>' for the
! 	     definition of `S<int>::f'.  */
! 	  if (CLASSTYPE_TEMPLATE_INFO (t)
! 	      && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
! 		  || uses_template_parms (CLASSTYPE_TI_ARGS (t)))
! 	      && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
! 	    template_count += 1;
! 
! 	  t = TYPE_MAIN_DECL (t);
! 	  t = DECL_CONTEXT (t);
! 	}
! 
!       if (ctype == current_class_type)
! 	{
! 	  /* class A {
! 	       void A::f ();
! 	     };
! 
! 	     Is this ill-formed?  */
! 
! 	  if (pedantic)
! 	    pedwarn ("extra qualification `%T::' on member `%s' ignored",
! 			ctype, name);
! 	}
!       else if (TREE_CODE (type) == FUNCTION_TYPE)
! 	{
! 	  tree sname = TREE_OPERAND (declarator->u.id.name, 1);
  
! 	  if (TREE_CODE (sname) == IDENTIFIER_NODE
! 	      && NEW_DELETE_OPNAME_P (sname))
! 	    /* Overloaded operator new and operator delete
! 	       are always static functions.  */
! 	    ;
! 	  else if (current_class_type == NULL_TREE || friendp)
! 	    type 
! 	      = build_method_type_directly (ctype, 
! 					    TREE_TYPE (type),
! 					    TYPE_ARG_TYPES (type));
! 	  else
! 	    {
! 	      error ("cannot declare member function `%T::%s' within `%T'",
!  		     ctype, name, current_class_type);
! 	      return error_mark_node;
! 	    }
! 	}
!       else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
! 	       || COMPLETE_TYPE_P (complete_type (ctype)))
! 	{
! 	  /* Have to move this code elsewhere in this function.
! 	     this code is used for i.e., typedef int A::M; M *pm;
  
! 	     It is?  How? jason 10/2/94 */
  
! 	  if (current_class_type)
! 	    {
! 	      error ("cannot declare member `%T::%s' within `%T'",
! 		     ctype, name, current_class_type);
! 	      return void_type_node;
! 	    }
! 	}
!       else
! 	{
! 	  cxx_incomplete_type_error (NULL_TREE, ctype);
! 	  return error_mark_node;
  	}
      }
  
    if (returned_attrs)
      {
*************** grokdeclarator (tree declarator,
*** 7794,7821 ****
  	  error ("const `%s' cannot be declared `mutable'", name);
   	  RIDBIT_RESET (RID_MUTABLE, specbits);
  	}
      }
  
-   if (declarator == NULL_TREE
-       || TREE_CODE (declarator) == ERROR_MARK
-       || TREE_CODE (declarator) == IDENTIFIER_NODE
-       || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
- 	  && (TREE_CODE (type) == FUNCTION_TYPE
- 	      || TREE_CODE (type) == METHOD_TYPE)))
-     /* OK */;
-   else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
-     {
-       error ("template-id `%D' used as a declarator", declarator);
-       declarator = dname;
-     }
-   else
-     /* Unexpected declarator format.  */
-     abort ();
- 
    /* If this is declaring a typedef name, return a TYPE_DECL.  */
- 
    if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
      {
        tree decl;
  
        /* Note that the grammar rejects storage classes
--- 7552,7562 ----
*************** grokdeclarator (tree declarator,
*** 7823,7840 ****
        if (current_lang_name == lang_name_java)
  	TYPE_FOR_JAVA (type) = 1;
  
        if (decl_context == FIELD)
  	{
! 	  if (constructor_name_p (declarator, current_class_type))
  	    pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
! 			declarator);
! 	  decl = build_lang_decl (TYPE_DECL, declarator, type);
  	}
        else
  	{
! 	  decl = build_decl (TYPE_DECL, declarator, type);
  	  if (in_namespace || ctype)
  	    error ("%Jtypedef name may not be a nested-name-specifier", decl);
  	  if (!current_function_decl)
  	    DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
  	}
--- 7564,7581 ----
        if (current_lang_name == lang_name_java)
  	TYPE_FOR_JAVA (type) = 1;
  
        if (decl_context == FIELD)
  	{
! 	  if (constructor_name_p (unqualified_id, current_class_type))
  	    pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
! 		     unqualified_id);
! 	  decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
  	}
        else
  	{
! 	  decl = build_decl (TYPE_DECL, unqualified_id, type);
  	  if (in_namespace || ctype)
  	    error ("%Jtypedef name may not be a nested-name-specifier", decl);
  	  if (!current_function_decl)
  	    DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
  	}
*************** grokdeclarator (tree declarator,
*** 7842,7852 ****
        /* If the user declares "typedef struct {...} foo" then the
  	 struct will have an anonymous name.  Fill that name in now.
  	 Nothing can refer to it, so nothing needs know about the name
  	 change.  */
        if (type != error_mark_node
! 	  && declarator
  	  && TYPE_NAME (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
  	  && TYPE_ANONYMOUS_P (type)
  	  /* Don't do this if there are attributes.  */
  	  && (!attrlist || !*attrlist)
--- 7583,7593 ----
        /* If the user declares "typedef struct {...} foo" then the
  	 struct will have an anonymous name.  Fill that name in now.
  	 Nothing can refer to it, so nothing needs know about the name
  	 change.  */
        if (type != error_mark_node
! 	  && unqualified_id
  	  && TYPE_NAME (type)
  	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
  	  && TYPE_ANONYMOUS_P (type)
  	  /* Don't do this if there are attributes.  */
  	  && (!attrlist || !*attrlist)
*************** grokdeclarator (tree declarator,
*** 7854,7864 ****
  	{
  	  tree oldname = TYPE_NAME (type);
  	  tree t;
  
  	  /* Replace the anonymous name with the real name everywhere.  */
! 	  lookup_tag_reverse (type, declarator);
  	  for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
  	    if (TYPE_NAME (t) == oldname)
  	      TYPE_NAME (t) = decl;
  
  	  if (TYPE_LANG_SPECIFIC (type))
--- 7595,7605 ----
  	{
  	  tree oldname = TYPE_NAME (type);
  	  tree t;
  
  	  /* Replace the anonymous name with the real name everywhere.  */
! 	  lookup_tag_reverse (type, unqualified_id);
  	  for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
  	    if (TYPE_NAME (t) == oldname)
  	      TYPE_NAME (t) = decl;
  
  	  if (TYPE_LANG_SPECIFIC (type))
*************** grokdeclarator (tree declarator,
*** 7990,8028 ****
  	      else
  	        ctype = TYPE_METHOD_BASETYPE (type);
  	    }
  	  if (ctype)
  	    {
! 	      tree dummy = build_decl (TYPE_DECL, declarator, type);
  	      grok_method_quals (ctype, dummy, quals);
  	      type = TREE_TYPE (dummy);
  	    }
  	}
  
        return type;
      }
!   else if (declarator == NULL_TREE && decl_context != PARM
  	   && decl_context != CATCHPARM
  	   && TREE_CODE (type) != UNION_TYPE
  	   && ! bitfield)
      {
        error ("abstract declarator `%T' used as declaration", type);
!       declarator = make_anon_name ();
      }
  
    /* `void' at top level (not within pointer)
       is allowed only in typedefs or type names.
       We don't complain about parms either, but that is because
       a better error message can be made later.  */
  
    if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
      {
!       if (! declarator)
  	error ("unnamed variable or field declared void");
!       else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
  	{
! 	  if (IDENTIFIER_OPNAME_P (declarator))
  	    abort ();
  	  else
  	    error ("variable or field `%s' declared void", name);
  	}
        else
--- 7731,7769 ----
  	      else
  	        ctype = TYPE_METHOD_BASETYPE (type);
  	    }
  	  if (ctype)
  	    {
! 	      tree dummy = build_decl (TYPE_DECL, unqualified_id, type);
  	      grok_method_quals (ctype, dummy, quals);
  	      type = TREE_TYPE (dummy);
  	    }
  	}
  
        return type;
      }
!   else if (unqualified_id == NULL_TREE && decl_context != PARM
  	   && decl_context != CATCHPARM
  	   && TREE_CODE (type) != UNION_TYPE
  	   && ! bitfield)
      {
        error ("abstract declarator `%T' used as declaration", type);
!       unqualified_id = make_anon_name ();
      }
  
    /* `void' at top level (not within pointer)
       is allowed only in typedefs or type names.
       We don't complain about parms either, but that is because
       a better error message can be made later.  */
  
    if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
      {
!       if (! unqualified_id)
  	error ("unnamed variable or field declared void");
!       else if (TREE_CODE (unqualified_id) == IDENTIFIER_NODE)
  	{
! 	  if (IDENTIFIER_OPNAME_P (unqualified_id))
  	    abort ();
  	  else
  	    error ("variable or field `%s' declared void", name);
  	}
        else
*************** grokdeclarator (tree declarator,
*** 8055,8065 ****
    {
      tree decl;
  
      if (decl_context == PARM)
        {
! 	decl = cp_build_parm_decl (declarator, type);
  
  	bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
  			inlinep, friendp, raises != NULL_TREE);
        }
      else if (decl_context == FIELD)
--- 7796,7806 ----
    {
      tree decl;
  
      if (decl_context == PARM)
        {
! 	decl = cp_build_parm_decl (unqualified_id, type);
  
  	bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
  			inlinep, friendp, raises != NULL_TREE);
        }
      else if (decl_context == FIELD)
*************** grokdeclarator (tree declarator,
*** 8089,8102 ****
  	    int publicp = 0;
  	    tree function_context;
  
  	    /* We catch the others as conflicts with the builtin
  	       typedefs.  */
! 	    if (friendp && declarator == ridpointers[(int) RID_SIGNED])
  	      {
  		error ("function `%D' cannot be declared friend",
! 			  declarator);
  		friendp = 0;
  	      }
  
  	    if (friendp == 0)
  	      {
--- 7830,7843 ----
  	    int publicp = 0;
  	    tree function_context;
  
  	    /* We catch the others as conflicts with the builtin
  	       typedefs.  */
! 	    if (friendp && unqualified_id == ridpointers[(int) RID_SIGNED])
  	      {
  		error ("function `%D' cannot be declared friend",
! 		       unqualified_id);
  		friendp = 0;
  	      }
  
  	    if (friendp == 0)
  	      {
*************** grokdeclarator (tree declarator,
*** 8104,8132 ****
  		  ctype = current_class_type;
  
  		if (ctype == NULL_TREE)
  		  {
  		    error ("can't make `%D' into a method -- not in a class",
! 			      declarator);
  		    return void_type_node;
  		  }
  
  		/* ``A union may [ ... ] not [ have ] virtual functions.''
  		   ARM 9.5 */
  		if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
  		  {
  		    error ("function `%D' declared virtual inside a union",
! 			      declarator);
  		    return void_type_node;
  		  }
  
! 		if (NEW_DELETE_OPNAME_P (declarator))
  		  {
  		    if (virtualp)
  		      {
  			error ("`%D' cannot be declared virtual, since it is always static",
! 				  declarator);
  			virtualp = 0;
  		      }
  		  }
  		else if (staticp < 2)
  		  type = build_method_type_directly (ctype, 
--- 7845,7873 ----
  		  ctype = current_class_type;
  
  		if (ctype == NULL_TREE)
  		  {
  		    error ("can't make `%D' into a method -- not in a class",
! 			   unqualified_id);
  		    return void_type_node;
  		  }
  
  		/* ``A union may [ ... ] not [ have ] virtual functions.''
  		   ARM 9.5 */
  		if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
  		  {
  		    error ("function `%D' declared virtual inside a union",
! 			   unqualified_id);
  		    return void_type_node;
  		  }
  
! 		if (NEW_DELETE_OPNAME_P (unqualified_id))
  		  {
  		    if (virtualp)
  		      {
  			error ("`%D' cannot be declared virtual, since it is always static",
! 			       unqualified_id);
  			virtualp = 0;
  		      }
  		  }
  		else if (staticp < 2)
  		  type = build_method_type_directly (ctype, 
*************** grokdeclarator (tree declarator,
*** 8138,8151 ****
  	    function_context = (ctype != NULL_TREE) ?
  	      decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
  	    publicp = (! friendp || ! staticp)
  	      && function_context == NULL_TREE;
  	    decl = grokfndecl (ctype, type,
! 			       TREE_CODE (declarator) != TEMPLATE_ID_EXPR
! 			       ? declarator : dname,
  			       parms,
! 			       declarator,
  			       virtualp, flags, quals, raises,
  			       friendp ? -1 : 0, friendp, publicp, inlinep,
  			       funcdef_flag, template_count, in_namespace);
  	    if (decl == NULL_TREE)
  	      return decl;
--- 7879,7892 ----
  	    function_context = (ctype != NULL_TREE) ?
  	      decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
  	    publicp = (! friendp || ! staticp)
  	      && function_context == NULL_TREE;
  	    decl = grokfndecl (ctype, type,
! 			       TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
! 			       ? unqualified_id : dname,
  			       parms,
! 			       unqualified_id,
  			       virtualp, flags, quals, raises,
  			       friendp ? -1 : 0, friendp, publicp, inlinep,
  			       funcdef_flag, template_count, in_namespace);
  	    if (decl == NULL_TREE)
  	      return decl;
*************** grokdeclarator (tree declarator,
*** 8185,8210 ****
  	    /* We only get here for friend declarations of
  	       members of other classes.  */
  	    /* All method decls are public, so tell grokfndecl to set
  	       TREE_PUBLIC, also.  */
  	    decl = grokfndecl (ctype, type,
! 			       TREE_CODE (declarator) != TEMPLATE_ID_EXPR
! 			       ? declarator : dname,
  			       parms,
! 			       declarator,
  			       virtualp, flags, quals, raises,
  			       friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
  			       template_count, in_namespace);
  	    if (decl == NULL_TREE)
  	      return NULL_TREE;
  	  }
  	else if (!staticp && !dependent_type_p (type)
  		 && !COMPLETE_TYPE_P (complete_type (type))
  		 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
  	  {
! 	    if (declarator)
! 	      error ("field `%D' has incomplete type", declarator);
  	    else
  	      error ("name `%T' has incomplete type", type);
  
  	    /* If we're instantiating a template, tell them which
  	       instantiation made the field's type be incomplete.  */
--- 7926,7951 ----
  	    /* We only get here for friend declarations of
  	       members of other classes.  */
  	    /* All method decls are public, so tell grokfndecl to set
  	       TREE_PUBLIC, also.  */
  	    decl = grokfndecl (ctype, type,
! 			       TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
! 			       ? unqualified_id : dname,
  			       parms,
! 			       unqualified_id,
  			       virtualp, flags, quals, raises,
  			       friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
  			       template_count, in_namespace);
  	    if (decl == NULL_TREE)
  	      return NULL_TREE;
  	  }
  	else if (!staticp && !dependent_type_p (type)
  		 && !COMPLETE_TYPE_P (complete_type (type))
  		 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
  	  {
! 	    if (unqualified_id)
! 	      error ("field `%D' has incomplete type", unqualified_id);
  	    else
  	      error ("name `%T' has incomplete type", type);
  
  	    /* If we're instantiating a template, tell them which
  	       instantiation made the field's type be incomplete.  */
*************** grokdeclarator (tree declarator,
*** 8222,8232 ****
  	else
  	  {
  	    if (friendp)
  	      {
  		error ("`%E' is neither function nor member function; "
!                        "cannot be declared friend", declarator);
  		friendp = 0;
  	      }
  	    decl = NULL_TREE;
  	  }
  
--- 7963,7973 ----
  	else
  	  {
  	    if (friendp)
  	      {
  		error ("`%E' is neither function nor member function; "
!                        "cannot be declared friend", unqualified_id);
  		friendp = 0;
  	      }
  	    decl = NULL_TREE;
  	  }
  
*************** grokdeclarator (tree declarator,
*** 8238,8254 ****
   	    else if (decl && DECL_NAME (decl))
  	      {
  		if (template_class_depth (current_class_type) == 0)
  		  {
  		    decl = check_explicit_specialization
! 		      (declarator, decl, template_count,
  		       2 * (funcdef_flag != 0) + 4);
  		    if (decl == error_mark_node)
  		      return error_mark_node;
  		  }
  		
! 		decl = do_friend (ctype, declarator, decl,
  				  *attrlist, flags, quals, funcdef_flag);
  		return decl;
  	      }
  	    else
  	      return void_type_node;
--- 7979,7995 ----
   	    else if (decl && DECL_NAME (decl))
  	      {
  		if (template_class_depth (current_class_type) == 0)
  		  {
  		    decl = check_explicit_specialization
! 		      (unqualified_id, decl, template_count,
  		       2 * (funcdef_flag != 0) + 4);
  		    if (decl == error_mark_node)
  		      return error_mark_node;
  		  }
  		
! 		decl = do_friend (ctype, unqualified_id, decl,
  				  *attrlist, flags, quals, funcdef_flag);
  		return decl;
  	      }
  	    else
  	      return void_type_node;
*************** grokdeclarator (tree declarator,
*** 8273,8291 ****
  		       This used to be relatively common practice, but
  		       the rest of the compiler does not correctly
  		       handle the initialization unless the member is
  		       static so we make it static below.  */
  		    pedwarn ("ISO C++ forbids initialization of member `%D'",
! 				declarator);
! 		    pedwarn ("making `%D' static", declarator);
  		    staticp = 1;
  		  }
  
  		if (uses_template_parms (type))
  		  /* We'll check at instantiation time.  */
  		  ;
! 		else if (check_static_variable_definition (declarator,
  							   type))
  		  /* If we just return the declaration, crashes
  		     will sometimes occur.  We therefore return
  		     void_type_node, as if this was a friend
  		     declaration, to cause callers to completely
--- 8014,8032 ----
  		       This used to be relatively common practice, but
  		       the rest of the compiler does not correctly
  		       handle the initialization unless the member is
  		       static so we make it static below.  */
  		    pedwarn ("ISO C++ forbids initialization of member `%D'",
! 			     unqualified_id);
! 		    pedwarn ("making `%D' static", unqualified_id);
  		    staticp = 1;
  		  }
  
  		if (uses_template_parms (type))
  		  /* We'll check at instantiation time.  */
  		  ;
! 		else if (check_static_variable_definition (unqualified_id,
  							   type))
  		  /* If we just return the declaration, crashes
  		     will sometimes occur.  We therefore return
  		     void_type_node, as if this was a friend
  		     declaration, to cause callers to completely
*************** grokdeclarator (tree declarator,
*** 8295,8312 ****
  
  	    if (staticp)
  	      {
  		/* C++ allows static class members.  All other work
  		   for this is done by grokfield.  */
! 		decl = build_lang_decl (VAR_DECL, declarator, type);
  		TREE_STATIC (decl) = 1;
  		/* In class context, 'static' means public access.  */
  		TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
  	      }
  	    else
  	      {
! 		decl = build_decl (FIELD_DECL, declarator, type);
  		DECL_NONADDRESSABLE_P (decl) = bitfield;
  		if (RIDBIT_SETP (RID_MUTABLE, specbits))
  		  {
  		    DECL_MUTABLE_P (decl) = 1;
  		    RIDBIT_RESET (RID_MUTABLE, specbits);
--- 8036,8053 ----
  
  	    if (staticp)
  	      {
  		/* C++ allows static class members.  All other work
  		   for this is done by grokfield.  */
! 		decl = build_lang_decl (VAR_DECL, unqualified_id, type);
  		TREE_STATIC (decl) = 1;
  		/* In class context, 'static' means public access.  */
  		TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
  	      }
  	    else
  	      {
! 		decl = build_decl (FIELD_DECL, unqualified_id, type);
  		DECL_NONADDRESSABLE_P (decl) = bitfield;
  		if (RIDBIT_SETP (RID_MUTABLE, specbits))
  		  {
  		    DECL_MUTABLE_P (decl) = 1;
  		    RIDBIT_RESET (RID_MUTABLE, specbits);
*************** grokdeclarator (tree declarator,
*** 8321,8337 ****
  	     || TREE_CODE (type) == METHOD_TYPE)
        {
  	tree original_name;
  	int publicp = 0;
  
! 	if (! declarator)
  	  return NULL_TREE;
  
! 	if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
  	  original_name = dname;
  	else
! 	  original_name = declarator;
  
  	if (RIDBIT_SETP (RID_AUTO, specbits))
  	  error ("storage class `auto' invalid for function `%s'", name);
  	else if (RIDBIT_SETP (RID_REGISTER, specbits))
  	  error ("storage class `register' invalid for function `%s'", name);
--- 8062,8078 ----
  	     || TREE_CODE (type) == METHOD_TYPE)
        {
  	tree original_name;
  	int publicp = 0;
  
! 	if (!unqualified_id)
  	  return NULL_TREE;
  
! 	if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
  	  original_name = dname;
  	else
! 	  original_name = unqualified_id;
  
  	if (RIDBIT_SETP (RID_AUTO, specbits))
  	  error ("storage class `auto' invalid for function `%s'", name);
  	else if (RIDBIT_SETP (RID_REGISTER, specbits))
  	  error ("storage class `register' invalid for function `%s'", name);
*************** grokdeclarator (tree declarator,
*** 8369,8379 ****
  	/* Record presence of `static'.  */
  	publicp = (ctype != NULL_TREE
  		   || RIDBIT_SETP (RID_EXTERN, specbits)
  		   || !RIDBIT_SETP (RID_STATIC, specbits));
  
! 	decl = grokfndecl (ctype, type, original_name, parms, declarator,
  			   virtualp, flags, quals, raises,
  			   1, friendp,
  			   publicp, inlinep, funcdef_flag,
  			   template_count, in_namespace);
  	if (decl == NULL_TREE)
--- 8110,8120 ----
  	/* Record presence of `static'.  */
  	publicp = (ctype != NULL_TREE
  		   || RIDBIT_SETP (RID_EXTERN, specbits)
  		   || !RIDBIT_SETP (RID_STATIC, specbits));
  
! 	decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
  			   virtualp, flags, quals, raises,
  			   1, friendp,
  			   publicp, inlinep, funcdef_flag,
  			   template_count, in_namespace);
  	if (decl == NULL_TREE)
*************** grokdeclarator (tree declarator,
*** 8407,8417 ****
      else
        {
  	/* It's a variable.  */
  
  	/* An uninitialized decl with `extern' is a reference.  */
! 	decl = grokvardecl (type, declarator, &specbits,
  			    initialized,
  			    (type_quals & TYPE_QUAL_CONST) != 0,
  			    ctype ? ctype : in_namespace);
  	bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
  			inlinep, friendp, raises != NULL_TREE);
--- 8148,8158 ----
      else
        {
  	/* It's a variable.  */
  
  	/* An uninitialized decl with `extern' is a reference.  */
! 	decl = grokvardecl (type, unqualified_id, &specbits,
  			    initialized,
  			    (type_quals & TYPE_QUAL_CONST) != 0,
  			    ctype ? ctype : in_namespace);
  	bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
  			inlinep, friendp, raises != NULL_TREE);
*************** check_default_argument (tree decl, tree 
*** 8603,8654 ****
  
  /* Decode the list of parameter types for a function type.
     Given the list of things declared inside the parens,
     return a list of types.
  
!    We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
!    flag. If unset, we append void_list_node. A parmlist declared
!    as `(void)' is accepted as the empty parmlist.
  
     *PARMS is set to the chain of PARM_DECLs created.  */
  
  static tree
! grokparms (tree first_parm, tree *parms)
  {
    tree result = NULL_TREE;
    tree decls = NULL_TREE;
!   int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
!   tree parm, chain;
    int any_error = 0;
  
!   my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);
! 
!   for (parm = first_parm; parm != NULL_TREE; parm = chain)
      {
        tree type = NULL_TREE;
!       tree decl = TREE_VALUE (parm);
!       tree init = TREE_PURPOSE (parm);
        tree specs, attrs;
  
!       chain = TREE_CHAIN (parm);
!       /* @@ weak defense against parse errors.  */
!       if (TREE_CODE (decl) != VOID_TYPE
! 	  && TREE_CODE (decl) != TREE_LIST)
! 	{
! 	  /* Give various messages as the need arises.  */
! 	  if (TREE_CODE (decl) == STRING_CST)
! 	    error ("invalid string constant `%E'", decl);
! 	  else if (TREE_CODE (decl) == INTEGER_CST)
! 	    error ("invalid integer constant in parameter list, did you forget to give parameter name?");
! 	  continue;
! 	}
! 
!       if (parm == void_list_node)
          break;
  
!       split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs);
!       decl = grokdeclarator (TREE_VALUE (decl), specs,
  			     PARM, init != NULL_TREE, &attrs);
        if (! decl || TREE_TYPE (decl) == error_mark_node)
          continue;
  
        if (attrs)
--- 8344,8380 ----
  
  /* Decode the list of parameter types for a function type.
     Given the list of things declared inside the parens,
     return a list of types.
  
!    If this parameter does not end with an ellipsis, we append
!    void_list_node.
  
     *PARMS is set to the chain of PARM_DECLs created.  */
  
  static tree
! grokparms (const cp_parameter_declarator *first_parm, tree *parms)
  {
    tree result = NULL_TREE;
    tree decls = NULL_TREE;
!   int ellipsis = !first_parm || first_parm->ellipsis_p;
!   const cp_parameter_declarator *parm;
    int any_error = 0;
  
!   for (parm = first_parm; parm != NULL; parm = parm->next)
      {
        tree type = NULL_TREE;
!       tree decl_specifiers = parm->decl_specifiers;
!       tree init = parm->default_argument;
        tree specs, attrs;
+       tree decl;
  
!       if (parm == no_parameters)
          break;
  
!       split_specs_attrs (decl_specifiers, &specs, &attrs);
!       decl = grokdeclarator (parm->declarator, specs,
  			     PARM, init != NULL_TREE, &attrs);
        if (! decl || TREE_TYPE (decl) == error_mark_node)
          continue;
  
        if (attrs)
*************** grokparms (tree first_parm, tree *parms)
*** 8656,8666 ****
  
        type = TREE_TYPE (decl);
        if (VOID_TYPE_P (type))
          {
            if (same_type_p (type, void_type_node)
!               && !DECL_NAME (decl) && !result && !chain && !ellipsis)
              /* this is a parmlist of `(void)', which is ok.  */
              break;
            cxx_incomplete_type_error (decl, type);
  	  /* It's not a good idea to actually create parameters of
  	     type `void'; other parts of the compiler assume that a
--- 8382,8392 ----
  
        type = TREE_TYPE (decl);
        if (VOID_TYPE_P (type))
          {
            if (same_type_p (type, void_type_node)
!               && !DECL_NAME (decl) && !result && !parm->next && !ellipsis)
              /* this is a parmlist of `(void)', which is ok.  */
              break;
            cxx_incomplete_type_error (decl, type);
  	  /* It's not a good idea to actually create parameters of
  	     type `void'; other parts of the compiler assume that a
*************** check_function_type (tree decl, tree cur
*** 10038,10060 ****
     indicating that the function is an inline defined in-class.
  
     This function creates a binding context for the function body
     as well as setting up the FUNCTION_DECL in current_function_decl.
  
-    Returns 1 on success.  If the DECLARATOR is not suitable for a function
-    (it defines a datum instead), we return 0, which tells
-    yyparse to report a parse error.
- 
     For C++, we must first check whether that datum makes any sense.
     For example, "class A local_a(1,2);" means that variable local_a
     is an aggregate of type A, which should have a constructor
     applied to it with the argument list [1, 2].  */
  
! int
! start_function (tree declspecs, tree declarator, tree attrs, int flags)
  {
-   tree decl1;
    tree ctype = NULL_TREE;
    tree fntype;
    tree restype;
    int doing_friend = 0;
    struct cp_binding_level *bl;
--- 9764,9781 ----
     indicating that the function is an inline defined in-class.
  
     This function creates a binding context for the function body
     as well as setting up the FUNCTION_DECL in current_function_decl.
  
     For C++, we must first check whether that datum makes any sense.
     For example, "class A local_a(1,2);" means that variable local_a
     is an aggregate of type A, which should have a constructor
     applied to it with the argument list [1, 2].  */
  
! void
! start_preparsed_function (tree decl1, tree attrs, int flags)
  {
    tree ctype = NULL_TREE;
    tree fntype;
    tree restype;
    int doing_friend = 0;
    struct cp_binding_level *bl;
*************** start_function (tree declspecs, tree dec
*** 10062,10132 ****
  
    /* Sanity check.  */
    my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
    my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
  
!   /* This should only be done once on the top most decl.  */
!   if (have_extern_spec)
!     {
!       declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
!       have_extern_spec = false;
!     }
! 
!   if (flags & SF_PRE_PARSED)
!     {
!       decl1 = declarator;
! 
!       fntype = TREE_TYPE (decl1);
!       if (TREE_CODE (fntype) == METHOD_TYPE)
! 	ctype = TYPE_METHOD_BASETYPE (fntype);
! 
!       /* ISO C++ 11.4/5.  A friend function defined in a class is in
! 	 the (lexical) scope of the class in which it is defined.  */
!       if (!ctype && DECL_FRIEND_P (decl1))
! 	{
! 	  ctype = DECL_FRIEND_CONTEXT (decl1);
! 
! 	  /* CTYPE could be null here if we're dealing with a template;
! 	     for example, `inline friend float foo()' inside a template
! 	     will have no CTYPE set.  */
! 	  if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
! 	    ctype = NULL_TREE;
! 	  else
! 	    doing_friend = 1;
! 	}
!     }
!   else
      {
!       decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
!       /* If the declarator is not suitable for a function definition,
! 	 cause a syntax error.  */
!       if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
! 	return 0;
! 
!       cplus_decl_attributes (&decl1, attrs, 0);
! 
!       /* If #pragma weak was used, mark the decl weak now.  */
!       if (global_scope_p (current_binding_level))
! 	maybe_apply_pragma_weak (decl1);
! 
!       fntype = TREE_TYPE (decl1);
! 
!       restype = TREE_TYPE (fntype);
! 
!       if (TREE_CODE (fntype) == METHOD_TYPE)
! 	ctype = TYPE_METHOD_BASETYPE (fntype);
!       else if (DECL_MAIN_P (decl1))
! 	{
! 	  /* If this doesn't return integer_type, or a typedef to
! 	     integer_type, complain.  */
! 	  if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
! 	    {
! 	      if (pedantic || warn_return_type)
! 		pedwarn ("return type for `main' changed to `int'");
! 	      TREE_TYPE (decl1) = fntype = default_function_type;
! 	    }
! 	}
      }
  
    if (DECL_DECLARED_INLINE_P (decl1)
        && lookup_attribute ("noinline", attrs))
      warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
--- 9783,9809 ----
  
    /* Sanity check.  */
    my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
    my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
  
!   fntype = TREE_TYPE (decl1);
!   if (TREE_CODE (fntype) == METHOD_TYPE)
!     ctype = TYPE_METHOD_BASETYPE (fntype);
!   
!   /* ISO C++ 11.4/5.  A friend function defined in a class is in
!      the (lexical) scope of the class in which it is defined.  */
!   if (!ctype && DECL_FRIEND_P (decl1))
      {
!       ctype = DECL_FRIEND_CONTEXT (decl1);
!       
!       /* CTYPE could be null here if we're dealing with a template;
! 	 for example, `inline friend float foo()' inside a template
! 	 will have no CTYPE set.  */
!       if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
! 	ctype = NULL_TREE;
!       else
! 	doing_friend = 1;
      }
  
    if (DECL_DECLARED_INLINE_P (decl1)
        && lookup_attribute ("noinline", attrs))
      warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
*************** start_function (tree declspecs, tree dec
*** 10384,10393 ****
--- 10061,10119 ----
      }
  
    start_fname_decls ();
    
    store_parm_decls (current_function_parms);
+ }
+ 
+ 
+ /* Like start_preparsed_function, except that instead of a
+    FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR.
+ 
+    Returns 1 on success.  If the DECLARATOR is not suitable for a function
+    (it defines a datum instead), we return 0, which tells
+    yyparse to report a parse error.  */
+ 
+ int
+ start_function (tree declspecs, const cp_declarator *declarator,
+ 		tree attrs)
+ {
+   tree decl1;
+ 
+   if (have_extern_spec)
+     {
+       declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), 
+ 			     declspecs);
+       /* This should only be done once on the outermost decl.  */
+       have_extern_spec = false;
+     }
+   
+   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+   /* If the declarator is not suitable for a function definition,
+      cause a syntax error.  */
+   if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
+     return 0;
+   
+   cplus_decl_attributes (&decl1, attrs, 0);
+   
+   /* If #pragma weak was used, mark the decl weak now.  */
+   if (global_scope_p (current_binding_level))
+     maybe_apply_pragma_weak (decl1);
+   
+   if (DECL_MAIN_P (decl1))
+     {
+       /* If this doesn't return integer_type, or a typedef to
+ 	 integer_type, complain.  */
+       if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
+ 	{
+ 	  if (pedantic || warn_return_type)
+ 	    pedwarn ("return type for `main' changed to `int'");
+ 	  TREE_TYPE (decl1) = default_function_type;
+ 	}
+     }
+ 
+   start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
  
    return 1;
  }
  
  /* Store the parameter declarations into the current function declaration.
*************** finish_function (int flags)
*** 10874,10884 ****
  
     DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
     CHANGES TO CODE IN `grokfield'.  */
  
  tree
! start_method (tree declspecs, tree declarator, tree attrlist)
  {
    tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
  				&attrlist);
  
    if (fndecl == error_mark_node)
--- 10600,10610 ----
  
     DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
     CHANGES TO CODE IN `grokfield'.  */
  
  tree
! start_method (tree declspecs, const cp_declarator *declarator, tree attrlist)
  {
    tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
  				&attrlist);
  
    if (fndecl == error_mark_node)
*************** cp_tree_node_structure (union lang_tree_
*** 11186,11196 ****
  /* Build the void_list_node (void_type_node having been created).  */
  tree
  build_void_list_node (void)
  {
    tree t = build_tree_list (NULL_TREE, void_type_node);
-   TREE_PARMLIST (t) = 1;
    return t;
  }
  
  bool
  cp_missing_noreturn_ok_p (tree decl)
--- 10912,10921 ----
Index: cp/decl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.h,v
retrieving revision 1.13
diff -c -5 -p -r1.13 decl.h
*** cp/decl.h	24 Mar 2004 23:45:50 -0000	1.13
--- cp/decl.h	22 Jun 2004 02:13:16 -0000
*************** enum decl_context
*** 29,39 ****
    TYPENAME,			/* Typename (inside cast or sizeof)  */
    MEMFUNCDEF			/* Member function definition */
  };
  
  /* We need this in here to get the decl_context definition.  */
! extern tree grokdeclarator (tree, tree, enum decl_context, int, tree*);
  
  #ifdef DEBUG_CP_BINDING_LEVELS
  /* Purely for debugging purposes.  */
  extern int debug_bindings_indentation;
  #endif
--- 29,39 ----
    TYPENAME,			/* Typename (inside cast or sizeof)  */
    MEMFUNCDEF			/* Member function definition */
  };
  
  /* We need this in here to get the decl_context definition.  */
! extern tree grokdeclarator (const cp_declarator *, tree, enum decl_context, int, tree*);
  
  #ifdef DEBUG_CP_BINDING_LEVELS
  /* Purely for debugging purposes.  */
  extern int debug_bindings_indentation;
  #endif
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.716
diff -c -5 -p -r1.716 decl2.c
*** cp/decl2.c	17 Jun 2004 21:11:38 -0000	1.716
--- cp/decl2.c	22 Jun 2004 02:13:16 -0000
*************** grok_method_quals (tree ctype, tree func
*** 125,135 ****
    tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
    int type_quals = TYPE_UNQUALIFIED;
    int dup_quals = TYPE_UNQUALIFIED;
    int this_quals = TYPE_UNQUALIFIED;
  
!   do
      {
        int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
        
        if ((type_quals | this_quals) & tq)
  	dup_quals |= tq;
--- 125,135 ----
    tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
    int type_quals = TYPE_UNQUALIFIED;
    int dup_quals = TYPE_UNQUALIFIED;
    int this_quals = TYPE_UNQUALIFIED;
  
!   while (quals)
      {
        int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
        
        if ((type_quals | this_quals) & tq)
  	dup_quals |= tq;
*************** grok_method_quals (tree ctype, tree func
*** 137,147 ****
          this_quals |= tq;
        else
  	type_quals |= tq;
        quals = TREE_CHAIN (quals);
      } 
-   while (quals);
  
    if (dup_quals != TYPE_UNQUALIFIED)
      error ("duplicate type qualifiers in %s declaration",
  	      TREE_CODE (function) == FUNCTION_DECL 
  	      ? "member function" : "type");
--- 137,146 ----
*************** grok_x_components (tree specs)
*** 166,176 ****
    tree t;
  
    specs = strip_attrs (specs);
  
    check_tag_decl (specs);
!   t = groktypename (build_tree_list (specs, NULL_TREE)); 
  
    /* The only case where we need to do anything additional here is an
       anonymous union field, e.g.: `struct S { union { int i; }; };'.  */
    if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t))
      return;
--- 165,175 ----
    tree t;
  
    specs = strip_attrs (specs);
  
    check_tag_decl (specs);
!   t = groktypename (specs, /*declarator=*/NULL);
  
    /* The only case where we need to do anything additional here is an
       anonymous union field, e.g.: `struct S { union { int i; }; };'.  */
    if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t))
      return;
*************** finish_static_data_member_decl (tree dec
*** 838,864 ****
  
     DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
     CHANGES TO CODE IN `start_method'.  */
  
  tree
! grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
             tree attrlist)
  {
    tree value;
    const char *asmspec = 0;
    int flags = LOOKUP_ONLYCONVERTING;
  
    if (declspecs == NULL_TREE
!       && TREE_CODE (declarator) == SCOPE_REF
!       && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE)
      {
        /* Access declaration */
!       if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
  	;
!       else if (TREE_COMPLEXITY (declarator) == current_class_depth)
  	pop_nested_class ();
!       return do_class_using_decl (declarator);
      }
  
    if (init
        && TREE_CODE (init) == TREE_LIST
        && TREE_VALUE (init) == error_mark_node
--- 837,867 ----
  
     DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
     CHANGES TO CODE IN `start_method'.  */
  
  tree
! grokfield (const cp_declarator *declarator, tree declspecs, 
! 	   tree init, tree asmspec_tree,
             tree attrlist)
  {
    tree value;
    const char *asmspec = 0;
    int flags = LOOKUP_ONLYCONVERTING;
  
    if (declspecs == NULL_TREE
!       && declarator->kind == cdk_id
!       && TREE_CODE (declarator->u.id.name) == SCOPE_REF
!       && (TREE_CODE (TREE_OPERAND (declarator->u.id.name, 1)) 
! 	  == IDENTIFIER_NODE))
      {
        /* Access declaration */
!       if (! IS_AGGR_TYPE_CODE (TREE_CODE 
! 			       (TREE_OPERAND (declarator->u.id.name, 0))))
  	;
!       else if (TREE_COMPLEXITY (declarator->u.id.name) == current_class_depth)
  	pop_nested_class ();
!       return do_class_using_decl (declarator->u.id.name);
      }
  
    if (init
        && TREE_CODE (init) == TREE_LIST
        && TREE_VALUE (init) == error_mark_node
*************** grokfield (tree declarator, tree declspe
*** 1017,1027 ****
  
  /* Like `grokfield', but for bitfields.
     WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node.  */
  
  tree
! grokbitfield (tree declarator, tree declspecs, tree width)
  {
    tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
  
    if (! value) return NULL_TREE; /* friends went bad.  */
  
--- 1020,1030 ----
  
  /* Like `grokfield', but for bitfields.
     WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node.  */
  
  tree
! grokbitfield (const cp_declarator *declarator, tree declspecs, tree width)
  {
    tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
  
    if (! value) return NULL_TREE; /* friends went bad.  */
  
*************** set_guard (tree guard)
*** 1911,1922 ****
     or destructors.  Subroutine of do_[cd]tors.  */
  
  static tree
  start_objects (int method_type, int initp)
  {
-   tree fnname;
    tree body;
    char type[10];
  
    /* Make ctor or dtor function.  METHOD_TYPE may be 'I' or 'D'.  */
  
    if (initp != DEFAULT_INIT_PRIORITY)
--- 1914,1925 ----
     or destructors.  Subroutine of do_[cd]tors.  */
  
  static tree
  start_objects (int method_type, int initp)
  {
    tree body;
+   tree fndecl;
    char type[10];
  
    /* Make ctor or dtor function.  METHOD_TYPE may be 'I' or 'D'.  */
  
    if (initp != DEFAULT_INIT_PRIORITY)
*************** start_objects (int method_type, int init
*** 1932,1947 ****
        sprintf (type, "%c%c%.5u", method_type, joiner, initp);
      }
    else
      sprintf (type, "%c", method_type);
  
!   fnname = get_file_function_name_long (type);
! 
!   start_function (void_list_node,
! 		  make_call_declarator (fnname, void_list_node, NULL_TREE,
! 					NULL_TREE),
! 		  NULL_TREE, SF_DEFAULT);
  
    /* It can be a static function as long as collect2 does not have
       to scan the object file to find its ctor/dtor routine.  */
    TREE_PUBLIC (current_function_decl) = ! targetm.have_ctors_dtors;
  
--- 1935,1949 ----
        sprintf (type, "%c%c%.5u", method_type, joiner, initp);
      }
    else
      sprintf (type, "%c", method_type);
  
!   fndecl = build_lang_decl (FUNCTION_DECL, 
! 			    get_file_function_name_long (type),
! 			    build_function_type (void_type_node,
! 						 void_list_node));
!   start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
  
    /* It can be a static function as long as collect2 does not have
       to scan the object file to find its ctor/dtor routine.  */
    TREE_PUBLIC (current_function_decl) = ! targetm.have_ctors_dtors;
  
*************** start_static_storage_duration_function (
*** 2104,2117 ****
  
         static void __ssdf (int __initialize_p, init __priority_p);
         
       It is static because we only need to call this function from the
       various constructor and destructor functions for this module.  */
!   start_function (/*specs=*/NULL_TREE, 
! 		  ssdf_decl,
! 		  /*attrs=*/NULL_TREE,
! 		  SF_PRE_PARSED);
  
    /* Set up the scope of the outermost block in the function.  */
    body = begin_compound_stmt (BCS_FN_BODY);
  
    /* This function must not be deferred because we are depending on
--- 2106,2118 ----
  
         static void __ssdf (int __initialize_p, init __priority_p);
         
       It is static because we only need to call this function from the
       various constructor and destructor functions for this module.  */
!   start_preparsed_function (ssdf_decl,
! 			    /*attrs=*/NULL_TREE,
! 			    SF_PRE_PARSED);
  
    /* Set up the scope of the outermost block in the function.  */
    body = begin_compound_stmt (BCS_FN_BODY);
  
    /* This function must not be deferred because we are depending on
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.374
diff -c -5 -p -r1.374 init.c
*** cp/init.c	16 Jun 2004 01:21:30 -0000	1.374
--- cp/init.c	22 Jun 2004 02:13:17 -0000
*************** build_builtin_delete_call (tree addr)
*** 1663,1791 ****
     free the memory returned by `new'.
  
     PLACEMENT is the `placement' list for user-defined operator new ().  */
  
  tree
! build_new (tree placement, tree decl, tree init, int use_global_new)
  {
!   tree type, rval;
!   tree nelts = NULL_TREE, t;
!   int has_array = 0;
  
!   if (decl == error_mark_node)
      return error_mark_node;
  
-   if (TREE_CODE (decl) == TREE_LIST)
-     {
-       tree absdcl = TREE_VALUE (decl);
-       tree last_absdcl = NULL_TREE;
- 
-       if (current_function_decl
- 	  && DECL_CONSTRUCTOR_P (current_function_decl))
- 	my_friendly_assert (immediate_size_expand == 0, 19990926);
- 
-       nelts = integer_one_node;
- 
-       if (absdcl && TREE_CODE (absdcl) == CALL_EXPR)
- 	abort ();
-       while (absdcl && TREE_CODE (absdcl) == INDIRECT_REF)
- 	{
- 	  last_absdcl = absdcl;
- 	  absdcl = TREE_OPERAND (absdcl, 0);
- 	}
- 
-       if (absdcl && TREE_CODE (absdcl) == ARRAY_REF)
- 	{
- 	  /* Probably meant to be a vec new.  */
- 	  tree this_nelts;
- 
- 	  while (TREE_OPERAND (absdcl, 0)
- 		 && TREE_CODE (TREE_OPERAND (absdcl, 0)) == ARRAY_REF)
- 	    {
- 	      last_absdcl = absdcl;
- 	      absdcl = TREE_OPERAND (absdcl, 0);
- 	    }
- 
- 	  has_array = 1;
- 	  this_nelts = TREE_OPERAND (absdcl, 1);
- 	  if (this_nelts != error_mark_node)
- 	    {
- 	      if (this_nelts == NULL_TREE)
- 		error ("new of array type fails to specify size");
- 	      else if (processing_template_decl)
- 		{
- 		  nelts = this_nelts;
- 		  absdcl = TREE_OPERAND (absdcl, 0);
- 		}
- 	      else
- 		{
- 		  if (build_expr_type_conversion (WANT_INT | WANT_ENUM, 
- 						  this_nelts, false)
- 		      == NULL_TREE)
- 		    pedwarn ("size in array new must have integral type");
- 
- 		  this_nelts = save_expr (cp_convert (sizetype, this_nelts));
- 		  absdcl = TREE_OPERAND (absdcl, 0);
- 	          if (this_nelts == integer_zero_node)
- 		    {
- 		      warning ("zero size array reserves no space");
- 		      nelts = integer_zero_node;
- 		    }
- 		  else
- 		    nelts = cp_build_binary_op (MULT_EXPR, nelts, this_nelts);
- 		}
- 	    }
- 	  else
- 	    nelts = integer_zero_node;
- 	}
- 
-       if (last_absdcl)
- 	TREE_OPERAND (last_absdcl, 0) = absdcl;
-       else
- 	TREE_VALUE (decl) = absdcl;
- 
-       type = groktypename (decl);
-       if (! type || type == error_mark_node)
- 	return error_mark_node;
-     }
-   else if (TREE_CODE (decl) == IDENTIFIER_NODE)
-     {
-       if (IDENTIFIER_HAS_TYPE_VALUE (decl))
- 	{
- 	  /* An aggregate type.  */
- 	  type = IDENTIFIER_TYPE_VALUE (decl);
- 	  decl = TYPE_MAIN_DECL (type);
- 	}
-       else
- 	{
- 	  /* A builtin type.  */
- 	  decl = lookup_name (decl, 1);
- 	  my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 215);
- 	  type = TREE_TYPE (decl);
- 	}
-     }
-   else if (TREE_CODE (decl) == TYPE_DECL)
-     {
-       type = TREE_TYPE (decl);
-     }
-   else
-     {
-       type = decl;
-       decl = TYPE_MAIN_DECL (type);
-     }
- 
    if (processing_template_decl)
      {
-       if (has_array)
- 	t = tree_cons (tree_cons (NULL_TREE, type, NULL_TREE),
- 		       build_min_nt (ARRAY_REF, NULL_TREE, nelts),
- 		       NULL_TREE);
-       else
- 	t = type;
- 	
        rval = build_min (NEW_EXPR, build_pointer_type (type), 
! 			placement, t, init);
        NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
        TREE_SIDE_EFFECTS (rval) = 1;
        return rval;
      }
  
--- 1663,1684 ----
     free the memory returned by `new'.
  
     PLACEMENT is the `placement' list for user-defined operator new ().  */
  
  tree
! build_new (tree placement, tree type, tree nelts, tree init, 
! 	   int use_global_new)
  {
!   tree rval;
  
!   if (type == error_mark_node)
      return error_mark_node;
  
    if (processing_template_decl)
      {
        rval = build_min (NEW_EXPR, build_pointer_type (type), 
! 			placement, type, nelts, init);
        NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
        TREE_SIDE_EFFECTS (rval) = 1;
        return rval;
      }
  
*************** build_new (tree placement, tree decl, tr
*** 1802,1827 ****
      {
        error ("new cannot be applied to a function type");
        return error_mark_node;
      }
  
!   /* When the object being created is an array, the new-expression yields a
!      pointer to the initial element (if any) of the array.  For example,
!      both new int and new int[10] return an int*.  5.3.4.  */
!   if (TREE_CODE (type) == ARRAY_TYPE && has_array == 0)
!     {
!       nelts = array_type_nelts_top (type);
!       has_array = 1;
!       type = TREE_TYPE (type);
!     }
! 
!   if (has_array)
!     t = build_nt (ARRAY_REF, type, nelts);
!   else
!     t = type;
! 
!   rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init);
    NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
    TREE_SIDE_EFFECTS (rval) = 1;
    rval = build_new_1 (rval);
    if (rval == error_mark_node)
      return error_mark_node;
--- 1695,1706 ----
      {
        error ("new cannot be applied to a function type");
        return error_mark_node;
      }
  
!   rval = build (NEW_EXPR, build_pointer_type (type), placement, type,
! 		nelts, init);
    NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
    TREE_SIDE_EFFECTS (rval) = 1;
    rval = build_new_1 (rval);
    if (rval == error_mark_node)
      return error_mark_node;
*************** build_new_1 (tree exp)
*** 1954,1972 ****
    tree data_addr;
    tree init_preeval_expr = NULL_TREE;
  
    placement = TREE_OPERAND (exp, 0);
    type = TREE_OPERAND (exp, 1);
!   init = TREE_OPERAND (exp, 2);
    globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
  
!   if (TREE_CODE (type) == ARRAY_REF)
      {
        has_array = 1;
!       nelts = outer_nelts = TREE_OPERAND (type, 1);
!       type = TREE_OPERAND (type, 0);
! 
        /* Use an incomplete array type to avoid VLA headaches.  */
        full_type = build_cplus_array_type (type, NULL_TREE);
      }
    else
      full_type = type;
--- 1833,1850 ----
    tree data_addr;
    tree init_preeval_expr = NULL_TREE;
  
    placement = TREE_OPERAND (exp, 0);
    type = TREE_OPERAND (exp, 1);
!   nelts = TREE_OPERAND (exp, 2);
!   init = TREE_OPERAND (exp, 3);
    globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
  
!   if (nelts)
      {
        has_array = 1;
!       outer_nelts = nelts;
        /* Use an incomplete array type to avoid VLA headaches.  */
        full_type = build_cplus_array_type (type, NULL_TREE);
      }
    else
      full_type = type;
Index: cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.329
diff -c -5 -p -r1.329 lex.c
*** cp/lex.c	9 Jun 2004 18:34:05 -0000	1.329
--- cp/lex.c	22 Jun 2004 02:13:17 -0000
*************** struct impl_files
*** 81,146 ****
  };
  
  static struct impl_files *impl_file_chain;
  
  
- /* Return something to represent absolute declarators containing a *.
-    TARGET is the absolute declarator that the * contains.
-    CV_QUALIFIERS is a list of modifiers such as const or volatile
-    to apply to the pointer type, represented as identifiers.
- 
-    We return an INDIRECT_REF whose "contents" are TARGET
-    and whose type is the modifier list.  */
- 
- tree
- make_pointer_declarator (tree cv_qualifiers, tree target)
- {
-   if (target && TREE_CODE (target) == IDENTIFIER_NODE
-       && ANON_AGGRNAME_P (target))
-     error ("type name expected before `*'");
-   target = build_nt (INDIRECT_REF, target);
-   TREE_TYPE (target) = cv_qualifiers;
-   return target;
- }
- 
- /* Return something to represent absolute declarators containing a &.
-    TARGET is the absolute declarator that the & contains.
-    CV_QUALIFIERS is a list of modifiers such as const or volatile
-    to apply to the reference type, represented as identifiers.
- 
-    We return an ADDR_EXPR whose "contents" are TARGET
-    and whose type is the modifier list.  */
- 
- tree
- make_reference_declarator (tree cv_qualifiers, tree target)
- {
-   target = build_nt (ADDR_EXPR, target);
-   TREE_TYPE (target) = cv_qualifiers;
-   return target;
- }
- 
- tree
- make_call_declarator (tree target, tree parms, tree cv_qualifiers, 
-                       tree exception_specification)
- {
-   target = build_nt (CALL_EXPR, target,
- 		     tree_cons (parms, cv_qualifiers, NULL_TREE),
- 		     /* The third operand is really RTL.  We
- 			shouldn't put anything there.  */
- 		     NULL_TREE);
-   CALL_DECLARATOR_EXCEPTION_SPEC (target) = exception_specification;
-   return target;
- }
- 
- void
- set_quals_and_spec (tree call_declarator, tree cv_qualifiers, 
-                     tree exception_specification)
- {
-   CALL_DECLARATOR_QUALS (call_declarator) = cv_qualifiers;
-   CALL_DECLARATOR_EXCEPTION_SPEC (call_declarator) = exception_specification;
- }
- 
  int interface_only;		/* whether or not current file is only for
  				   interface definitions.  */
  int interface_unknown;		/* whether or not we know this class
  				   to behave according to #pragma interface.  */
  
--- 81,90 ----
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.285
diff -c -5 -p -r1.285 method.c
*** cp/method.c	16 Jun 2004 01:21:31 -0000	1.285
--- cp/method.c	22 Jun 2004 02:13:17 -0000
*************** use_thunk (tree thunk_fndecl, bool emit_
*** 460,470 ****
  	error ("generic thunk code fails for method `%#D' which uses `...'",
  	       function);
  
        DECL_RESULT (thunk_fndecl) = NULL_TREE;
  
!       start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
        /* We don't bother with a body block for thunks.  */
  
        /* There's no need to check accessibility inside the thunk body.  */
        push_deferring_access_checks (dk_no_check);
  
--- 460,470 ----
  	error ("generic thunk code fails for method `%#D' which uses `...'",
  	       function);
  
        DECL_RESULT (thunk_fndecl) = NULL_TREE;
  
!       start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
        /* We don't bother with a body block for thunks.  */
  
        /* There's no need to check accessibility inside the thunk body.  */
        push_deferring_access_checks (dk_no_check);
  
*************** synthesize_method (tree fndecl)
*** 753,763 ****
       user a hint as to why we are attempting to generate the
       function.  */
    DECL_SOURCE_LOCATION (fndecl) = input_location;
  
    interface_unknown = 1;
!   start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
    clear_last_expr ();
    stmt = begin_function_body ();
  
    if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
      {
--- 753,763 ----
       user a hint as to why we are attempting to generate the
       function.  */
    DECL_SOURCE_LOCATION (fndecl) = input_location;
  
    interface_unknown = 1;
!   start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
    clear_last_expr ();
    stmt = begin_function_body ();
  
    if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
      {
*************** locate_copy (tree type, void *client_)
*** 948,1029 ****
     reference argument or a non-const reference.  */
  
  tree
  implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
  {
!   tree declspecs = NULL_TREE;
!   tree fn, args = NULL_TREE;
    tree raises = empty_except_spec;
!   bool retref = false;
!   bool has_parm = false;
!   tree name = constructor_name (type);
  
    switch (kind)
      {
      case sfk_destructor:
        /* Destructor.  */
!       name = build_nt (BIT_NOT_EXPR, name);
!       args = void_list_node;
        raises = synthesize_exception_spec (type, &locate_dtor, 0);
        break;
  
      case sfk_constructor:
        /* Default constructor.  */
!       args = void_list_node;
        raises = synthesize_exception_spec (type, &locate_ctor, 0);
        break;
  
      case sfk_copy_constructor:
      case sfk_assignment_operator:
      {
        struct copy_data data;
-       tree argtype = type;
        
-       has_parm = true;
        data.name = NULL;
        data.quals = 0;
        if (kind == sfk_assignment_operator)
          {
!           retref = true;
!           declspecs = build_tree_list (NULL_TREE, type);
! 
            name = ansi_assopname (NOP_EXPR);
            data.name = name;
          }
        if (const_p)
          {
            data.quals = TYPE_QUAL_CONST;
!           argtype = build_qualified_type (argtype, TYPE_QUAL_CONST);
          }
!     
!       argtype = build_reference_type (argtype);
!       args = build_tree_list (hash_tree_chain (argtype, NULL_TREE),
! 			      get_identifier ("_ctor_arg"));
!       args = tree_cons (NULL_TREE, args, void_list_node);
!       
        raises = synthesize_exception_spec (type, &locate_copy, &data);
        break;
      }
      default:
        abort ();
      }
  
!   TREE_PARMLIST (args) = 1;
! 
!   {
!     tree declarator = make_call_declarator (name, args, NULL_TREE, raises);
!     
!     if (retref)
!       declarator = build_nt (ADDR_EXPR, declarator);
! 
!     fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
!     if (has_parm)
!       TREE_USED (FUNCTION_FIRST_USER_PARM (fn)) = 1;
!   }
! 
!   my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 20000408);
! 
    DECL_ARTIFICIAL (fn) = 1;
    DECL_NOT_REALLY_EXTERN (fn) = 1;
    DECL_DECLARED_INLINE_P (fn) = 1;
    DECL_INLINE (fn) = 1;
    if (TREE_USED (fn))
--- 948,1045 ----
     reference argument or a non-const reference.  */
  
  tree
  implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
  {
!   tree fn;
!   tree parameter_types = void_list_node;
!   tree return_type = void_type_node;
!   tree fn_type;
    tree raises = empty_except_spec;
!   tree rhs_parm_type = NULL_TREE;
!   tree name;
  
    switch (kind)
      {
      case sfk_destructor:
        /* Destructor.  */
!       name = constructor_name (type);
        raises = synthesize_exception_spec (type, &locate_dtor, 0);
        break;
  
      case sfk_constructor:
        /* Default constructor.  */
!       name = constructor_name (type);
        raises = synthesize_exception_spec (type, &locate_ctor, 0);
+       TYPE_HAS_CONSTRUCTOR (type) = 1;
        break;
  
      case sfk_copy_constructor:
+       TYPE_HAS_CONSTRUCTOR (type) = 1;
+       /* Fall through. */
      case sfk_assignment_operator:
      {
        struct copy_data data;
        
        data.name = NULL;
        data.quals = 0;
        if (kind == sfk_assignment_operator)
          {
! 	  return_type = build_reference_type (type);
            name = ansi_assopname (NOP_EXPR);
            data.name = name;
          }
+       else
+ 	name = constructor_name (type);
+ 
        if (const_p)
          {
            data.quals = TYPE_QUAL_CONST;
! 	  rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST);
          }
!       else
! 	rhs_parm_type = type;
!       rhs_parm_type = build_reference_type (rhs_parm_type);
!       parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types);
        raises = synthesize_exception_spec (type, &locate_copy, &data);
        break;
      }
      default:
        abort ();
      }
  
!   /* Create the function.  */
!   fn_type = build_method_type_directly (type, return_type, parameter_types);
!   if (raises)
!     fn_type = build_exception_variant (fn_type, raises);
!   fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
!   if (kind == sfk_constructor || kind == sfk_copy_constructor)
!     DECL_CONSTRUCTOR_P (fn) = 1;
!   else if (kind == sfk_destructor)
!     DECL_DESTRUCTOR_P (fn) = 1;
!   else
!     {
!       DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
!       SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
!     }
!   /* Create the argument list.  The call to "grokclassfn" will add the
!      "this" parameter and any other implicit parameters.  */
!   if (rhs_parm_type)
!     {
!       /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we
! 	 want its type to be included in the mangled function
! 	 name.  */
!       DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
!       TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
!     }
! 
!   grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
! 	       /*quals=*/NULL_TREE);
!   grok_special_member_properties (fn);
!   cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
! 		  /*flags=*/LOOKUP_ONLYCONVERTING);
!   DECL_IN_AGGR_P (fn) = 1;
    DECL_ARTIFICIAL (fn) = 1;
    DECL_NOT_REALLY_EXTERN (fn) = 1;
    DECL_DECLARED_INLINE_P (fn) = 1;
    DECL_INLINE (fn) = 1;
    if (TREE_USED (fn))
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/optimize.c,v
retrieving revision 1.109
diff -c -5 -p -r1.109 optimize.c
*** cp/optimize.c	20 May 2004 11:36:14 -0000	1.109
--- cp/optimize.c	22 Jun 2004 02:13:17 -0000
*************** maybe_clone_body (tree fn)
*** 130,140 ****
  	/* Update this parameter.  */
  	update_cloned_parm (parm, clone_parm);
  
        /* Start processing the function.  */
        push_to_top_level ();
!       start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED);
  
        /* Remap the parameters.  */
        decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
        for (parmno = 0,
  	     parm = DECL_ARGUMENTS (fn),
--- 130,140 ----
  	/* Update this parameter.  */
  	update_cloned_parm (parm, clone_parm);
  
        /* Start processing the function.  */
        push_to_top_level ();
!       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
  
        /* Remap the parameters.  */
        decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
        for (parmno = 0,
  	     parm = DECL_ARGUMENTS (fn),
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.211
diff -c -5 -p -r1.211 parser.c
*** cp/parser.c	17 Jun 2004 01:24:04 -0000	1.211
--- cp/parser.c	22 Jun 2004 02:13:17 -0000
*************** cp_lexer_stop_debugging (cp_lexer* lexer
*** 993,1002 ****
--- 993,1177 ----
  {
    --lexer->debugging_p;
  }
  
  
+ /* Declarators.  */
+ 
+ /* Nothing other than the parser should be creating declarators;
+    declarators are a semi-syntactic representation of C++ entities.
+    Other parts of the front end that need to create entities (like
+    VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
+ 
+ static cp_declarator *make_id_declarator 
+   (tree);
+ static cp_declarator *make_call_declarator	
+   (cp_declarator *, cp_parameter_declarator *, tree, tree);
+ static cp_declarator *make_array_declarator	
+   (cp_declarator *, tree);
+ static cp_declarator *make_pointer_declarator	
+   (tree, cp_declarator *);
+ static cp_declarator *make_reference_declarator	
+   (tree, cp_declarator *);
+ static cp_parameter_declarator *make_parameter_declarator 
+   (tree, cp_declarator *, tree);
+ static cp_declarator *make_ptrmem_declarator	
+   (tree, tree, cp_declarator *);
+ 
+ cp_declarator *cp_error_declarator;
+ 
+ /* The obstack on which declarators and related data structures are
+    allocated.  */
+ static struct obstack declarator_obstack;
+ 
+ /* Alloc BYTES from the declarator memory pool.  */
+ 
+ static inline void *
+ alloc_declarator (size_t bytes)
+ {
+   return obstack_alloc (&declarator_obstack, bytes);
+ }
+ 
+ /* Allocate a declarator of the indicated KIND.  Clear fields that are
+    common to all declarators.  */
+ 
+ static cp_declarator *
+ make_declarator (cp_declarator_kind kind)
+ {
+   cp_declarator *declarator;
+ 
+   declarator = (cp_declarator *) alloc_declarator (sizeof (cp_declarator));
+   declarator->kind = kind;
+   declarator->attributes = NULL_TREE;
+   declarator->declarator = NULL;
+ 
+   return declarator;
+ }
+ 
+ /* Make a declarator for a generalized identifier.  */
+ 
+ cp_declarator *
+ make_id_declarator (tree id)
+ {
+   cp_declarator *declarator;
+   
+   declarator = make_declarator (cdk_id);
+   declarator->u.id.name = id;
+   declarator->u.id.sfk = sfk_none;
+ 
+   return declarator;
+ }
+ 
+ /* Make a declarator for a pointer to TARGET.  CV_QUALIFIERS is a list
+    of modifiers such as const or volatile to apply to the pointer
+    type, represented as identifiers.  */
+ 
+ cp_declarator *
+ make_pointer_declarator (tree cv_qualifiers, cp_declarator *target)
+ {
+   cp_declarator *declarator;
+ 
+   declarator = make_declarator (cdk_pointer);
+   declarator->declarator = target;
+   declarator->u.pointer.qualifiers = cv_qualifiers;
+   declarator->u.pointer.class_type = NULL_TREE;
+ 
+   return declarator;
+ }
+ 
+ /* Like make_pointer_declarator -- but for references.  */
+ 
+ cp_declarator *
+ make_reference_declarator (tree cv_qualifiers, cp_declarator *target)
+ {
+   cp_declarator *declarator;
+ 
+   declarator = make_declarator (cdk_reference);
+   declarator->declarator = target;
+   declarator->u.pointer.qualifiers = cv_qualifiers;
+   declarator->u.pointer.class_type = NULL_TREE;
+ 
+   return declarator;
+ }
+ 
+ /* Like make_pointer_declarator -- but for a pointer to a non-static
+    member of CLASS_TYPE.  */
+ 
+ cp_declarator *
+ make_ptrmem_declarator (tree cv_qualifiers, tree class_type,
+ 			cp_declarator *pointee)
+ {
+   cp_declarator *declarator;
+ 
+   declarator = make_declarator (cdk_ptrmem);
+   declarator->declarator = pointee;
+   declarator->u.pointer.qualifiers = cv_qualifiers;
+   declarator->u.pointer.class_type = class_type;
+ 
+   return declarator;
+ }
+ 
+ /* Make a declarator for the function given by TARGET, with the
+    indicated PARMS.  The CV_QUALIFIERS aply to the function, as in
+    "const"-qualified member function.  The EXCEPTION_SPECIFICATION
+    indicates what exceptions can be thrown.  */
+ 
+ cp_declarator *
+ make_call_declarator (cp_declarator *target, 
+ 		      cp_parameter_declarator *parms,
+ 		      tree cv_qualifiers, 
+                       tree exception_specification)
+ {
+   cp_declarator *declarator;
+ 
+   declarator = make_declarator (cdk_function);
+   declarator->declarator = target;
+   declarator->u.function.parameters = parms;
+   declarator->u.function.qualifiers = cv_qualifiers;
+   declarator->u.function.exception_specification = exception_specification;
+ 
+   return declarator;
+ }
+ 
+ /* Make a declarator for an array of BOUNDS elements, each of which is
+    defined by ELEMENT.  */
+ 
+ cp_declarator *
+ make_array_declarator (cp_declarator *element, tree bounds)
+ {
+   cp_declarator *declarator;
+ 
+   declarator = make_declarator (cdk_array);
+   declarator->declarator = element;
+   declarator->u.array.bounds = bounds;
+ 
+   return declarator;
+ }
+ 
+ cp_parameter_declarator *no_parameters;
+ 
+ /* Create a parameter declarator with the indicated DECL_SPECIFIERS,
+    DECLARATOR and DEFAULT_ARGUMENT.  */
+ 
+ cp_parameter_declarator *
+ make_parameter_declarator (tree decl_specifiers, 
+ 			   cp_declarator *declarator,
+ 			   tree default_argument)
+ {
+   cp_parameter_declarator *parameter;
+ 
+   parameter = ((cp_parameter_declarator *) 
+ 	       alloc_declarator (sizeof (cp_parameter_declarator)));
+   parameter->next = NULL;
+   parameter->decl_specifiers = decl_specifiers;
+   parameter->declarator = declarator;
+   parameter->default_argument = default_argument;
+   parameter->ellipsis_p = false;
+ 
+   return parameter;
+ }
+ 
  /* The parser.  */
  
  /* Overview
     --------
  
*************** static enum tree_code cp_parser_unary_op
*** 1364,1377 ****
  static tree cp_parser_new_expression
    (cp_parser *);
  static tree cp_parser_new_placement
    (cp_parser *);
  static tree cp_parser_new_type_id
    (cp_parser *);
! static tree cp_parser_new_declarator_opt
!   (cp_parser *);
! static tree cp_parser_direct_new_declarator
    (cp_parser *);
  static tree cp_parser_new_initializer
    (cp_parser *);
  static tree cp_parser_delete_expression
    (cp_parser *);
--- 1539,1552 ----
  static tree cp_parser_new_expression
    (cp_parser *);
  static tree cp_parser_new_placement
    (cp_parser *);
  static tree cp_parser_new_type_id
+   (cp_parser *, tree *);
+ static cp_declarator *cp_parser_new_declarator_opt
    (cp_parser *);
! static cp_declarator *cp_parser_direct_new_declarator
    (cp_parser *);
  static tree cp_parser_new_initializer
    (cp_parser *);
  static tree cp_parser_delete_expression
    (cp_parser *);
*************** static void cp_parser_linkage_specificat
*** 1493,1505 ****
  
  /* Declarators [gram.dcl.decl] */
  
  static tree cp_parser_init_declarator
    (cp_parser *, tree, tree, bool, bool, int, bool *);
! static tree cp_parser_declarator
    (cp_parser *, cp_parser_declarator_kind, int *, bool *);
! static tree cp_parser_direct_declarator
    (cp_parser *, cp_parser_declarator_kind, int *);
  static enum tree_code cp_parser_ptr_operator
    (cp_parser *, tree *, tree *);
  static tree cp_parser_cv_qualifier_seq_opt
    (cp_parser *);
--- 1668,1680 ----
  
  /* Declarators [gram.dcl.decl] */
  
  static tree cp_parser_init_declarator
    (cp_parser *, tree, tree, bool, bool, int, bool *);
! static cp_declarator *cp_parser_declarator
    (cp_parser *, cp_parser_declarator_kind, int *, bool *);
! static cp_declarator *cp_parser_direct_declarator
    (cp_parser *, cp_parser_declarator_kind, int *);
  static enum tree_code cp_parser_ptr_operator
    (cp_parser *, tree *, tree *);
  static tree cp_parser_cv_qualifier_seq_opt
    (cp_parser *);
*************** static tree cp_parser_declarator_id
*** 1509,1523 ****
    (cp_parser *);
  static tree cp_parser_type_id
    (cp_parser *);
  static tree cp_parser_type_specifier_seq
    (cp_parser *);
! static tree cp_parser_parameter_declaration_clause
    (cp_parser *);
! static tree cp_parser_parameter_declaration_list
!   (cp_parser *);
! static tree cp_parser_parameter_declaration
    (cp_parser *, bool, bool *);
  static void cp_parser_function_body
    (cp_parser *);
  static tree cp_parser_initializer
    (cp_parser *, bool *, bool *);
--- 1684,1698 ----
    (cp_parser *);
  static tree cp_parser_type_id
    (cp_parser *);
  static tree cp_parser_type_specifier_seq
    (cp_parser *);
! static cp_parameter_declarator *cp_parser_parameter_declaration_clause
    (cp_parser *);
! static cp_parameter_declarator *cp_parser_parameter_declaration_list
!   (cp_parser *, bool *);
! static cp_parameter_declarator *cp_parser_parameter_declaration
    (cp_parser *, bool, bool *);
  static void cp_parser_function_body
    (cp_parser *);
  static tree cp_parser_initializer
    (cp_parser *, bool *, bool *);
*************** static tree cp_parser_base_specifier
*** 1559,1569 ****
  
  static tree cp_parser_conversion_function_id
    (cp_parser *);
  static tree cp_parser_conversion_type_id
    (cp_parser *);
! static tree cp_parser_conversion_declarator_opt
    (cp_parser *);
  static bool cp_parser_ctor_initializer_opt
    (cp_parser *);
  static void cp_parser_mem_initializer_list
    (cp_parser *);
--- 1734,1744 ----
  
  static tree cp_parser_conversion_function_id
    (cp_parser *);
  static tree cp_parser_conversion_type_id
    (cp_parser *);
! static cp_declarator *cp_parser_conversion_declarator_opt
    (cp_parser *);
  static bool cp_parser_ctor_initializer_opt
    (cp_parser *);
  static void cp_parser_mem_initializer_list
    (cp_parser *);
*************** static tree cp_parser_operator
*** 1584,1594 ****
  static void cp_parser_template_declaration
    (cp_parser *, bool);
  static tree cp_parser_template_parameter_list
    (cp_parser *);
  static tree cp_parser_template_parameter
!   (cp_parser *);
  static tree cp_parser_type_parameter
    (cp_parser *);
  static tree cp_parser_template_id
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_template_name
--- 1759,1769 ----
  static void cp_parser_template_declaration
    (cp_parser *, bool);
  static tree cp_parser_template_parameter_list
    (cp_parser *);
  static tree cp_parser_template_parameter
!   (cp_parser *, bool *);
  static tree cp_parser_type_parameter
    (cp_parser *);
  static tree cp_parser_template_id
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_template_name
*************** static tree cp_parser_lookup_name
*** 1645,1655 ****
  static tree cp_parser_lookup_name_simple
    (cp_parser *, tree);
  static tree cp_parser_maybe_treat_template_as_class
    (tree, bool);
  static bool cp_parser_check_declarator_template_parameters
!   (cp_parser *, tree);
  static bool cp_parser_check_template_parameters
    (cp_parser *, unsigned);
  static tree cp_parser_simple_cast_expression
    (cp_parser *);
  static tree cp_parser_binary_expression
--- 1820,1830 ----
  static tree cp_parser_lookup_name_simple
    (cp_parser *, tree);
  static tree cp_parser_maybe_treat_template_as_class
    (tree, bool);
  static bool cp_parser_check_declarator_template_parameters
!   (cp_parser *, cp_declarator *);
  static bool cp_parser_check_template_parameters
    (cp_parser *, unsigned);
  static tree cp_parser_simple_cast_expression
    (cp_parser *);
  static tree cp_parser_binary_expression
*************** static tree cp_parser_binary_expression
*** 1657,1677 ****
  static tree cp_parser_global_scope_opt
    (cp_parser *, bool);
  static bool cp_parser_constructor_declarator_p
    (cp_parser *, bool);
  static tree cp_parser_function_definition_from_specifiers_and_declarator
!   (cp_parser *, tree, tree, tree);
  static tree cp_parser_function_definition_after_declarator
    (cp_parser *, bool);
  static void cp_parser_template_declaration_after_export
    (cp_parser *, bool);
  static tree cp_parser_single_declaration
    (cp_parser *, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
  static tree cp_parser_save_member_function_body
!   (cp_parser *, tree, tree, tree);
  static tree cp_parser_enclosed_template_argument_list
    (cp_parser *);
  static void cp_parser_save_default_args
    (cp_parser *, tree);
  static void cp_parser_late_parsing_for_member
--- 1832,1852 ----
  static tree cp_parser_global_scope_opt
    (cp_parser *, bool);
  static bool cp_parser_constructor_declarator_p
    (cp_parser *, bool);
  static tree cp_parser_function_definition_from_specifiers_and_declarator
!   (cp_parser *, tree, tree, const cp_declarator *);
  static tree cp_parser_function_definition_after_declarator
    (cp_parser *, bool);
  static void cp_parser_template_declaration_after_export
    (cp_parser *, bool);
  static tree cp_parser_single_declaration
    (cp_parser *, bool, bool *);
  static tree cp_parser_functional_cast
    (cp_parser *, tree);
  static tree cp_parser_save_member_function_body
!   (cp_parser *, tree, cp_declarator *, tree);
  static tree cp_parser_enclosed_template_argument_list
    (cp_parser *);
  static void cp_parser_save_default_args
    (cp_parser *, tree);
  static void cp_parser_late_parsing_for_member
*************** static void cp_parser_name_lookup_error
*** 1727,1737 ****
  static bool cp_parser_simulate_error
    (cp_parser *);
  static void cp_parser_check_type_definition
    (cp_parser *);
  static void cp_parser_check_for_definition_in_return_type
!   (tree, int);
  static void cp_parser_check_for_invalid_template_id
    (cp_parser *, tree);
  static bool cp_parser_non_integral_constant_expression
    (cp_parser *, const char *);
  static void cp_parser_diagnose_invalid_type_name
--- 1902,1912 ----
  static bool cp_parser_simulate_error
    (cp_parser *);
  static void cp_parser_check_type_definition
    (cp_parser *);
  static void cp_parser_check_for_definition_in_return_type
!   (cp_declarator *, int);
  static void cp_parser_check_for_invalid_template_id
    (cp_parser *, tree);
  static bool cp_parser_non_integral_constant_expression
    (cp_parser *, const char *);
  static void cp_parser_diagnose_invalid_type_name
*************** cp_parser_check_type_definition (cp_pars
*** 1869,1890 ****
     DECLARATOR is a function declarator and DECLARES_CLASS_OR_ENUM
     indicates that a type was defined in the decl-specifiers for DECL,
     then an error is issued.  */
  
  static void
! cp_parser_check_for_definition_in_return_type (tree declarator,
  					       int declares_class_or_enum)
  {
    /* [dcl.fct] forbids type definitions in return types.
       Unfortunately, it's not easy to know whether or not we are
       processing a return type until after the fact.  */
    while (declarator
! 	 && (TREE_CODE (declarator) == INDIRECT_REF
! 	     || TREE_CODE (declarator) == ADDR_EXPR))
!     declarator = TREE_OPERAND (declarator, 0);
    if (declarator
!       && TREE_CODE (declarator) == CALL_EXPR
        && declares_class_or_enum & 2)
      error ("new types may not be defined in a return type");
  }
  
  /* A type-specifier (TYPE) has been parsed which cannot be followed by
--- 2044,2066 ----
     DECLARATOR is a function declarator and DECLARES_CLASS_OR_ENUM
     indicates that a type was defined in the decl-specifiers for DECL,
     then an error is issued.  */
  
  static void
! cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
  					       int declares_class_or_enum)
  {
    /* [dcl.fct] forbids type definitions in return types.
       Unfortunately, it's not easy to know whether or not we are
       processing a return type until after the fact.  */
    while (declarator
! 	 && (declarator->kind == cdk_pointer
! 	     || declarator->kind == cdk_reference
! 	     || declarator->kind == cdk_ptrmem))
!     declarator = declarator->declarator;
    if (declarator
!       && declarator->kind == cdk_function
        && declares_class_or_enum & 2)
      error ("new types may not be defined in a return type");
  }
  
  /* A type-specifier (TYPE) has been parsed which cannot be followed by
*************** cp_parser_identifier (cp_parser* parser)
*** 2421,2451 ****
     Returns TRUE if all went well.  */
  
  static bool
  cp_parser_translation_unit (cp_parser* parser)
  {
    while (true)
      {
        cp_parser_declaration_seq_opt (parser);
  
        /* If there are no tokens left then all went well.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
! 	break;
  
!       /* Otherwise, issue an error message.  */
!       cp_parser_error (parser, "expected declaration");
!       return false;
      }
  
!   /* Consume the EOF token.  */
!   cp_parser_require (parser, CPP_EOF, "end-of-file");
! 
!   /* Finish up.  */
!   finish_translation_unit ();
  
    /* All went well.  */
!   return true;
  }
  
  /* Expressions [gram.expr] */
  
  /* Parse a primary-expression.
--- 2597,2655 ----
     Returns TRUE if all went well.  */
  
  static bool
  cp_parser_translation_unit (cp_parser* parser)
  {
+   /* The address of the first non-permanent object on the declarator
+      obstack.  */
+   static void *declarator_obstack_base;
+ 
+   bool success;
+   
+   /* Create the declarator obstack, if necessary.  */
+   if (!cp_error_declarator)
+     {
+       gcc_obstack_init (&declarator_obstack);
+       /* Create the error declarator.  */
+       cp_error_declarator = make_declarator (cdk_error);
+       /* Create the empty parameter list.  */
+       no_parameters = make_parameter_declarator (NULL_TREE, NULL, NULL_TREE);
+       /* Remember where the base of the declarator obstack lies.  */
+       declarator_obstack_base = obstack_next_free (&declarator_obstack);
+     }
+ 
    while (true)
      {
        cp_parser_declaration_seq_opt (parser);
  
        /* If there are no tokens left then all went well.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
! 	{
! 	  /* Consume the EOF token.  */
! 	  cp_parser_require (parser, CPP_EOF, "end-of-file");
! 	  
! 	  /* Finish up.  */
! 	  finish_translation_unit ();
  
! 	  success = true;
! 	  break;
! 	}
!       else
! 	{
! 	  cp_parser_error (parser, "expected declaration");
! 	  success = false;
! 	  break;
! 	}
      }
  
!   /* Make sure the declarator obstack was fully cleaned up.  */
!   my_friendly_assert (obstack_next_free (&declarator_obstack) ==
! 		      declarator_obstack_base,
! 		      20040621);
  
    /* All went well.  */
!   return success;
  }
  
  /* Expressions [gram.expr] */
  
  /* Parse a primary-expression.
*************** cp_parser_new_expression (cp_parser* par
*** 4555,4564 ****
--- 4759,4769 ----
  {
    bool global_scope_p;
    tree placement;
    tree type;
    tree initializer;
+   tree nelts;
  
    /* Look for the optional `::' operator.  */
    global_scope_p
      = (cp_parser_global_scope_opt (parser,
  				   /*current_scope_valid_p=*/false)
*************** cp_parser_new_expression (cp_parser* par
*** 4591,4604 ****
  	{
  	  error ("array bound forbidden after parenthesized type-id");
  	  inform ("try removing the parentheses around the type-id");
  	  cp_parser_direct_new_declarator (parser);
  	}
      }
    /* Otherwise, there must be a new-type-id.  */
    else
!     type = cp_parser_new_type_id (parser);
  
    /* If the next token is a `(', then we have a new-initializer.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
      initializer = cp_parser_new_initializer (parser);
    else
--- 4796,4810 ----
  	{
  	  error ("array bound forbidden after parenthesized type-id");
  	  inform ("try removing the parentheses around the type-id");
  	  cp_parser_direct_new_declarator (parser);
  	}
+       nelts = integer_one_node;
      }
    /* Otherwise, there must be a new-type-id.  */
    else
!     type = cp_parser_new_type_id (parser, &nelts);
  
    /* If the next token is a `(', then we have a new-initializer.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
      initializer = cp_parser_new_initializer (parser);
    else
*************** cp_parser_new_expression (cp_parser* par
*** 4608,4618 ****
       expression.  */
    if (cp_parser_non_integral_constant_expression (parser, "`new'"))
      return error_mark_node;
  
    /* Create a representation of the new-expression.  */
!   return build_new (placement, type, initializer, global_scope_p);
  }
  
  /* Parse a new-placement.
  
     new-placement:
--- 4814,4824 ----
       expression.  */
    if (cp_parser_non_integral_constant_expression (parser, "`new'"))
      return error_mark_node;
  
    /* Create a representation of the new-expression.  */
!   return build_new (placement, type, nelts, initializer, global_scope_p);
  }
  
  /* Parse a new-placement.
  
     new-placement:
*************** cp_parser_new_placement (cp_parser* pars
*** 4635,4653 ****
  /* Parse a new-type-id.
  
     new-type-id:
       type-specifier-seq new-declarator [opt]
  
!    Returns a TREE_LIST whose TREE_PURPOSE is the type-specifier-seq,
!    and whose TREE_VALUE is the new-declarator.  */
  
  static tree
! cp_parser_new_type_id (cp_parser* parser)
  {
    tree type_specifier_seq;
!   tree declarator;
    const char *saved_message;
  
    /* The type-specifier sequence must not contain type definitions.
       (It cannot contain declarations of new types either, but if they
       are not definitions we will catch that because they are not
       complete.)  */
--- 4841,4863 ----
  /* Parse a new-type-id.
  
     new-type-id:
       type-specifier-seq new-declarator [opt]
  
!    Returns the TYPE allocated.  If the new-type-id indicates an array
!    type, *NELTS is set to the number of elements in the last array
!    bound; the TYPE will not include the last array bound.  */
  
  static tree
! cp_parser_new_type_id (cp_parser* parser, tree *nelts)
  {
    tree type_specifier_seq;
!   cp_declarator *new_declarator;
!   cp_declarator *declarator;
!   cp_declarator *outer_declarator;
    const char *saved_message;
+   tree type;
  
    /* The type-specifier sequence must not contain type definitions.
       (It cannot contain declarations of new types either, but if they
       are not definitions we will catch that because they are not
       complete.)  */
*************** cp_parser_new_type_id (cp_parser* parser
*** 4657,4681 ****
    /* Parse the type-specifier-seq.  */
    type_specifier_seq = cp_parser_type_specifier_seq (parser);
    /* Restore the old message.  */
    parser->type_definition_forbidden_message = saved_message;
    /* Parse the new-declarator.  */
!   declarator = cp_parser_new_declarator_opt (parser);
  
!   return build_tree_list (type_specifier_seq, declarator);
  }
  
  /* Parse an (optional) new-declarator.
  
     new-declarator:
       ptr-operator new-declarator [opt]
       direct-new-declarator
  
!    Returns a representation of the declarator.  See
!    cp_parser_declarator for the representations used.  */
  
! static tree
  cp_parser_new_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree type;
    tree cv_qualifier_seq;
--- 4867,4937 ----
    /* Parse the type-specifier-seq.  */
    type_specifier_seq = cp_parser_type_specifier_seq (parser);
    /* Restore the old message.  */
    parser->type_definition_forbidden_message = saved_message;
    /* Parse the new-declarator.  */
!   new_declarator = cp_parser_new_declarator_opt (parser);
! 
!   /* Determine the number of elements in the last array dimension, if
!      any.  */
!   *nelts = NULL_TREE;
!   /* Skip down to the last array dimension.  */
!   declarator = new_declarator;
!   outer_declarator = NULL;
!   while (declarator && (declarator->kind == cdk_pointer
! 			|| declarator->kind == cdk_ptrmem))
!     {
!       outer_declarator = declarator;
!       declarator = declarator->declarator;
!     }
!   while (declarator 
! 	 && declarator->kind == cdk_array
! 	 && declarator->declarator
! 	 && declarator->declarator->kind == cdk_array)
!     {
!       outer_declarator = declarator;
!       declarator = declarator->declarator;
!     }
!   
!   if (declarator && declarator->kind == cdk_array)
!     {
!       *nelts = declarator->u.array.bounds;
!       if (*nelts == error_mark_node)
! 	*nelts = integer_one_node;
!       else if (!processing_template_decl)
! 	{
! 	  if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, *nelts, 
! 					   false))
! 	    pedwarn ("size in array new must have integral type");
! 	  *nelts = save_expr (cp_convert (sizetype, *nelts));
! 	  if (*nelts == integer_zero_node)
! 	    warning ("zero size array reserves no space");
! 	}
!       if (outer_declarator)
! 	outer_declarator->declarator = declarator->declarator;
!       else
! 	new_declarator = NULL;
!     }
  
!   type = groktypename (type_specifier_seq, new_declarator);
!   if (TREE_CODE (type) == ARRAY_TYPE && *nelts == NULL_TREE)
!     {
!       *nelts = array_type_nelts_top (type);
!       type = TREE_TYPE (type);
!     }
!   return type;
  }
  
  /* Parse an (optional) new-declarator.
  
     new-declarator:
       ptr-operator new-declarator [opt]
       direct-new-declarator
  
!    Returns the declarator.  */
  
! static cp_declarator *
  cp_parser_new_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree type;
    tree cv_qualifier_seq;
*************** cp_parser_new_declarator_opt (cp_parser*
*** 4685,4734 ****
    /* Look for a ptr-operator.  */
    code = cp_parser_ptr_operator (parser, &type, &cv_qualifier_seq);
    /* If that worked, look for more new-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
!       tree declarator;
  
        /* Parse another optional declarator.  */
        declarator = cp_parser_new_declarator_opt (parser);
  
        /* Create the representation of the declarator.  */
!       if (code == INDIRECT_REF)
  	declarator = make_pointer_declarator (cv_qualifier_seq,
  					      declarator);
        else
  	declarator = make_reference_declarator (cv_qualifier_seq,
  						declarator);
  
-      /* Handle the pointer-to-member case.  */
-      if (type)
-        declarator = build_nt (SCOPE_REF, type, declarator);
- 
        return declarator;
      }
  
    /* If the next token is a `[', there is a direct-new-declarator.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
      return cp_parser_direct_new_declarator (parser);
  
!   return NULL_TREE;
  }
  
  /* Parse a direct-new-declarator.
  
     direct-new-declarator:
       [ expression ]
       direct-new-declarator [constant-expression]
  
!    Returns an ARRAY_REF, following the same conventions as are
!    documented for cp_parser_direct_declarator.  */
  
! static tree
  cp_parser_direct_new_declarator (cp_parser* parser)
  {
!   tree declarator = NULL_TREE;
  
    while (true)
      {
        tree expression;
  
--- 4941,4989 ----
    /* Look for a ptr-operator.  */
    code = cp_parser_ptr_operator (parser, &type, &cv_qualifier_seq);
    /* If that worked, look for more new-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
!       cp_declarator *declarator;
  
        /* Parse another optional declarator.  */
        declarator = cp_parser_new_declarator_opt (parser);
  
        /* Create the representation of the declarator.  */
!       if (type)
! 	declarator = make_ptrmem_declarator (cv_qualifier_seq,
! 					     type,
! 					     declarator);
!       else if (code == INDIRECT_REF)
  	declarator = make_pointer_declarator (cv_qualifier_seq,
  					      declarator);
        else
  	declarator = make_reference_declarator (cv_qualifier_seq,
  						declarator);
  
        return declarator;
      }
  
    /* If the next token is a `[', there is a direct-new-declarator.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
      return cp_parser_direct_new_declarator (parser);
  
!   return NULL;
  }
  
  /* Parse a direct-new-declarator.
  
     direct-new-declarator:
       [ expression ]
       direct-new-declarator [constant-expression]
  
!    */
  
! static cp_declarator *
  cp_parser_direct_new_declarator (cp_parser* parser)
  {
!   cp_declarator *declarator = NULL;
  
    while (true)
      {
        tree expression;
  
*************** cp_parser_direct_new_declarator (cp_pars
*** 4765,4775 ****
  					   NULL);
        /* Look for the closing `]'.  */
        cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
  
        /* Add this bound to the declarator.  */
!       declarator = build_nt (ARRAY_REF, declarator, expression);
  
        /* If the next token is not a `[', then there are no more
  	 bounds.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_SQUARE))
  	break;
--- 5020,5030 ----
  					   NULL);
        /* Look for the closing `]'.  */
        cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
  
        /* Add this bound to the declarator.  */
!       declarator = make_array_declarator (declarator, expression);
  
        /* If the next token is not a `[', then there are no more
  	 bounds.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_SQUARE))
  	break;
*************** cp_parser_condition (cp_parser* parser)
*** 6020,6030 ****
    if (!cp_parser_error_occurred (parser))
      {
        tree decl;
        tree asm_specification;
        tree attributes;
!       tree declarator;
        tree initializer = NULL_TREE;
  
        /* Parse the declarator.  */
        declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  					 /*ctor_dtor_or_conv_p=*/NULL,
--- 6275,6285 ----
    if (!cp_parser_error_occurred (parser))
      {
        tree decl;
        tree asm_specification;
        tree attributes;
!       cp_declarator *declarator;
        tree initializer = NULL_TREE;
  
        /* Parse the declarator.  */
        declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  					 /*ctor_dtor_or_conv_p=*/NULL,
*************** cp_parser_jump_statement (cp_parser* par
*** 6331,6343 ****
       block-declaration  */
  
  static void
  cp_parser_declaration_statement (cp_parser* parser)
  {
!   /* Parse the block-declaration.  */
    cp_parser_block_declaration (parser, /*statement_p=*/true);
  
    /* Finish off the statement.  */
    finish_stmt ();
  }
  
  /* Some dependent statements (like `if (cond) statement'), are
--- 6586,6606 ----
       block-declaration  */
  
  static void
  cp_parser_declaration_statement (cp_parser* parser)
  {
!   void *p;
! 
!   /* Get the high-water mark for the DECLARATOR_OBSTACK.  */
!   p = obstack_alloc (&declarator_obstack, 0);
! 
!  /* Parse the block-declaration.  */
    cp_parser_block_declaration (parser, /*statement_p=*/true);
  
+   /* Free any declarators allocated.  */
+   obstack_free (&declarator_obstack, p);
+ 
    /* Finish off the statement.  */
    finish_stmt ();
  }
  
  /* Some dependent statements (like `if (cond) statement'), are
*************** static void
*** 6464,6473 ****
--- 6727,6737 ----
  cp_parser_declaration (cp_parser* parser)
  {
    cp_token token1;
    cp_token token2;
    int saved_pedantic;
+   void *p;
  
    /* Set this here since we can be called after
       pushing the linkage specification.  */
    c_lex_string_translate = 1;
  
*************** cp_parser_declaration (cp_parser* parser
*** 6492,6501 ****
--- 6756,6768 ----
    if (token1.type != CPP_EOF)
      token2 = *cp_lexer_peek_nth_token (parser->lexer, 2);
  
    c_lex_string_translate = 1;
  
+   /* Get the high-water mark for the DECLARATOR_OBSTACK.  */
+   p = obstack_alloc (&declarator_obstack, 0);
+ 
    /* If the next token is `extern' and the following token is a string
       literal, then we have a linkage specification.  */
    if (token1.keyword == RID_EXTERN
        && cp_parser_is_string_literal (&token2))
      cp_parser_linkage_specification (parser);
*************** cp_parser_declaration (cp_parser* parser
*** 6541,6550 ****
--- 6808,6820 ----
    /* We must have either a block declaration or a function
       definition.  */
    else
      /* Try to parse a block-declaration, or a function-definition.  */
      cp_parser_block_declaration (parser, /*statement_p=*/false);
+ 
+   /* Free any declarators allocated.  */
+   obstack_free (&declarator_obstack, p);
  }
  
  /* Parse a block-declaration.
  
     block-declaration:
*************** cp_parser_conversion_function_id (cp_par
*** 7226,7236 ****
  static tree
  cp_parser_conversion_type_id (cp_parser* parser)
  {
    tree attributes;
    tree type_specifiers;
!   tree declarator;
  
    /* Parse the attributes.  */
    attributes = cp_parser_attributes_opt (parser);
    /* Parse the type-specifiers.  */
    type_specifiers = cp_parser_type_specifier_seq (parser);
--- 7496,7506 ----
  static tree
  cp_parser_conversion_type_id (cp_parser* parser)
  {
    tree attributes;
    tree type_specifiers;
!   cp_declarator *declarator;
  
    /* Parse the attributes.  */
    attributes = cp_parser_attributes_opt (parser);
    /* Parse the type-specifiers.  */
    type_specifiers = cp_parser_type_specifier_seq (parser);
*************** cp_parser_conversion_type_id (cp_parser*
*** 7247,7260 ****
  /* Parse an (optional) conversion-declarator.
  
     conversion-declarator:
       ptr-operator conversion-declarator [opt]
  
!    Returns a representation of the declarator.  See
!    cp_parser_declarator for details.  */
  
! static tree
  cp_parser_conversion_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree class_type;
    tree cv_qualifier_seq;
--- 7517,7529 ----
  /* Parse an (optional) conversion-declarator.
  
     conversion-declarator:
       ptr-operator conversion-declarator [opt]
  
!    */
  
! static cp_declarator *
  cp_parser_conversion_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree class_type;
    tree cv_qualifier_seq;
*************** cp_parser_conversion_declarator_opt (cp_
*** 7265,7295 ****
    code = cp_parser_ptr_operator (parser, &class_type,
  				 &cv_qualifier_seq);
    /* If it worked, look for more conversion-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
!      tree declarator;
! 
!      /* Parse another optional declarator.  */
!      declarator = cp_parser_conversion_declarator_opt (parser);
! 
!      /* Create the representation of the declarator.  */
!      if (code == INDIRECT_REF)
!        declarator = make_pointer_declarator (cv_qualifier_seq,
  					     declarator);
!      else
!        declarator =  make_reference_declarator (cv_qualifier_seq,
  						declarator);
! 
!      /* Handle the pointer-to-member case.  */
!      if (class_type)
!        declarator = build_nt (SCOPE_REF, class_type, declarator);
! 
!      return declarator;
     }
  
!   return NULL_TREE;
  }
  
  /* Parse an (optional) ctor-initializer.
  
     ctor-initializer:
--- 7534,7564 ----
    code = cp_parser_ptr_operator (parser, &class_type,
  				 &cv_qualifier_seq);
    /* If it worked, look for more conversion-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
!       cp_declarator *declarator;
!       
!       /* Parse another optional declarator.  */
!       declarator = cp_parser_conversion_declarator_opt (parser);
!       
!       /* Create the representation of the declarator.  */
!       if (class_type)
! 	declarator = make_ptrmem_declarator (cv_qualifier_seq,
! 					     class_type,
  					     declarator);
!       else if (code == INDIRECT_REF)
! 	declarator = make_pointer_declarator (cv_qualifier_seq,
! 					      declarator);
!       else
! 	declarator = make_reference_declarator (cv_qualifier_seq,
  						declarator);
!       
!       return declarator;
     }
  
!   return NULL;
  }
  
  /* Parse an (optional) ctor-initializer.
  
     ctor-initializer:
*************** cp_parser_template_parameter_list (cp_pa
*** 7809,7825 ****
  
    while (true)
      {
        tree parameter;
        cp_token *token;
  
        /* Parse the template-parameter.  */
!       parameter = cp_parser_template_parameter (parser);
        /* Add it to the list.  */
        parameter_list = process_template_parm (parameter_list,
! 					      parameter);
! 
        /* Peek at the next token.  */
        token = cp_lexer_peek_token (parser->lexer);
        /* If it's not a `,', we're done.  */
        if (token->type != CPP_COMMA)
  	break;
--- 8078,8095 ----
  
    while (true)
      {
        tree parameter;
        cp_token *token;
+       bool is_non_type;
  
        /* Parse the template-parameter.  */
!       parameter = cp_parser_template_parameter (parser, &is_non_type);
        /* Add it to the list.  */
        parameter_list = process_template_parm (parameter_list,
! 					      parameter,
! 					      is_non_type);
        /* Peek at the next token.  */
        token = cp_lexer_peek_token (parser->lexer);
        /* If it's not a `,', we're done.  */
        if (token->type != CPP_COMMA)
  	break;
*************** cp_parser_template_parameter_list (cp_pa
*** 7835,7851 ****
     template-parameter:
       type-parameter
       parameter-declaration
  
     Returns a TREE_LIST.  The TREE_VALUE represents the parameter.  The
!    TREE_PURPOSE is the default value, if any.  */
  
  static tree
! cp_parser_template_parameter (cp_parser* parser)
  {
    cp_token *token;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If it is `class' or `template', we have a type-parameter.  */
    if (token->keyword == RID_TEMPLATE)
      return cp_parser_type_parameter (parser);
--- 8105,8125 ----
     template-parameter:
       type-parameter
       parameter-declaration
  
     Returns a TREE_LIST.  The TREE_VALUE represents the parameter.  The
!    TREE_PURPOSE is the default value, if any.  *IS_NON_TYPE is set to
!    true iff this parameter is a non-type parameter.  */
  
  static tree
! cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
  {
    cp_token *token;
+   const cp_parameter_declarator *parameter_declarator;
  
+   /* Assume it is a type parameter or a template parameter.  */
+   *is_non_type = false;
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If it is `class' or `template', we have a type-parameter.  */
    if (token->keyword == RID_TEMPLATE)
      return cp_parser_type_parameter (parser);
*************** cp_parser_template_parameter (cp_parser*
*** 7883,7895 ****
  
       When parsing a default template-argument for a non-type
       template-parameter, the first non-nested `>' is taken as the end
       of the template parameter-list rather than a greater-than
       operator.  */
!   return
!     cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
! 				     /*parenthesized_p=*/NULL);
  }
  
  /* Parse a type-parameter.
  
     type-parameter:
--- 8157,8176 ----
  
       When parsing a default template-argument for a non-type
       template-parameter, the first non-nested `>' is taken as the end
       of the template parameter-list rather than a greater-than
       operator.  */
!   *is_non_type = true;
!   parameter_declarator
!      = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
! 					/*parenthesized_p=*/NULL);
!   return (build_tree_list 
! 	  (parameter_declarator->default_argument,
! 	   grokdeclarator (parameter_declarator->declarator,
! 			   parameter_declarator->decl_specifiers,
! 			   PARM, /*initialized=*/0, 
! 			   /*attrlist=*/NULL)));
  }
  
  /* Parse a type-parameter.
  
     type-parameter:
*************** cp_parser_explicit_instantiation (cp_par
*** 8766,8786 ****
        if (type)
  	do_type_instantiation (type, extension_specifier, /*complain=*/1);
      }
    else
      {
!       tree declarator;
        tree decl;
  
        /* Parse the declarator.  */
        declarator
  	= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  				/*ctor_dtor_or_conv_p=*/NULL,
  				/*parenthesized_p=*/NULL);
        cp_parser_check_for_definition_in_return_type (declarator,
  						     declares_class_or_enum);
!       if (declarator != error_mark_node)
  	{
  	  decl = grokdeclarator (declarator, decl_specifiers,
  				 NORMAL, 0, NULL);
  	  /* Turn access control back on for names used during
  	     template instantiation.  */
--- 9047,9067 ----
        if (type)
  	do_type_instantiation (type, extension_specifier, /*complain=*/1);
      }
    else
      {
!       cp_declarator *declarator;
        tree decl;
  
        /* Parse the declarator.  */
        declarator
  	= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  				/*ctor_dtor_or_conv_p=*/NULL,
  				/*parenthesized_p=*/NULL);
        cp_parser_check_for_definition_in_return_type (declarator,
  						     declares_class_or_enum);
!       if (declarator != cp_error_declarator)
  	{
  	  decl = grokdeclarator (declarator, decl_specifiers,
  				 NORMAL, 0, NULL);
  	  /* Turn access control back on for names used during
  	     template instantiation.  */
*************** cp_parser_init_declarator (cp_parser* pa
*** 10095,10105 ****
  			   bool member_p,
  			   int declares_class_or_enum,
  			   bool* function_definition_p)
  {
    cp_token *token;
!   tree declarator;
    tree attributes;
    tree asm_specification;
    tree initializer;
    tree decl = NULL_TREE;
    tree scope;
--- 10376,10386 ----
  			   bool member_p,
  			   int declares_class_or_enum,
  			   bool* function_definition_p)
  {
    cp_token *token;
!   cp_declarator *declarator;
    tree attributes;
    tree asm_specification;
    tree initializer;
    tree decl = NULL_TREE;
    tree scope;
*************** cp_parser_init_declarator (cp_parser* pa
*** 10128,10138 ****
    /* Gather up the deferred checks.  */
    stop_deferring_access_checks ();
  
    /* If the DECLARATOR was erroneous, there's no need to go
       further.  */
!   if (declarator == error_mark_node)
      return error_mark_node;
  
    cp_parser_check_for_definition_in_return_type (declarator,
  						 declares_class_or_enum);
  
--- 10409,10419 ----
    /* Gather up the deferred checks.  */
    stop_deferring_access_checks ();
  
    /* If the DECLARATOR was erroneous, there's no need to go
       further.  */
!   if (declarator == cp_error_declarator)
      return error_mark_node;
  
    cp_parser_check_for_definition_in_return_type (declarator,
  						 declares_class_or_enum);
  
*************** cp_parser_init_declarator (cp_parser* pa
*** 10370,10399 ****
  
     abstract-declarator:
       attributes [opt] ptr-operator abstract-declarator [opt]
       attributes [opt] direct-abstract-declarator
  
-    Returns a representation of the declarator.  If the declarator has
-    the form `* declarator', then an INDIRECT_REF is returned, whose
-    only operand is the sub-declarator.  Analogously, `& declarator' is
-    represented as an ADDR_EXPR.  For `X::* declarator', a SCOPE_REF is
-    used.  The first operand is the TYPE for `X'.  The second operand
-    is an INDIRECT_REF whose operand is the sub-declarator.
- 
-    Otherwise, the representation is as for a direct-declarator.
- 
-    (It would be better to define a structure type to represent
-    declarators, rather than abusing `tree' nodes to represent
-    declarators.  That would be much clearer and save some memory.
-    There is no reason for declarators to be garbage-collected, for
-    example; they are created during parser and no longer needed after
-    `grokdeclarator' has been called.)
- 
-    For a ptr-operator that has the optional cv-qualifier-seq,
-    cv-qualifiers will be stored in the TREE_TYPE of the INDIRECT_REF
-    node.
- 
     If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
     detect constructor, destructor or conversion operators. It is set
     to -1 if the declarator is a name, and +1 if it is a
     function. Otherwise it is set to zero. Usually you just want to
     test for >0, but internally the negative value is used.
--- 10651,10660 ----
*************** cp_parser_init_declarator (cp_parser* pa
*** 10407,10424 ****
     expression, not a declaration.)
  
     If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
     the declarator is a direct-declarator of the form "(...)".  */
  
! static tree
  cp_parser_declarator (cp_parser* parser,
                        cp_parser_declarator_kind dcl_kind,
                        int* ctor_dtor_or_conv_p,
  		      bool* parenthesized_p)
  {
    cp_token *token;
!   tree declarator;
    enum tree_code code;
    tree cv_qualifier_seq;
    tree class_type;
    tree attributes = NULL_TREE;
  
--- 10668,10685 ----
     expression, not a declaration.)
  
     If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
     the declarator is a direct-declarator of the form "(...)".  */
  
! static cp_declarator *
  cp_parser_declarator (cp_parser* parser,
                        cp_parser_declarator_kind dcl_kind,
                        int* ctor_dtor_or_conv_p,
  		      bool* parenthesized_p)
  {
    cp_token *token;
!   cp_declarator *declarator;
    enum tree_code code;
    tree cv_qualifier_seq;
    tree class_type;
    tree attributes = NULL_TREE;
  
*************** cp_parser_declarator (cp_parser* parser,
*** 10458,10479 ****
  
        /* If we are parsing an abstract-declarator, we must handle the
  	 case where the dependent declarator is absent.  */
        if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
  	  && !cp_parser_parse_definitely (parser))
! 	declarator = NULL_TREE;
  
        /* Build the representation of the ptr-operator.  */
!       if (code == INDIRECT_REF)
  	declarator = make_pointer_declarator (cv_qualifier_seq,
  					      declarator);
        else
  	declarator = make_reference_declarator (cv_qualifier_seq,
  						declarator);
-       /* Handle the pointer-to-member case.  */
-       if (class_type)
- 	declarator = build_nt (SCOPE_REF, class_type, declarator);
      }
    /* Everything else is a direct-declarator.  */
    else
      {
        if (parenthesized_p)
--- 10719,10741 ----
  
        /* If we are parsing an abstract-declarator, we must handle the
  	 case where the dependent declarator is absent.  */
        if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
  	  && !cp_parser_parse_definitely (parser))
! 	declarator = NULL;
  
        /* Build the representation of the ptr-operator.  */
!       if (class_type)
! 	declarator = make_ptrmem_declarator (cv_qualifier_seq,
! 					     class_type,
! 					     declarator);
!       else if (code == INDIRECT_REF)
  	declarator = make_pointer_declarator (cv_qualifier_seq,
  					      declarator);
        else
  	declarator = make_reference_declarator (cv_qualifier_seq,
  						declarator);
      }
    /* Everything else is a direct-declarator.  */
    else
      {
        if (parenthesized_p)
*************** cp_parser_declarator (cp_parser* parser,
*** 10481,10492 ****
  						   CPP_OPEN_PAREN);
        declarator = cp_parser_direct_declarator (parser, dcl_kind,
  						ctor_dtor_or_conv_p);
      }
  
!   if (attributes && declarator != error_mark_node)
!     declarator = tree_cons (attributes, declarator, NULL_TREE);
  
    return declarator;
  }
  
  /* Parse a direct-declarator or direct-abstract-declarator.
--- 10743,10754 ----
  						   CPP_OPEN_PAREN);
        declarator = cp_parser_direct_declarator (parser, dcl_kind,
  						ctor_dtor_or_conv_p);
      }
  
!   if (attributes && declarator != cp_error_declarator)
!     declarator->attributes = attributes;
  
    return declarator;
  }
  
  /* Parse a direct-declarator or direct-abstract-declarator.
*************** cp_parser_declarator (cp_parser* parser,
*** 10512,10539 ****
     direct-abstract-declarator.  It is CP_PARSER_DECLARATOR_NAMED, if
     we are parsing a direct-declarator.  It is
     CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
     of ambiguity we prefer an abstract declarator, as per
     [dcl.ambig.res].  CTOR_DTOR_OR_CONV_P is as for
!    cp_parser_declarator.
! 
!    For the declarator-id production, the representation is as for an
!    id-expression, except that a qualified name is represented as a
!    SCOPE_REF.  A function-declarator is represented as a CALL_EXPR;
!    see the documentation of the FUNCTION_DECLARATOR_* macros for
!    information about how to find the various declarator components.
!    An array-declarator is represented as an ARRAY_REF.  The
!    direct-declarator is the first operand; the constant-expression
!    indicating the size of the array is the second operand.  */
  
! static tree
  cp_parser_direct_declarator (cp_parser* parser,
                               cp_parser_declarator_kind dcl_kind,
                               int* ctor_dtor_or_conv_p)
  {
    cp_token *token;
!   tree declarator = NULL_TREE;
    tree scope = NULL_TREE;
    bool saved_default_arg_ok_p = parser->default_arg_ok_p;
    bool saved_in_declarator_p = parser->in_declarator_p;
    bool first = true;
    bool pop_p = false;
--- 10774,10792 ----
     direct-abstract-declarator.  It is CP_PARSER_DECLARATOR_NAMED, if
     we are parsing a direct-declarator.  It is
     CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
     of ambiguity we prefer an abstract declarator, as per
     [dcl.ambig.res].  CTOR_DTOR_OR_CONV_P is as for
!    cp_parser_declarator.  */
  
! static cp_declarator *
  cp_parser_direct_declarator (cp_parser* parser,
                               cp_parser_declarator_kind dcl_kind,
                               int* ctor_dtor_or_conv_p)
  {
    cp_token *token;
!   cp_declarator *declarator = NULL;
    tree scope = NULL_TREE;
    bool saved_default_arg_ok_p = parser->default_arg_ok_p;
    bool saved_in_declarator_p = parser->in_declarator_p;
    bool first = true;
    bool pop_p = false;
*************** cp_parser_direct_declarator (cp_parser* 
*** 10582,10592 ****
  	     Thus again, we try a parameter-declaration-clause, and if
  	     that fails, we back out and return.  */
  
  	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
  	    {
! 	      tree params;
  	      unsigned saved_num_template_parameter_lists;
  
  	      cp_parser_parse_tentatively (parser);
  
  	      /* Consume the `('.  */
--- 10835,10845 ----
  	     Thus again, we try a parameter-declaration-clause, and if
  	     that fails, we back out and return.  */
  
  	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
  	    {
! 	      cp_parameter_declarator *params;
  	      unsigned saved_num_template_parameter_lists;
  
  	      cp_parser_parse_tentatively (parser);
  
  	      /* Consume the `('.  */
*************** cp_parser_direct_declarator (cp_parser* 
*** 10664,10675 ****
  					/*parenthesized_p=*/NULL);
  	      parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
  	      first = false;
  	      /* Expect a `)'.  */
  	      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
! 		declarator = error_mark_node;
! 	      if (declarator == error_mark_node)
  		break;
  
  	      goto handle_declarator;
  	    }
  	  /* Otherwise, we must be done.  */
--- 10917,10928 ----
  					/*parenthesized_p=*/NULL);
  	      parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
  	      first = false;
  	      /* Expect a `)'.  */
  	      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
! 		declarator = cp_error_declarator;
! 	      if (declarator == cp_error_declarator)
  		break;
  
  	      goto handle_declarator;
  	    }
  	  /* Otherwise, we must be done.  */
*************** cp_parser_direct_declarator (cp_parser* 
*** 10708,10747 ****
  	  else
  	    bounds = NULL_TREE;
  	  /* Look for the closing `]'.  */
  	  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
  	    {
! 	      declarator = error_mark_node;
  	      break;
  	    }
  
! 	  declarator = build_nt (ARRAY_REF, declarator, bounds);
  	}
        else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
  	{
  	  /* Parse a declarator-id */
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    cp_parser_parse_tentatively (parser);
! 	  declarator = cp_parser_declarator_id (parser);
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    {
  	      if (!cp_parser_parse_definitely (parser))
! 		declarator = error_mark_node;
! 	      else if (TREE_CODE (declarator) != IDENTIFIER_NODE)
  		{
  		  cp_parser_error (parser, "expected unqualified-id");
! 		  declarator = error_mark_node;
  		}
  	    }
  
! 	  if (declarator == error_mark_node)
! 	    break;
  
! 	  if (TREE_CODE (declarator) == SCOPE_REF
! 	      && !current_scope ())
  	    {
! 	      tree scope = TREE_OPERAND (declarator, 0);
  
  	      /* In the declaration of a member of a template class
  	     	 outside of the class itself, the SCOPE will sometimes
  	     	 be a TYPENAME_TYPE.  For example, given:
  
--- 10961,11004 ----
  	  else
  	    bounds = NULL_TREE;
  	  /* Look for the closing `]'.  */
  	  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
  	    {
! 	      declarator = cp_error_declarator;
  	      break;
  	    }
  
! 	  declarator = make_array_declarator (declarator, bounds);
  	}
        else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
  	{
+ 	  tree id;
+ 
  	  /* Parse a declarator-id */
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    cp_parser_parse_tentatively (parser);
! 	  id = cp_parser_declarator_id (parser);
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    {
  	      if (!cp_parser_parse_definitely (parser))
! 		id = error_mark_node;
! 	      else if (TREE_CODE (id) != IDENTIFIER_NODE)
  		{
  		  cp_parser_error (parser, "expected unqualified-id");
! 		  id = error_mark_node;
  		}
  	    }
  
! 	  if (id == error_mark_node)
! 	    {
! 	      declarator = cp_error_declarator;
! 	      break;
! 	    }
  
! 	  if (TREE_CODE (id) == SCOPE_REF && !current_scope ())
  	    {
! 	      tree scope = TREE_OPERAND (id, 0);
  
  	      /* In the declaration of a member of a template class
  	     	 outside of the class itself, the SCOPE will sometimes
  	     	 be a TYPENAME_TYPE.  For example, given:
  
*************** cp_parser_direct_declarator (cp_parser* 
*** 10768,10837 ****
  		  if (type == error_mark_node)
  		    error ("`%T::%D' is not a type",
  			   TYPE_CONTEXT (scope),
  			   TYPE_IDENTIFIER (scope));
  		  /* Build a new DECLARATOR.  */
! 		  declarator = build_nt (SCOPE_REF,
! 					 type,
! 					 TREE_OPERAND (declarator, 1));
  		}
  	    }
  
! 	  /* Check to see whether the declarator-id names a constructor,
! 	     destructor, or conversion.  */
! 	  if (declarator && ctor_dtor_or_conv_p
! 	      && ((TREE_CODE (declarator) == SCOPE_REF
! 		   && CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
! 		  || (TREE_CODE (declarator) != SCOPE_REF
! 		      && at_class_scope_p ())))
  	    {
- 	      tree unqualified_name;
  	      tree class_type;
  
! 	      /* Get the unqualified part of the name.  */
! 	      if (TREE_CODE (declarator) == SCOPE_REF)
  		{
! 		  class_type = TREE_OPERAND (declarator, 0);
! 		  unqualified_name = TREE_OPERAND (declarator, 1);
  		}
  	      else
  		{
  		  class_type = current_class_type;
! 		  unqualified_name = declarator;
  		}
  
! 	      /* See if it names ctor, dtor or conv.  */
! 	      if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
! 		  || IDENTIFIER_TYPENAME_P (unqualified_name)
! 		  || constructor_name_p (unqualified_name, class_type)
! 		  || (TREE_CODE (unqualified_name) == TYPE_DECL
! 		      && same_type_p (TREE_TYPE (unqualified_name),
! 				      class_type)))
! 		*ctor_dtor_or_conv_p = -1;
! 		if (TREE_CODE (declarator) == SCOPE_REF
! 		    && TREE_CODE (unqualified_name) == TYPE_DECL 
! 		    && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
! 		  {
! 		    error ("invalid use of constructor as a template");
! 		    inform ("use `%T::%D' instead of `%T::%T' to name the "
! 			    "constructor in a qualified name", class_type, 
! 			    DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
! 			    class_type, class_type);
! 		  }
  	    }
  
  	handle_declarator:;
  	  scope = get_scope_of_declarator (declarator);
  	  if (scope)
  	    /* Any names that appear after the declarator-id for a
  	       member are looked up in the containing scope.  */
  	    pop_p = push_scope (scope);
  	  parser->in_declarator_p = true;
  	  if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
! 	      || (declarator
! 		  && (TREE_CODE (declarator) == SCOPE_REF
! 		      || TREE_CODE (declarator) == IDENTIFIER_NODE)))
  	    /* Default args are only allowed on function
  	       declarations.  */
  	    parser->default_arg_ok_p = saved_default_arg_ok_p;
  	  else
  	    parser->default_arg_ok_p = false;
--- 11025,11093 ----
  		  if (type == error_mark_node)
  		    error ("`%T::%D' is not a type",
  			   TYPE_CONTEXT (scope),
  			   TYPE_IDENTIFIER (scope));
  		  /* Build a new DECLARATOR.  */
! 		  id = build_nt (SCOPE_REF, type, TREE_OPERAND (id, 1));
  		}
  	    }
  
! 	  declarator = make_id_declarator (id);
! 	  if (id)
  	    {
  	      tree class_type;
+ 	      tree unqualified_name;
  
! 	      if (TREE_CODE (id) == SCOPE_REF
! 		  && CLASS_TYPE_P (TREE_OPERAND (id, 0)))
  		{
! 		  class_type = TREE_OPERAND (id, 0);
! 		  unqualified_name = TREE_OPERAND (id, 1);
  		}
  	      else
  		{
  		  class_type = current_class_type;
! 		  unqualified_name = id;
  		}
  
! 	      if (class_type)
! 		{
! 		  if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
! 		    declarator->u.id.sfk = sfk_destructor;
! 		  else if (IDENTIFIER_TYPENAME_P (unqualified_name))
! 		    declarator->u.id.sfk = sfk_conversion;
! 		  else if (constructor_name_p (unqualified_name,
! 					       class_type)
! 			   || (TREE_CODE (unqualified_name) == TYPE_DECL
! 			       && same_type_p (TREE_TYPE (unqualified_name),
! 					       class_type)))
! 		    declarator->u.id.sfk = sfk_constructor;
! 
! 		  if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
! 		    *ctor_dtor_or_conv_p = -1;
! 		  if (TREE_CODE (id) == SCOPE_REF
! 		      && TREE_CODE (unqualified_name) == TYPE_DECL 
! 		      && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
! 		    {
! 		      error ("invalid use of constructor as a template");
! 		      inform ("use `%T::%D' instead of `%T::%T' to name the "
! 			      "constructor in a qualified name", class_type, 
! 			      DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
! 			      class_type, class_type);
! 		    }
! 		}
  	    }
  
  	handle_declarator:;
  	  scope = get_scope_of_declarator (declarator);
  	  if (scope)
  	    /* Any names that appear after the declarator-id for a
  	       member are looked up in the containing scope.  */
  	    pop_p = push_scope (scope);
  	  parser->in_declarator_p = true;
  	  if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
! 	      || (declarator && declarator->kind == cdk_id))
  	    /* Default args are only allowed on function
  	       declarations.  */
  	    parser->default_arg_ok_p = saved_default_arg_ok_p;
  	  else
  	    parser->default_arg_ok_p = false;
*************** cp_parser_declarator_id (cp_parser* pars
*** 11074,11084 ****
  
  static tree
  cp_parser_type_id (cp_parser* parser)
  {
    tree type_specifier_seq;
!   tree abstract_declarator;
  
    /* Parse the type-specifier-seq.  */
    type_specifier_seq
      = cp_parser_type_specifier_seq (parser);
    if (type_specifier_seq == error_mark_node)
--- 11330,11340 ----
  
  static tree
  cp_parser_type_id (cp_parser* parser)
  {
    tree type_specifier_seq;
!   cp_declarator *abstract_declarator;
  
    /* Parse the type-specifier-seq.  */
    type_specifier_seq
      = cp_parser_type_specifier_seq (parser);
    if (type_specifier_seq == error_mark_node)
*************** cp_parser_type_id (cp_parser* parser)
*** 11090,11103 ****
    abstract_declarator
      = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
  			    /*parenthesized_p=*/NULL);
    /* Check to see if there really was a declarator.  */
    if (!cp_parser_parse_definitely (parser))
!     abstract_declarator = NULL_TREE;
  
!   return groktypename (build_tree_list (type_specifier_seq,
! 					abstract_declarator));
  }
  
  /* Parse a type-specifier-seq.
  
     type-specifier-seq:
--- 11346,11358 ----
    abstract_declarator
      = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
  			    /*parenthesized_p=*/NULL);
    /* Check to see if there really was a declarator.  */
    if (!cp_parser_parse_definitely (parser))
!     abstract_declarator = NULL;
  
!   return groktypename (type_specifier_seq, abstract_declarator);
  }
  
  /* Parse a type-specifier-seq.
  
     type-specifier-seq:
*************** cp_parser_type_specifier_seq (cp_parser*
*** 11164,11225 ****
  
     parameter-declaration-clause:
       parameter-declaration-list [opt] ... [opt]
       parameter-declaration-list , ...
  
!    Returns a representation for the parameter declarations.  Each node
!    is a TREE_LIST.  (See cp_parser_parameter_declaration for the exact
!    representation.)  If the parameter-declaration-clause ends with an
!    ellipsis, PARMLIST_ELLIPSIS_P will hold of the first node in the
!    list.  A return value of NULL_TREE indicates a
!    parameter-declaration-clause consisting only of an ellipsis.  */
  
! static tree
  cp_parser_parameter_declaration_clause (cp_parser* parser)
  {
!   tree parameters;
    cp_token *token;
    bool ellipsis_p;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* Check for trivial parameter-declaration-clauses.  */
    if (token->type == CPP_ELLIPSIS)
      {
        /* Consume the `...' token.  */
        cp_lexer_consume_token (parser->lexer);
!       return NULL_TREE;
      }
    else if (token->type == CPP_CLOSE_PAREN)
      /* There are no parameters.  */
      {
  #ifndef NO_IMPLICIT_EXTERN_C
        if (in_system_header && current_class_type == NULL
  	  && current_lang_name == lang_name_c)
! 	return NULL_TREE;
        else
  #endif
! 	return void_list_node;
      }
    /* Check for `(void)', too, which is a special case.  */
    else if (token->keyword == RID_VOID
  	   && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
  	       == CPP_CLOSE_PAREN))
      {
        /* Consume the `void' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* There are no parameters.  */
!       return void_list_node;
      }
  
    /* Parse the parameter-declaration-list.  */
!   parameters = cp_parser_parameter_declaration_list (parser);
    /* If a parse error occurred while parsing the
       parameter-declaration-list, then the entire
       parameter-declaration-clause is erroneous.  */
!   if (parameters == error_mark_node)
!     return error_mark_node;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If it's a `,', the clause should terminate with an ellipsis.  */
    if (token->type == CPP_COMMA)
--- 11419,11478 ----
  
     parameter-declaration-clause:
       parameter-declaration-list [opt] ... [opt]
       parameter-declaration-list , ...
  
!    Returns a representation for the parameter declarations.  A return
!    value of NULL indicates a parameter-declaration-clause consisting
!    only of an ellipsis.  */
  
! static cp_parameter_declarator *
  cp_parser_parameter_declaration_clause (cp_parser* parser)
  {
!   cp_parameter_declarator *parameters;
    cp_token *token;
    bool ellipsis_p;
+   bool is_error;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* Check for trivial parameter-declaration-clauses.  */
    if (token->type == CPP_ELLIPSIS)
      {
        /* Consume the `...' token.  */
        cp_lexer_consume_token (parser->lexer);
!       return NULL;
      }
    else if (token->type == CPP_CLOSE_PAREN)
      /* There are no parameters.  */
      {
  #ifndef NO_IMPLICIT_EXTERN_C
        if (in_system_header && current_class_type == NULL
  	  && current_lang_name == lang_name_c)
! 	return NULL;
        else
  #endif
! 	return no_parameters;
      }
    /* Check for `(void)', too, which is a special case.  */
    else if (token->keyword == RID_VOID
  	   && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
  	       == CPP_CLOSE_PAREN))
      {
        /* Consume the `void' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* There are no parameters.  */
!       return no_parameters;
      }
  
    /* Parse the parameter-declaration-list.  */
!   parameters = cp_parser_parameter_declaration_list (parser, &is_error);
    /* If a parse error occurred while parsing the
       parameter-declaration-list, then the entire
       parameter-declaration-clause is erroneous.  */
!   if (is_error)
!     return NULL;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If it's a `,', the clause should terminate with an ellipsis.  */
    if (token->type == CPP_COMMA)
*************** cp_parser_parameter_declaration_clause (
*** 11241,11289 ****
      }
    else
      ellipsis_p = false;
  
    /* Finish the parameter list.  */
!   return finish_parmlist (parameters, ellipsis_p);
  }
  
  /* Parse a parameter-declaration-list.
  
     parameter-declaration-list:
       parameter-declaration
       parameter-declaration-list , parameter-declaration
  
     Returns a representation of the parameter-declaration-list, as for
     cp_parser_parameter_declaration_clause.  However, the
!    `void_list_node' is never appended to the list.  */
  
! static tree
! cp_parser_parameter_declaration_list (cp_parser* parser)
  {
!   tree parameters = NULL_TREE;
  
    /* Look for more parameters.  */
    while (true)
      {
!       tree parameter;
        bool parenthesized_p;
        /* Parse the parameter.  */
        parameter
  	= cp_parser_parameter_declaration (parser,
  					   /*template_parm_p=*/false,
  					   &parenthesized_p);
  
        /* If a parse error occurred parsing the parameter declaration,
  	 then the entire parameter-declaration-list is erroneous.  */
!       if (parameter == error_mark_node)
  	{
! 	  parameters = error_mark_node;
  	  break;
  	}
        /* Add the new parameter to the list.  */
!       TREE_CHAIN (parameter) = parameters;
!       parameters = parameter;
  
        /* Peek at the next token.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
  	  || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
  	/* The parameter-declaration-list is complete.  */
--- 11494,11551 ----
      }
    else
      ellipsis_p = false;
  
    /* Finish the parameter list.  */
!   if (parameters && ellipsis_p)
!     parameters->ellipsis_p = true;
!   
!   return parameters;
  }
  
  /* Parse a parameter-declaration-list.
  
     parameter-declaration-list:
       parameter-declaration
       parameter-declaration-list , parameter-declaration
  
     Returns a representation of the parameter-declaration-list, as for
     cp_parser_parameter_declaration_clause.  However, the
!    `void_list_node' is never appended to the list.  Upon return,
!    *IS_ERROR will be true iff an error occurred.  */
  
! static cp_parameter_declarator *
! cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
  {
!   cp_parameter_declarator *parameters = NULL;
!   cp_parameter_declarator **tail = &parameters;
! 
!   /* Assume all will go well.  */
!   *is_error = false;
  
    /* Look for more parameters.  */
    while (true)
      {
!       cp_parameter_declarator *parameter;
        bool parenthesized_p;
        /* Parse the parameter.  */
        parameter
  	= cp_parser_parameter_declaration (parser,
  					   /*template_parm_p=*/false,
  					   &parenthesized_p);
  
        /* If a parse error occurred parsing the parameter declaration,
  	 then the entire parameter-declaration-list is erroneous.  */
!       if (!parameter)
  	{
! 	  *is_error = true;
! 	  parameters = NULL;
  	  break;
  	}
        /* Add the new parameter to the list.  */
!       *tail = parameter;
!       tail = &parameter->next;
  
        /* Peek at the next token.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
  	  || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
  	/* The parameter-declaration-list is complete.  */
*************** cp_parser_parameter_declaration_list (cp
*** 11334,11345 ****
  						   /*consume_paren=*/false);
  	  break;
  	}
      }
  
!   /* We built up the list in reverse order; straighten it out now.  */
!   return nreverse (parameters);
  }
  
  /* Parse a parameter declaration.
  
     parameter-declaration:
--- 11596,11606 ----
  						   /*consume_paren=*/false);
  	  break;
  	}
      }
  
!   return parameters;
  }
  
  /* Parse a parameter declaration.
  
     parameter-declaration:
*************** cp_parser_parameter_declaration_list (cp
*** 11351,11381 ****
     If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
     declares a template parameter.  (In that case, a non-nested `>'
     token encountered during the parsing of the assignment-expression
     is not interpreted as a greater-than operator.)
  
!    Returns a TREE_LIST representing the parameter-declaration.  The
!    TREE_PURPOSE is the default argument expression, or NULL_TREE if
!    there is no default argument.  The TREE_VALUE is a representation
!    of the decl-specifier-seq and declarator.  In particular, the
!    TREE_VALUE will be a TREE_LIST whose TREE_PURPOSE represents the
!    decl-specifier-seq and whose TREE_VALUE represents the declarator.
!    If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
!    the declarator is of the form "(p)".  */
  
! static tree
  cp_parser_parameter_declaration (cp_parser *parser,
  				 bool template_parm_p,
  				 bool *parenthesized_p)
  {
    int declares_class_or_enum;
    bool greater_than_is_operator_p;
    tree decl_specifiers;
    tree attributes;
!   tree declarator;
    tree default_argument;
-   tree parameter;
    cp_token *token;
    const char *saved_message;
  
    /* In a template parameter, `>' is not an operator.
  
--- 11612,11636 ----
     If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
     declares a template parameter.  (In that case, a non-nested `>'
     token encountered during the parsing of the assignment-expression
     is not interpreted as a greater-than operator.)
  
!    Returns a representation of the parameter, or NULL if an error
!    occurs.  If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to
!    true iff the declarator is of the form "(p)".  */
  
! static cp_parameter_declarator *
  cp_parser_parameter_declaration (cp_parser *parser,
  				 bool template_parm_p,
  				 bool *parenthesized_p)
  {
    int declares_class_or_enum;
    bool greater_than_is_operator_p;
    tree decl_specifiers;
    tree attributes;
!   cp_declarator *declarator;
    tree default_argument;
    cp_token *token;
    const char *saved_message;
  
    /* In a template parameter, `>' is not an operator.
  
*************** cp_parser_parameter_declaration (cp_pars
*** 11401,11411 ****
    /* If an error occurred, there's no reason to attempt to parse the
       rest of the declaration.  */
    if (cp_parser_error_occurred (parser))
      {
        parser->type_definition_forbidden_message = saved_message;
!       return error_mark_node;
      }
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If the next token is a `)', `,', `=', `>', or `...', then there
--- 11656,11666 ----
    /* If an error occurred, there's no reason to attempt to parse the
       rest of the declaration.  */
    if (cp_parser_error_occurred (parser))
      {
        parser->type_definition_forbidden_message = saved_message;
!       return NULL;
      }
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If the next token is a `)', `,', `=', `>', or `...', then there
*************** cp_parser_parameter_declaration (cp_pars
*** 11414,11424 ****
        || token->type == CPP_COMMA
        || token->type == CPP_EQ
        || token->type == CPP_ELLIPSIS
        || token->type == CPP_GREATER)
      {
!       declarator = NULL_TREE;
        if (parenthesized_p)
  	*parenthesized_p = false;
      }
    /* Otherwise, there should be a declarator.  */
    else
--- 11669,11679 ----
        || token->type == CPP_COMMA
        || token->type == CPP_EQ
        || token->type == CPP_ELLIPSIS
        || token->type == CPP_GREATER)
      {
!       declarator = NULL;
        if (parenthesized_p)
  	*parenthesized_p = false;
      }
    /* Otherwise, there should be a declarator.  */
    else
*************** cp_parser_parameter_declaration (cp_pars
*** 11592,11606 ****
      default_argument = NULL_TREE;
  
    /* Create the representation of the parameter.  */
    if (attributes)
      decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers);
-   parameter = build_tree_list (default_argument,
- 			       build_tree_list (decl_specifiers,
- 						declarator));
  
!   return parameter;
  }
  
  /* Parse a function-body.
  
     function-body:
--- 11847,11860 ----
      default_argument = NULL_TREE;
  
    /* Create the representation of the parameter.  */
    if (attributes)
      decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers);
  
!   return make_parameter_declarator (decl_specifiers,
! 				    declarator,
! 				    default_argument);
  }
  
  /* Parse a function-body.
  
     function-body:
*************** cp_parser_member_declaration (cp_parser*
*** 12740,12758 ****
  	      first_attribute = attributes;
  	      /* Combine the attributes.  */
  	      attributes = chainon (prefix_attributes, attributes);
  
  	      /* Create the bitfield declaration.  */
! 	      decl = grokbitfield (identifier,
  				   decl_specifiers,
  				   width);
  	      /* Apply the attributes.  */
  	      cplus_decl_attributes (&decl, attributes, /*flags=*/0);
  	    }
  	  else
  	    {
! 	      tree declarator;
  	      tree initializer;
  	      tree asm_specification;
  	      int ctor_dtor_or_conv_p;
  
  	      /* Parse the declarator.  */
--- 12994,13014 ----
  	      first_attribute = attributes;
  	      /* Combine the attributes.  */
  	      attributes = chainon (prefix_attributes, attributes);
  
  	      /* Create the bitfield declaration.  */
! 	      decl = grokbitfield (identifier 
! 				   ? make_id_declarator (identifier)
! 				   : NULL,
  				   decl_specifiers,
  				   width);
  	      /* Apply the attributes.  */
  	      cplus_decl_attributes (&decl, attributes, /*flags=*/0);
  	    }
  	  else
  	    {
! 	      cp_declarator *declarator;
  	      tree initializer;
  	      tree asm_specification;
  	      int ctor_dtor_or_conv_p;
  
  	      /* Parse the declarator.  */
*************** cp_parser_member_declaration (cp_parser*
*** 12761,12771 ****
  					&ctor_dtor_or_conv_p,
  					/*parenthesized_p=*/NULL);
  
  	      /* If something went wrong parsing the declarator, make sure
  		 that we at least consume some tokens.  */
! 	      if (declarator == error_mark_node)
  		{
  		  /* Skip to the end of the statement.  */
  		  cp_parser_skip_to_end_of_statement (parser);
  		  /* If the next token is not a semicolon, that is
  		     probably because we just skipped over the body of
--- 13017,13027 ----
  					&ctor_dtor_or_conv_p,
  					/*parenthesized_p=*/NULL);
  
  	      /* If something went wrong parsing the declarator, make sure
  		 that we at least consume some tokens.  */
! 	      if (declarator == cp_error_declarator)
  		{
  		  /* Skip to the end of the statement.  */
  		  cp_parser_skip_to_end_of_statement (parser);
  		  /* If the next token is not a semicolon, that is
  		     probably because we just skipped over the body of
*************** cp_parser_member_declaration (cp_parser*
*** 12811,12821 ****
  
  		     Therefore, if the DECLARATOR is for a function, we look
  		     for a pure-specifier; otherwise, we look for a
  		     constant-initializer.  When we call `grokfield', it will
  		     perform more stringent semantics checks.  */
! 		  if (TREE_CODE (declarator) == CALL_EXPR)
  		    initializer = cp_parser_pure_specifier (parser);
  		  else
  		    /* Parse the initializer.  */
  		    initializer = cp_parser_constant_initializer (parser);
  		}
--- 13067,13077 ----
  
  		     Therefore, if the DECLARATOR is for a function, we look
  		     for a pure-specifier; otherwise, we look for a
  		     constant-initializer.  When we call `grokfield', it will
  		     perform more stringent semantics checks.  */
! 		  if (declarator->kind == cdk_function)
  		    initializer = cp_parser_pure_specifier (parser);
  		  else
  		    /* Parse the initializer.  */
  		    initializer = cp_parser_constant_initializer (parser);
  		}
*************** cp_parser_handler (cp_parser* parser)
*** 13348,13359 ****
     ellipsis variant is used.  */
  
  static tree
  cp_parser_exception_declaration (cp_parser* parser)
  {
    tree type_specifiers;
!   tree declarator;
    const char *saved_message;
  
    /* If it's an ellipsis, it's easy to handle.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
      {
--- 13604,13616 ----
     ellipsis variant is used.  */
  
  static tree
  cp_parser_exception_declaration (cp_parser* parser)
  {
+   tree decl;
    tree type_specifiers;
!   cp_declarator *declarator;
    const char *saved_message;
  
    /* If it's an ellipsis, it's easy to handle.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
      {
*************** cp_parser_exception_declaration (cp_pars
*** 13369,13388 ****
  
    /* Parse the type-specifier-seq.  */
    type_specifiers = cp_parser_type_specifier_seq (parser);
    /* If it's a `)', then there is no declarator.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
!     declarator = NULL_TREE;
    else
      declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
  				       /*ctor_dtor_or_conv_p=*/NULL,
  				       /*parenthesized_p=*/NULL);
  
    /* Restore the saved message.  */
    parser->type_definition_forbidden_message = saved_message;
  
!   return start_handler_parms (type_specifiers, declarator);
  }
  
  /* Parse a throw-expression.
  
     throw-expression:
--- 13626,13654 ----
  
    /* Parse the type-specifier-seq.  */
    type_specifiers = cp_parser_type_specifier_seq (parser);
    /* If it's a `)', then there is no declarator.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
!     declarator = NULL;
    else
      declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
  				       /*ctor_dtor_or_conv_p=*/NULL,
  				       /*parenthesized_p=*/NULL);
  
    /* Restore the saved message.  */
    parser->type_definition_forbidden_message = saved_message;
  
!   if (type_specifiers)
!     {
!       decl = grokdeclarator (declarator, type_specifiers, CATCHPARM, 1, NULL);
!       if (decl == NULL_TREE)
! 	error ("invalid catch parameter");
!     }
!   else
!     decl = NULL_TREE;
! 
!   return decl;
  }
  
  /* Parse a throw-expression.
  
     throw-expression:
*************** cp_parser_maybe_treat_template_as_class 
*** 14024,14100 ****
     declarator, issue an error message.  Returns TRUE if all went well,
     and FALSE otherwise.  */
  
  static bool
  cp_parser_check_declarator_template_parameters (cp_parser* parser,
!                                                 tree declarator)
  {
    unsigned num_templates;
  
    /* We haven't seen any classes that involve template parameters yet.  */
    num_templates = 0;
  
!   switch (TREE_CODE (declarator))
      {
!     case CALL_EXPR:
!     case ARRAY_REF:
!     case INDIRECT_REF:
!     case ADDR_EXPR:
!       {
! 	tree main_declarator = TREE_OPERAND (declarator, 0);
! 	return
! 	  cp_parser_check_declarator_template_parameters (parser,
! 							  main_declarator);
!       }
! 
!     case SCOPE_REF:
!       {
! 	tree scope;
! 	tree member;
! 
! 	scope = TREE_OPERAND (declarator, 0);
! 	member = TREE_OPERAND (declarator, 1);
! 
! 	/* If this is a pointer-to-member, then we are not interested
! 	   in the SCOPE, because it does not qualify the thing that is
! 	   being declared.  */
! 	if (TREE_CODE (member) == INDIRECT_REF)
! 	  return (cp_parser_check_declarator_template_parameters
! 		  (parser, member));
  
! 	while (scope && CLASS_TYPE_P (scope))
! 	  {
! 	    /* You're supposed to have one `template <...>'
! 	       for every template class, but you don't need one
! 	       for a full specialization.  For example:
! 
! 	       template <class T> struct S{};
! 	       template <> struct S<int> { void f(); };
! 	       void S<int>::f () {}
! 
! 	       is correct; there shouldn't be a `template <>' for
! 	       the definition of `S<int>::f'.  */
! 	    if (CLASSTYPE_TEMPLATE_INFO (scope)
! 		&& (CLASSTYPE_TEMPLATE_INSTANTIATION (scope)
! 		    || uses_template_parms (CLASSTYPE_TI_ARGS (scope)))
! 		&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
! 	      ++num_templates;
  
! 	    scope = TYPE_CONTEXT (scope);
! 	  }
!       }
  
!       /* Fall through.  */
  
-     default:
        /* If the DECLARATOR has the form `X<y>' then it uses one
  	 additional level of template parameters.  */
!       if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
  	++num_templates;
  
        return cp_parser_check_template_parameters (parser,
  						  num_templates);
      }
  }
  
  /* NUM_TEMPLATES were used in the current declaration.  If that is
     invalid, return FALSE and issue an error messages.  Otherwise,
--- 14290,14361 ----
     declarator, issue an error message.  Returns TRUE if all went well,
     and FALSE otherwise.  */
  
  static bool
  cp_parser_check_declarator_template_parameters (cp_parser* parser,
! 						cp_declarator *declarator)
  {
    unsigned num_templates;
  
    /* We haven't seen any classes that involve template parameters yet.  */
    num_templates = 0;
  
!   switch (declarator->kind)
      {
!     case cdk_id:
!       if (TREE_CODE (declarator->u.id.name) == SCOPE_REF)
! 	{
! 	  tree scope;
! 	  tree member;
  
! 	  scope = TREE_OPERAND (declarator->u.id.name, 0);
! 	  member = TREE_OPERAND (declarator->u.id.name, 1);
  
! 	  while (scope && CLASS_TYPE_P (scope))
! 	    {
! 	      /* You're supposed to have one `template <...>'
! 		 for every template class, but you don't need one
! 		 for a full specialization.  For example:
! 
! 		 template <class T> struct S{};
! 		 template <> struct S<int> { void f(); };
! 		 void S<int>::f () {}
! 
! 		 is correct; there shouldn't be a `template <>' for
! 		 the definition of `S<int>::f'.  */
! 	      if (CLASSTYPE_TEMPLATE_INFO (scope)
! 		  && (CLASSTYPE_TEMPLATE_INSTANTIATION (scope)
! 		      || uses_template_parms (CLASSTYPE_TI_ARGS (scope)))
! 		  && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
! 		++num_templates;
  
! 	      scope = TYPE_CONTEXT (scope);
! 	    }
! 	}
  
        /* If the DECLARATOR has the form `X<y>' then it uses one
  	 additional level of template parameters.  */
!       if (TREE_CODE (declarator->u.id.name) == TEMPLATE_ID_EXPR)
  	++num_templates;
  
        return cp_parser_check_template_parameters (parser,
  						  num_templates);
+ 
+     case cdk_function:
+     case cdk_array:
+     case cdk_pointer:
+     case cdk_reference:
+     case cdk_ptrmem:
+       return (cp_parser_check_declarator_template_parameters 
+ 	      (parser, declarator->declarator));
+ 
+     case cdk_error:
+       return true;
+ 
+     default:
+       abort ();
+       return false;
      }
  }
  
  /* NUM_TEMPLATES were used in the current declaration.  If that is
     invalid, return FALSE and issue an error messages.  Otherwise,
*************** cp_parser_constructor_declarator_p (cp_p
*** 14399,14428 ****
  static tree
  cp_parser_function_definition_from_specifiers_and_declarator
    (cp_parser* parser,
     tree decl_specifiers,
     tree attributes,
!    tree declarator)
  {
    tree fn;
    bool success_p;
  
    /* Begin the function-definition.  */
!   success_p = begin_function_definition (decl_specifiers,
! 					 attributes,
! 					 declarator);
  
    /* If there were names looked up in the decl-specifier-seq that we
       did not check, check them now.  We must wait until we are in the
       scope of the function to perform the checks, since the function
       might be a friend.  */
    perform_deferred_access_checks ();
  
    if (!success_p)
      {
!       /* If begin_function_definition didn't like the definition, skip
! 	 the entire function.  */
        error ("invalid function declaration");
        cp_parser_skip_to_end_of_block_or_statement (parser);
        fn = error_mark_node;
      }
    else
--- 14660,14690 ----
  static tree
  cp_parser_function_definition_from_specifiers_and_declarator
    (cp_parser* parser,
     tree decl_specifiers,
     tree attributes,
!    const cp_declarator *declarator)
  {
    tree fn;
    bool success_p;
  
    /* Begin the function-definition.  */
!   success_p = start_function (decl_specifiers, declarator, attributes);
! 
!   /* The things we're about to see are not directly qualified by any
!      template headers we've seen thus far.  */
!   reset_specialization ();
  
    /* If there were names looked up in the decl-specifier-seq that we
       did not check, check them now.  We must wait until we are in the
       scope of the function to perform the checks, since the function
       might be a friend.  */
    perform_deferred_access_checks ();
  
    if (!success_p)
      {
!       /* Skip the entire function.  */
        error ("invalid function declaration");
        cp_parser_skip_to_end_of_block_or_statement (parser);
        fn = error_mark_node;
      }
    else
*************** cp_parser_functional_cast (cp_parser* pa
*** 14703,14713 ****
     for the member function.  */
  
  static tree
  cp_parser_save_member_function_body (cp_parser* parser,
  				     tree decl_specifiers,
! 				     tree declarator,
  				     tree attributes)
  {
    cp_token_cache *cache;
    tree fn;
  
--- 14965,14975 ----
     for the member function.  */
  
  static tree
  cp_parser_save_member_function_body (cp_parser* parser,
  				     tree decl_specifiers,
! 				     cp_declarator *declarator,
  				     tree attributes)
  {
    cp_token_cache *cache;
    tree fn;
  
*************** cp_parser_late_parsing_for_member (cp_pa
*** 14877,14888 ****
  	 token in the saved inline body.  */
        cp_lexer_peek_token (parser->lexer);
  
        /* Let the front end know that we going to be defining this
  	 function.  */
!       start_function (NULL_TREE, member_function, NULL_TREE,
! 		      SF_PRE_PARSED | SF_INCLASS_INLINE);
  
        /* Now, parse the body of the function.  */
        cp_parser_function_definition_after_declarator (parser,
  						      /*inline_p=*/true);
  
--- 15139,15150 ----
  	 token in the saved inline body.  */
        cp_lexer_peek_token (parser->lexer);
  
        /* Let the front end know that we going to be defining this
  	 function.  */
!       start_preparsed_function (member_function, NULL_TREE,
! 				SF_PRE_PARSED | SF_INCLASS_INLINE);
  
        /* Now, parse the body of the function.  */
        cp_parser_function_definition_after_declarator (parser,
  						      /*inline_p=*/true);
  
*************** cp_parser_sizeof_operand (cp_parser* par
*** 15046,15056 ****
  	     a single type-specifier.  */
  	  type = build_tree_list (NULL_TREE,
  				  type);
  
  	  /* Call grokdeclarator to figure out what type this is.  */
! 	  expr = grokdeclarator (NULL_TREE,
  				 type,
  				 TYPENAME,
  				 /*initialized=*/0,
  				 /*attrlist=*/NULL);
  	}
--- 15308,15318 ----
  	     a single type-specifier.  */
  	  type = build_tree_list (NULL_TREE,
  				  type);
  
  	  /* Call grokdeclarator to figure out what type this is.  */
! 	  expr = grokdeclarator (NULL,
  				 type,
  				 TYPENAME,
  				 /*initialized=*/0,
  				 /*attrlist=*/NULL);
  	}
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.868
diff -c -5 -p -r1.868 pt.c
*** cp/pt.c	17 Jun 2004 01:24:04 -0000	1.868
--- cp/pt.c	22 Jun 2004 02:13:18 -0000
*************** reduce_template_parm_level (tree index, 
*** 2159,2183 ****
  
    return TEMPLATE_PARM_DESCENDANTS (index);
  }
  
  /* Process information from new template parameter NEXT and append it to the
!    LIST being built.  */
  
  tree
! process_template_parm (tree list, tree next)
  {
    tree parm;
    tree decl = 0;
    tree defval;
!   int is_type, idx;
  
    parm = next;
    my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
    defval = TREE_PURPOSE (parm);
-   parm = TREE_VALUE (parm);
-   is_type = TREE_PURPOSE (parm) == class_type_node;
  
    if (list)
      {
        tree p = TREE_VALUE (tree_last (list));
  
--- 2159,2182 ----
  
    return TEMPLATE_PARM_DESCENDANTS (index);
  }
  
  /* Process information from new template parameter NEXT and append it to the
!    LIST being built.  This new parameter is a non-type parameter iff
!    IS_NON_TYPE is true.  */
  
  tree
! process_template_parm (tree list, tree next, bool is_non_type)
  {
    tree parm;
    tree decl = 0;
    tree defval;
!   int idx;
  
    parm = next;
    my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
    defval = TREE_PURPOSE (parm);
  
    if (list)
      {
        tree p = TREE_VALUE (tree_last (list));
  
*************** process_template_parm (tree list, tree n
*** 2188,2203 ****
        ++idx;
      }
    else
      idx = 0;
  
!   if (!is_type)
      {
!       my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
!       /* is a const-param */
!       parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
! 			     PARM, 0, NULL);
        SET_DECL_TEMPLATE_PARM_P (parm);
  
        /* [temp.param]
  
  	 The top-level cv-qualifiers on the template-parameter are
--- 2187,2200 ----
        ++idx;
      }
    else
      idx = 0;
  
!   if (is_non_type)
      {
!       parm = TREE_VALUE (parm);
! 
        SET_DECL_TEMPLATE_PARM_P (parm);
  
        /* [temp.param]
  
  	 The top-level cv-qualifiers on the template-parameter are
*************** process_template_parm (tree list, tree n
*** 2220,2230 ****
  				     decl, TREE_TYPE (parm));
      }
    else
      {
        tree t;
!       parm = TREE_VALUE (parm);
        
        if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
  	{
  	  t = make_aggr_type (TEMPLATE_TEMPLATE_PARM);
  	  /* This is for distinguishing between real templates and template 
--- 2217,2227 ----
  				     decl, TREE_TYPE (parm));
      }
    else
      {
        tree t;
!       parm = TREE_VALUE (TREE_VALUE (parm));
        
        if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
  	{
  	  t = make_aggr_type (TEMPLATE_TEMPLATE_PARM);
  	  /* This is for distinguishing between real templates and template 
*************** convert_template_argument (tree parm, 
*** 3755,3765 ****
  		  val = error_mark_node;
  		}
  	    }
  	}
        else
! 	val = groktypename (arg);
      }
    else
      {
        tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
  
--- 3752,3762 ----
  		  val = error_mark_node;
  		}
  	    }
  	}
        else
! 	val = arg;
      }
    else
      {
        tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
  
*************** tsubst_call_declarator_parms (tree parms
*** 6598,6610 ****
    /* Chain this parameter on to the front of those we have already
       processed.  We don't use hash_tree_cons because that function
       doesn't check TREE_PARMLIST.  */
    new_parms = tree_cons (defarg, type, new_parms);
  
-   /* And note that these are parameters.  */
-   TREE_PARMLIST (new_parms) = 1;
-   
    return new_parms;
  }
  
  /* Take the tree structure T and replace template parameters used
     therein with the argument vector ARGS.  IN_DECL is an associated
--- 6595,6604 ----
*************** tsubst (tree t, tree args, tsubst_flags_
*** 6850,6860 ****
  	return r;
        }
  
      case TREE_LIST:
        {
! 	tree purpose, value, chain, result;
  
  	if (t == void_list_node)
  	  return t;
  
  	purpose = TREE_PURPOSE (t);
--- 6844,6854 ----
  	return r;
        }
  
      case TREE_LIST:
        {
! 	tree purpose, value, chain;
  
  	if (t == void_list_node)
  	  return t;
  
  	purpose = TREE_PURPOSE (t);
*************** tsubst (tree t, tree args, tsubst_flags_
*** 6880,6897 ****
  	  }
  	if (purpose == TREE_PURPOSE (t)
  	    && value == TREE_VALUE (t)
  	    && chain == TREE_CHAIN (t))
  	  return t;
! 	if (TREE_PARMLIST (t))
! 	  {
! 	    result = tree_cons (purpose, value, chain);
! 	    TREE_PARMLIST (result) = 1;
! 	  }
! 	else
! 	  result = hash_tree_cons (purpose, value, chain);
! 	return result;
        }
      case TREE_VEC:
        if (type != NULL_TREE)
  	{
  	  /* A binfo node.  We always need to make a copy, of the node
--- 6874,6884 ----
  	  }
  	if (purpose == TREE_PURPOSE (t)
  	    && value == TREE_VALUE (t)
  	    && chain == TREE_CHAIN (t))
  	  return t;
! 	return hash_tree_cons (purpose, value, chain);
        }
      case TREE_VEC:
        if (type != NULL_TREE)
  	{
  	  /* A binfo node.  We always need to make a copy, of the node
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7177,7200 ****
  
  	return make_unbound_class_template (ctx, name, complain);
        }
  
      case INDIRECT_REF:
-       {
- 	tree e = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- 	if (e == error_mark_node)
- 	  return error_mark_node;
- 	return make_pointer_declarator (type, e);
-       }
- 
      case ADDR_EXPR:
!       {
! 	tree e = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
! 	if (e == error_mark_node)
! 	  return error_mark_node;
! 	return make_reference_declarator (type, e);
!       }
  
      case ARRAY_REF:
        {
  	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
  	tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
--- 7164,7176 ----
  
  	return make_unbound_class_template (ctx, name, complain);
        }
  
      case INDIRECT_REF:
      case ADDR_EXPR:
!     case CALL_EXPR:
!       abort ();
  
      case ARRAY_REF:
        {
  	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
  	tree e2 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7202,7226 ****
  	  return error_mark_node;
  
  	return build_nt (ARRAY_REF, e1, e2);
        }
  
-     case CALL_EXPR:
-       {
- 	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
- 	tree e2 = (tsubst_call_declarator_parms
- 		   (CALL_DECLARATOR_PARMS (t), args, complain, in_decl));
- 	tree e3 = tsubst (CALL_DECLARATOR_EXCEPTION_SPEC (t), args,
- 			  complain, in_decl);
- 
- 	if (e1 == error_mark_node || e2 == error_mark_node 
- 	    || e3 == error_mark_node)
- 	  return error_mark_node;
- 
- 	return make_call_declarator (e1, e2, CALL_DECLARATOR_QUALS (t), e3);
-       }
- 
      case SCOPE_REF:
        {
  	tree e1 = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
  	tree e2 = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
  	if (e1 == error_mark_node || e2 == error_mark_node)
--- 7178,7187 ----
*************** tsubst_copy_and_build (tree t, 
*** 8336,8345 ****
--- 8297,8307 ----
      case NEW_EXPR:
        return build_new
  	(RECUR (TREE_OPERAND (t, 0)),
  	 RECUR (TREE_OPERAND (t, 1)),
  	 RECUR (TREE_OPERAND (t, 2)),
+ 	 RECUR (TREE_OPERAND (t, 3)),
  	 NEW_EXPR_USE_GLOBAL (t));
  
      case DELETE_EXPR:
       return delete_sanity
         (RECUR (TREE_OPERAND (t, 0)),
*************** instantiate_decl (tree d, int defer_ok, 
*** 11228,11238 ****
  					   eq_local_specializations,
  					   NULL);
  
        /* Set up context.  */
        import_export_decl (d);
!       start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
  
        /* Create substitution entries for the parameters.  */
        subst_decl = DECL_TEMPLATE_RESULT (template_for_substitution (d));
        tmpl_parm = DECL_ARGUMENTS (subst_decl);
        spec_parm = DECL_ARGUMENTS (d);
--- 11190,11200 ----
  					   eq_local_specializations,
  					   NULL);
  
        /* Set up context.  */
        import_export_decl (d);
!       start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
  
        /* Create substitution entries for the parameters.  */
        subst_decl = DECL_TEMPLATE_RESULT (template_for_substitution (d));
        tmpl_parm = DECL_ARGUMENTS (subst_decl);
        spec_parm = DECL_ARGUMENTS (d);
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.402
diff -c -5 -p -r1.402 semantics.c
*** cp/semantics.c	17 Jun 2004 22:35:53 -0000	1.402
--- cp/semantics.c	22 Jun 2004 02:13:18 -0000
*************** finish_fname (tree id)
*** 1863,1889 ****
    if (processing_template_decl)
      decl = DECL_NAME (decl);
    return decl;
  }
  
- /* Begin a function definition declared with DECL_SPECS, ATTRIBUTES,
-    and DECLARATOR.  Returns nonzero if the function-declaration is
-    valid.  */
- 
- int
- begin_function_definition (tree decl_specs, tree attributes, tree declarator)
- {
-   if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
-     return 0;
- 
-   /* The things we're about to see are not directly qualified by any
-      template headers we've seen thus far.  */
-   reset_specialization ();
- 
-   return 1;
- }
- 
  /* Finish a translation unit.  */
  
  void 
  finish_translation_unit (void)
  {
--- 1863,1872 ----
*************** check_template_template_default_arg (tre
*** 1961,1988 ****
      }
  
    return argument;
  }
  
- /* Finish a parameter list, indicated by PARMS.  If ELLIPSIS is
-    nonzero, the parameter list was terminated by a `...'.  */
- 
- tree
- finish_parmlist (tree parms, int ellipsis)
- {
-   if (parms)
-     {
-       /* We mark the PARMS as a parmlist so that declarator processing can
-          disambiguate certain constructs.  */
-       TREE_PARMLIST (parms) = 1;
-       /* We do not append void_list_node here, but leave it to grokparms
-          to do that.  */
-       PARMLIST_ELLIPSIS_P (parms) = ellipsis;
-     }
-   return parms;
- }
- 
  /* Begin a class definition, as indicated by T.  */
  
  tree
  begin_class_definition (tree t)
  {
--- 1944,1953 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]