From 058b15c1dc2199a810e4f8793993dc4ede61bb0a Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 22 Jun 2004 07:18:38 +0000 Subject: [PATCH] cp-tree.def (NEW_EXPR): Add a fourth slot. * 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. From-SVN: r83482 --- gcc/cp/ChangeLog | 109 ++++ gcc/cp/cp-mudflap.c | 9 +- gcc/cp/cp-tree.def | 5 +- gcc/cp/cp-tree.h | 132 +++-- gcc/cp/decl.c | 1223 +++++++++++++++++-------------------------- gcc/cp/decl.h | 2 +- gcc/cp/decl2.c | 43 +- gcc/cp/init.c | 145 +---- gcc/cp/lex.c | 56 -- gcc/cp/method.c | 88 ++-- gcc/cp/optimize.c | 2 +- gcc/cp/parser.c | 856 +++++++++++++++++++----------- gcc/cp/pt.c | 68 +-- gcc/cp/semantics.c | 35 -- 14 files changed, 1343 insertions(+), 1430 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d8b494bdff6..05ddba31d7b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,112 @@ +2004-06-21 Mark Mitchell + + * 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. + 2004-06-21 Richard Kenner * call.c (build_vfield_ref): Add new operand for COMPONENT_REF. diff --git a/gcc/cp/cp-mudflap.c b/gcc/cp/cp-mudflap.c index faa57e2df5e..23e875029d6 100644 --- a/gcc/cp/cp-mudflap.c +++ b/gcc/cp/cp-mudflap.c @@ -63,6 +63,7 @@ void mflang_flush_calls (tree enqueued_call_stmt_chain) { tree fnname, fndecl, body; + tree type; /* Short-circuit! */ if (enqueued_call_stmt_chain == NULL_TREE) @@ -70,11 +71,8 @@ mflang_flush_calls (tree enqueued_call_stmt_chain) /* 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); + 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; @@ -82,6 +80,7 @@ mflang_flush_calls (tree enqueued_call_stmt_chain) 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) diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 4f7961b7b8a..f1912b17438 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -51,8 +51,9 @@ 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) + 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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9d668d398b7..e29e084e0bb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -45,7 +45,6 @@ struct diagnostic_context; 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). @@ -64,7 +63,6 @@ struct diagnostic_context; 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). @@ -1566,13 +1564,6 @@ struct lang_type GTY(()) #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 @@ -2953,18 +2944,6 @@ struct lang_decl GTY(()) #define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1) #define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2) -/* 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. */ @@ -3529,6 +3508,89 @@ extern GTY(()) operator_name_info_t operator_name_info 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); @@ -3674,19 +3736,18 @@ 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 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 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 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); @@ -3696,11 +3757,12 @@ 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 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, tree, tree); +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); @@ -3749,8 +3811,8 @@ 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 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); @@ -3828,7 +3890,7 @@ 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_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); @@ -3839,14 +3901,8 @@ 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); @@ -3892,7 +3948,7 @@ 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 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); @@ -4095,11 +4151,9 @@ 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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 55ce6841723..66f6b36e9fe 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -53,7 +53,7 @@ Boston, MA 02111-1307, USA. */ #include "timevar.h" #include "tree-flow.h" -static tree grokparms (tree, tree *); +static tree grokparms (const cp_parameter_declarator *, tree *); static const char *redeclaration_error_message (tree, tree); static int decl_jump_unsafe (tree); @@ -3564,8 +3564,8 @@ shadow_tag (tree declspecs) if (TYPE_FIELDS (t)) { - tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, - NULL); + tree decl = grokdeclarator (/*declarator=*/NULL, + declspecs, NORMAL, 0, NULL); finish_anon_union (decl); } } @@ -3576,15 +3576,12 @@ shadow_tag (tree declspecs) /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree -groktypename (tree typename) +groktypename (tree type_specifiers, const cp_declarator *declarator) { 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); + split_specs_attrs (type_specifiers, &specs, &attrs); + type = grokdeclarator (declarator, specs, TYPENAME, 0, &attrs); if (attrs) cplus_decl_attributes (&type, attrs, 0); return type; @@ -3606,7 +3603,7 @@ groktypename (tree typename) grokfield and not through here. */ tree -start_decl (tree declarator, +start_decl (const cp_declarator *declarator, tree declspecs, int initialized, tree attributes, @@ -5122,7 +5119,7 @@ start_cleanup_fn (void) } pushdecl (fndecl); - start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED); + start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED); interface_unknown = old_interface_unknown; interface_only = old_interface_only; @@ -5284,25 +5281,6 @@ expand_static_init (tree decl, tree init) 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, @@ -6140,40 +6118,21 @@ compute_array_index_type (tree name, tree size) unqualified name, NULL_TREE is returned. */ tree -get_scope_of_declarator (tree declarator) +get_scope_of_declarator (const cp_declarator *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; - } + 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 @@ -6332,7 +6291,7 @@ check_special_function_return_type (special_function_kind sfk, should not be `S'. */ tree -grokdeclarator (tree declarator, +grokdeclarator (const cp_declarator *declarator, tree declspecs, enum decl_context decl_context, int initialized, @@ -6352,10 +6311,10 @@ grokdeclarator (tree declarator, tree dependant_name = NULL_TREE; tree typedef_decl = NULL_TREE; - const char *name; + const char *name = NULL; tree typedef_type = NULL_TREE; int funcdef_flag = 0; - enum tree_code innermost_code = ERROR_MARK; + cp_declarator_kind innermost_code = cdk_error; int bitfield = 0; #if 0 /* See the code below that used this. */ @@ -6368,16 +6327,27 @@ grokdeclarator (tree declarator, 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; + 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) @@ -6389,186 +6359,35 @@ grokdeclarator (tree declarator, /* 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; + for (id_declarator = declarator; + id_declarator; + id_declarator = id_declarator->declarator) + { + if (id_declarator->kind != cdk_id) + innermost_code = id_declarator->kind; - case BIT_NOT_EXPR: /* For C++ destructors! */ + switch (id_declarator->kind) + { + case cdk_function: + if (id_declarator->declarator + && id_declarator->declarator->kind == cdk_id) { - 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; + sfk = id_declarator->declarator->u.id.sfk; + if (sfk == sfk_destructor) + flags = DTOR_FLAG; } - 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; + break; - 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 + case cdk_id: + { + tree decl = id_declarator->u.id.name; + if (!decl) + break; + if (TREE_CODE (decl) == SCOPE_REF) { - 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 = ""; - } - 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: + tree qualifying_scope = TREE_OPERAND (decl, 0); +; + /* It is valid to write: class C { void f(); }; typedef C D; @@ -6578,93 +6397,112 @@ grokdeclarator (tree declarator, 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) + 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 name = decl; + tree type = TREE_OPERAND (decl, 0); + type = constructor_name (type); + name = IDENTIFIER_POINTER (type); + } + break; - if (TREE_CODE (name) == BIT_NOT_EXPR) - name = TREE_OPERAND (name, 0); + case TEMPLATE_ID_EXPR: + { + tree fns = TREE_OPERAND (decl, 0); - if (!constructor_name_p (decl, ctype)) - ; - else if (decl == name) - { - sfk = sfk_constructor; - ctor_return_type = ctype; - } - else + dname = fns; + if (TREE_CODE (dname) == COMPONENT_REF) + dname = TREE_OPERAND (dname, 1); + if (TREE_CODE (dname) != IDENTIFIER_NODE) { - sfk = sfk_destructor; - ctor_return_type = ctype; - flags = DTOR_FLAG; - TREE_OPERAND (decl, 0) = constructor_name (ctype); - next = &TREE_OPERAND (decl, 0); + my_friendly_assert (is_overloaded_fn (dname), + 19990331); + dname = DECL_NAME (get_first_fn (dname)); } } - } - break; + /* Fall through. */ - case ERROR_MARK: - next = 0; - break; + case IDENTIFIER_NODE: + if (TREE_CODE (decl) == IDENTIFIER_NODE) + dname = decl; - 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; + 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 = ""; + } + break; + + case TYPE_DECL: + dname = constructor_name (TREE_TYPE (decl)); + name = IDENTIFIER_POINTER (dname); + break; + + default: + abort (); + } break; - case BASELINK: - next = &BASELINK_FUNCTIONS (decl); + case cdk_array: + case cdk_pointer: + case cdk_reference: + case cdk_ptrmem: 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; + case cdk_error: break; - + default: - my_friendly_assert (0, 20020917); + 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 != CALL_EXPR) + if (funcdef_flag && innermost_code != cdk_function) return 0; if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG) - && innermost_code != CALL_EXPR + && innermost_code != cdk_function && ! (ctype && declspecs == NULL_TREE)) { error ("declaration of `%D' as non-function", dname); @@ -7143,10 +6981,10 @@ grokdeclarator (tree declarator, if (declarator) { /* Avoid trying to get an operand off an identifier node. */ - if (TREE_CODE (declarator) == IDENTIFIER_NODE) - tmp = declarator; + if (declarator->kind != cdk_id) + tmp = declarator->declarator->u.id.name; else - tmp = TREE_OPERAND (declarator, 0); + tmp = declarator->u.id.name; op = IDENTIFIER_OPNAME_P (tmp); if (IDENTIFIER_TYPENAME_P (tmp)) { @@ -7205,114 +7043,85 @@ grokdeclarator (tree declarator, 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) + if (!id_declarator) + unqualified_id = NULL_TREE; + else { - /* 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) + 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)) { - 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; - } - } + 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; - 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); - } + case IDENTIFIER_NODE: + case TEMPLATE_ID_EXPR: break; + + default: + abort (); + } + } - case ARRAY_REF: - { - tree size = TREE_OPERAND (declarator, 1); - declarator = TREE_OPERAND (declarator, 0); + /* 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; - type = create_array_type_for_decl (dname, type, size); + if (type == error_mark_node) + return error_mark_node; - 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); + inner_declarator = declarator->declarator; - ctype = NULL_TREE; - } + 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 CALL_EXPR: + case cdk_function: { 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. */ @@ -7334,25 +7143,15 @@ grokdeclarator (tree declarator, 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); + quals = declarator->u.function.qualifiers; /* Pick up the exception specifications. */ - raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator); + raises = declarator->u.function.exception_specification; /* 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); + funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id; if (ctype == NULL_TREE && decl_context == FIELD @@ -7362,7 +7161,8 @@ grokdeclarator (tree declarator, if (ctype && sfk == sfk_conversion) TYPE_HAS_CONVERSION (ctype) = 1; - if (ctype && constructor_name_p (dname, ctype)) + 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 @@ -7451,75 +7251,76 @@ grokdeclarator (tree declarator, 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); + arg_types = grokparms (declarator->u.function.parameters, + &parms); - if (declarator && flags == DTOR_FLAG) + if (inner_declarator + && inner_declarator->kind == cdk_id + && inner_declarator->u.id.sfk == sfk_destructor + && arg_types != void_list_node) { - /* 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; - } + 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: + 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 (TREE_CODE (declarator) == ADDR_EXPR + 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) - && (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. */ + 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 (TREE_CODE (declarator) == ADDR_EXPR) + 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 (ctype) - type = build_ptrmem_type (ctype, 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 (TREE_TYPE (declarator)) + if (declarator->u.pointer.qualifiers) { tree typemodlist; int erred = 0; @@ -7527,7 +7328,7 @@ grokdeclarator (tree declarator, int volatilep = 0; int restrictp = 0; - for (typemodlist = TREE_TYPE (declarator); typemodlist; + for (typemodlist = declarator->u.pointer.qualifiers; typemodlist; typemodlist = TREE_CHAIN (typemodlist)) { tree qualifier = TREE_VALUE (typemodlist); @@ -7562,158 +7363,115 @@ grokdeclarator (tree declarator, 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); + case cdk_error: + break; - 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 struct S{}; - template <> struct S { void f(); }; - void S::f () {} - - is correct; there shouldn't be a `template <>' for - the definition of `S::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); - } + 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 (sname == NULL_TREE) - goto done_scoping; + /* 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; - if (TREE_CODE (sname) == IDENTIFIER_NODE) - { - /* This is the `standard' use of the scoping operator: - basetype :: member . */ + 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: - if (ctype == current_class_type) - { - /* class A { - void A::f (); - }; + template struct S{}; + template <> struct S { void f(); }; + void S::f () {} - Is this ill-formed? */ + is correct; there shouldn't be a `template <>' for the + definition of `S::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; - 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; - } + t = TYPE_MAIN_DECL (t); + t = DECL_CONTEXT (t); + } - 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; + if (ctype == current_class_type) + { + /* class A { + void A::f (); + }; - case BIT_NOT_EXPR: - declarator = TREE_OPERAND (declarator, 0); - break; + Is this ill-formed? */ - case BASELINK: - declarator = BASELINK_FUNCTIONS (declarator); - break; + 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); - case RECORD_TYPE: - case UNION_TYPE: - case ENUMERAL_TYPE: - declarator = NULL_TREE; - break; + 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; - case ERROR_MARK: - declarator = NULL_TREE; - break; + It is? How? jason 10/2/94 */ - default: - abort (); + 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; } } @@ -7788,24 +7546,7 @@ grokdeclarator (tree declarator, } } - 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; @@ -7817,14 +7558,14 @@ grokdeclarator (tree declarator, if (decl_context == FIELD) { - if (constructor_name_p (declarator, current_class_type)) + if (constructor_name_p (unqualified_id, 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); + unqualified_id); + decl = build_lang_decl (TYPE_DECL, unqualified_id, type); } else { - decl = build_decl (TYPE_DECL, declarator, type); + 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) @@ -7836,7 +7577,7 @@ grokdeclarator (tree declarator, Nothing can refer to it, so nothing needs know about the name change. */ if (type != error_mark_node - && declarator + && unqualified_id && TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && TYPE_ANONYMOUS_P (type) @@ -7848,7 +7589,7 @@ grokdeclarator (tree declarator, tree t; /* Replace the anonymous name with the real name everywhere. */ - lookup_tag_reverse (type, declarator); + 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; @@ -7984,7 +7725,7 @@ grokdeclarator (tree declarator, } if (ctype) { - tree dummy = build_decl (TYPE_DECL, declarator, type); + tree dummy = build_decl (TYPE_DECL, unqualified_id, type); grok_method_quals (ctype, dummy, quals); type = TREE_TYPE (dummy); } @@ -7992,13 +7733,13 @@ grokdeclarator (tree declarator, return type; } - else if (declarator == NULL_TREE && decl_context != PARM + 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); - declarator = make_anon_name (); + unqualified_id = make_anon_name (); } /* `void' at top level (not within pointer) @@ -8008,11 +7749,11 @@ grokdeclarator (tree declarator, if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM) { - if (! declarator) + if (! unqualified_id) error ("unnamed variable or field declared void"); - else if (TREE_CODE (declarator) == IDENTIFIER_NODE) + else if (TREE_CODE (unqualified_id) == IDENTIFIER_NODE) { - if (IDENTIFIER_OPNAME_P (declarator)) + if (IDENTIFIER_OPNAME_P (unqualified_id)) abort (); else error ("variable or field `%s' declared void", name); @@ -8049,7 +7790,7 @@ grokdeclarator (tree declarator, if (decl_context == PARM) { - decl = cp_build_parm_decl (declarator, type); + decl = cp_build_parm_decl (unqualified_id, type); bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); @@ -8083,10 +7824,10 @@ grokdeclarator (tree declarator, /* We catch the others as conflicts with the builtin typedefs. */ - if (friendp && declarator == ridpointers[(int) RID_SIGNED]) + if (friendp && unqualified_id == ridpointers[(int) RID_SIGNED]) { error ("function `%D' cannot be declared friend", - declarator); + unqualified_id); friendp = 0; } @@ -8098,7 +7839,7 @@ grokdeclarator (tree declarator, if (ctype == NULL_TREE) { error ("can't make `%D' into a method -- not in a class", - declarator); + unqualified_id); return void_type_node; } @@ -8107,16 +7848,16 @@ grokdeclarator (tree declarator, if (virtualp && TREE_CODE (ctype) == UNION_TYPE) { error ("function `%D' declared virtual inside a union", - declarator); + unqualified_id); return void_type_node; } - if (NEW_DELETE_OPNAME_P (declarator)) + if (NEW_DELETE_OPNAME_P (unqualified_id)) { if (virtualp) { error ("`%D' cannot be declared virtual, since it is always static", - declarator); + unqualified_id); virtualp = 0; } } @@ -8132,10 +7873,10 @@ grokdeclarator (tree declarator, publicp = (! friendp || ! staticp) && function_context == NULL_TREE; decl = grokfndecl (ctype, type, - TREE_CODE (declarator) != TEMPLATE_ID_EXPR - ? declarator : dname, + TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR + ? unqualified_id : dname, parms, - declarator, + unqualified_id, virtualp, flags, quals, raises, friendp ? -1 : 0, friendp, publicp, inlinep, funcdef_flag, template_count, in_namespace); @@ -8179,10 +7920,10 @@ grokdeclarator (tree declarator, /* 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, + TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR + ? unqualified_id : dname, parms, - declarator, + unqualified_id, virtualp, flags, quals, raises, friendp ? -1 : 0, friendp, 1, 0, funcdef_flag, template_count, in_namespace); @@ -8193,8 +7934,8 @@ grokdeclarator (tree declarator, && !COMPLETE_TYPE_P (complete_type (type)) && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) { - if (declarator) - error ("field `%D' has incomplete type", declarator); + if (unqualified_id) + error ("field `%D' has incomplete type", unqualified_id); else error ("name `%T' has incomplete type", type); @@ -8216,7 +7957,7 @@ grokdeclarator (tree declarator, if (friendp) { error ("`%E' is neither function nor member function; " - "cannot be declared friend", declarator); + "cannot be declared friend", unqualified_id); friendp = 0; } decl = NULL_TREE; @@ -8232,13 +7973,13 @@ grokdeclarator (tree declarator, if (template_class_depth (current_class_type) == 0) { decl = check_explicit_specialization - (declarator, decl, template_count, + (unqualified_id, decl, template_count, 2 * (funcdef_flag != 0) + 4); if (decl == error_mark_node) return error_mark_node; } - decl = do_friend (ctype, declarator, decl, + decl = do_friend (ctype, unqualified_id, decl, *attrlist, flags, quals, funcdef_flag); return decl; } @@ -8267,15 +8008,15 @@ grokdeclarator (tree declarator, 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); + 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 (declarator, + else if (check_static_variable_definition (unqualified_id, type)) /* If we just return the declaration, crashes will sometimes occur. We therefore return @@ -8289,14 +8030,14 @@ grokdeclarator (tree declarator, { /* C++ allows static class members. All other work for this is done by grokfield. */ - decl = build_lang_decl (VAR_DECL, declarator, type); + 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, declarator, type); + decl = build_decl (FIELD_DECL, unqualified_id, type); DECL_NONADDRESSABLE_P (decl) = bitfield; if (RIDBIT_SETP (RID_MUTABLE, specbits)) { @@ -8315,13 +8056,13 @@ grokdeclarator (tree declarator, tree original_name; int publicp = 0; - if (! declarator) + if (!unqualified_id) return NULL_TREE; - if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR) original_name = dname; else - original_name = declarator; + original_name = unqualified_id; if (RIDBIT_SETP (RID_AUTO, specbits)) error ("storage class `auto' invalid for function `%s'", name); @@ -8363,7 +8104,7 @@ grokdeclarator (tree declarator, || RIDBIT_SETP (RID_EXTERN, specbits) || !RIDBIT_SETP (RID_STATIC, specbits)); - decl = grokfndecl (ctype, type, original_name, parms, declarator, + decl = grokfndecl (ctype, type, original_name, parms, unqualified_id, virtualp, flags, quals, raises, 1, friendp, publicp, inlinep, funcdef_flag, @@ -8401,7 +8142,7 @@ grokdeclarator (tree declarator, /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ - decl = grokvardecl (type, declarator, &specbits, + decl = grokvardecl (type, unqualified_id, &specbits, initialized, (type_quals & TYPE_QUAL_CONST) != 0, ctype ? ctype : in_namespace); @@ -8601,48 +8342,33 @@ check_default_argument (tree decl, tree arg) 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. + 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 (tree first_parm, tree *parms) +grokparms (const cp_parameter_declarator *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 ellipsis = !first_parm || first_parm->ellipsis_p; + const cp_parameter_declarator *parm; int any_error = 0; - my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115); - - for (parm = first_parm; parm != NULL_TREE; parm = chain) + for (parm = first_parm; parm != NULL; parm = parm->next) { tree type = NULL_TREE; - tree decl = TREE_VALUE (parm); - tree init = TREE_PURPOSE (parm); + tree decl_specifiers = parm->decl_specifiers; + tree init = parm->default_argument; tree specs, attrs; + tree decl; - 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) + if (parm == no_parameters) break; - split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs); - decl = grokdeclarator (TREE_VALUE (decl), specs, + 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; @@ -8654,7 +8380,7 @@ grokparms (tree first_parm, tree *parms) if (VOID_TYPE_P (type)) { if (same_type_p (type, void_type_node) - && !DECL_NAME (decl) && !result && !chain && !ellipsis) + && !DECL_NAME (decl) && !result && !parm->next && !ellipsis) /* this is a parmlist of `(void)', which is ok. */ break; cxx_incomplete_type_error (decl, type); @@ -10036,19 +9762,14 @@ check_function_type (tree decl, tree current_function_parms) 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) +void +start_preparsed_function (tree decl1, tree attrs, int flags) { - tree decl1; tree ctype = NULL_TREE; tree fntype; tree restype; @@ -10060,67 +9781,23 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) 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 + 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)) { - 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; - } - } + 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) @@ -10382,6 +10059,55 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) 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; } @@ -10872,7 +10598,7 @@ finish_function (int flags) CHANGES TO CODE IN `grokfield'. */ tree -start_method (tree declspecs, tree declarator, tree attrlist) +start_method (tree declspecs, const cp_declarator *declarator, tree attrlist) { tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, &attrlist); @@ -11184,7 +10910,6 @@ tree build_void_list_node (void) { tree t = build_tree_list (NULL_TREE, void_type_node); - TREE_PARMLIST (t) = 1; return t; } diff --git a/gcc/cp/decl.h b/gcc/cp/decl.h index 4bae89c64f5..871d568a0c5 100644 --- a/gcc/cp/decl.h +++ b/gcc/cp/decl.h @@ -31,7 +31,7 @@ enum decl_context }; /* We need this in here to get the decl_context definition. */ -extern tree grokdeclarator (tree, tree, enum decl_context, int, tree*); +extern tree grokdeclarator (const cp_declarator *, tree, enum decl_context, int, tree*); #ifdef DEBUG_CP_BINDING_LEVELS /* Purely for debugging purposes. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 00105a6d2a6..80e56ec82e7 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -127,7 +127,7 @@ grok_method_quals (tree ctype, tree function, tree quals) int dup_quals = TYPE_UNQUALIFIED; int this_quals = TYPE_UNQUALIFIED; - do + while (quals) { int tq = cp_type_qual_from_rid (TREE_VALUE (quals)); @@ -139,7 +139,6 @@ grok_method_quals (tree ctype, tree function, tree quals) type_quals |= tq; quals = TREE_CHAIN (quals); } - while (quals); if (dup_quals != TYPE_UNQUALIFIED) error ("duplicate type qualifiers in %s declaration", @@ -168,7 +167,7 @@ grok_x_components (tree specs) specs = strip_attrs (specs); check_tag_decl (specs); - t = groktypename (build_tree_list (specs, NULL_TREE)); + 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; }; };'. */ @@ -841,7 +840,8 @@ finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree, CHANGES TO CODE IN `start_method'. */ tree -grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree, +grokfield (const cp_declarator *declarator, tree declspecs, + tree init, tree asmspec_tree, tree attrlist) { tree value; @@ -849,15 +849,18 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree, int flags = LOOKUP_ONLYCONVERTING; if (declspecs == NULL_TREE - && TREE_CODE (declarator) == SCOPE_REF - && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE) + && 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, 0)))) + if (! IS_AGGR_TYPE_CODE (TREE_CODE + (TREE_OPERAND (declarator->u.id.name, 0)))) ; - else if (TREE_COMPLEXITY (declarator) == current_class_depth) + else if (TREE_COMPLEXITY (declarator->u.id.name) == current_class_depth) pop_nested_class (); - return do_class_using_decl (declarator); + return do_class_using_decl (declarator->u.id.name); } if (init @@ -1020,7 +1023,7 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree, WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */ tree -grokbitfield (tree declarator, tree declspecs, tree width) +grokbitfield (const cp_declarator *declarator, tree declspecs, tree width) { tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL); @@ -1915,8 +1918,8 @@ set_guard (tree guard) static tree start_objects (int method_type, int initp) { - tree fnname; tree body; + tree fndecl; char type[10]; /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */ @@ -1936,12 +1939,11 @@ start_objects (int method_type, int 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); + 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. */ @@ -2108,10 +2110,9 @@ start_static_storage_duration_function (unsigned count) 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); + 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); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 2af51185e7b..c2a98781431 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1665,126 +1665,18 @@ build_builtin_delete_call (tree addr) PLACEMENT is the `placement' list for user-defined operator new (). */ tree -build_new (tree placement, tree decl, tree init, int use_global_new) +build_new (tree placement, tree type, tree nelts, tree init, + int use_global_new) { - tree type, rval; - tree nelts = NULL_TREE, t; - int has_array = 0; + tree rval; - if (decl == error_mark_node) + if (type == 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, NULL_TREE), - NULL_TREE); - else - t = type; - rval = build_min (NEW_EXPR, build_pointer_type (type), - placement, t, init); + placement, type, nelts, init); NEW_EXPR_USE_GLOBAL (rval) = use_global_new; TREE_SIDE_EFFECTS (rval) = 1; return rval; @@ -1805,22 +1697,8 @@ build_new (tree placement, tree decl, tree init, int use_global_new) 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, NULL_TREE, NULL_TREE); - else - t = type; - - rval = build (NEW_EXPR, build_pointer_type (type), placement, t, init); + 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); @@ -1957,15 +1835,14 @@ build_new_1 (tree exp) placement = TREE_OPERAND (exp, 0); type = TREE_OPERAND (exp, 1); - init = TREE_OPERAND (exp, 2); + nelts = TREE_OPERAND (exp, 2); + init = TREE_OPERAND (exp, 3); globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp); - if (TREE_CODE (type) == ARRAY_REF) + if (nelts) { has_array = 1; - nelts = outer_nelts = TREE_OPERAND (type, 1); - type = TREE_OPERAND (type, 0); - + outer_nelts = nelts; /* Use an incomplete array type to avoid VLA headaches. */ full_type = build_cplus_array_type (type, NULL_TREE); } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index d10fa2e3758..7152e692759 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -82,62 +82,6 @@ struct impl_files 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. */ diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 495244fa748..cc06725c3c3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -448,7 +448,7 @@ use_thunk (tree thunk_fndecl, bool emit_p) DECL_RESULT (thunk_fndecl) = NULL_TREE; - start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED); + 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. */ @@ -742,7 +742,7 @@ synthesize_method (tree fndecl) DECL_SOURCE_LOCATION (fndecl) = input_location; interface_unknown = 1; - start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); + start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); clear_last_expr (); stmt = begin_function_body (); @@ -937,56 +937,56 @@ locate_copy (tree type, void *client_) tree implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) { - tree declspecs = NULL_TREE; - tree fn, args = NULL_TREE; + tree fn; + tree parameter_types = void_list_node; + tree return_type = void_type_node; + tree fn_type; tree raises = empty_except_spec; - bool retref = false; - bool has_parm = false; - tree name = constructor_name (type); + tree rhs_parm_type = NULL_TREE; + tree name; switch (kind) { case sfk_destructor: /* Destructor. */ - name = build_nt (BIT_NOT_EXPR, name); - args = void_list_node; + name = constructor_name (type); raises = synthesize_exception_spec (type, &locate_dtor, 0); break; case sfk_constructor: /* Default constructor. */ - args = void_list_node; + 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; - 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); - + 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; - argtype = build_qualified_type (argtype, TYPE_QUAL_CONST); + rhs_parm_type = build_qualified_type (type, 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); - + 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; } @@ -994,21 +994,37 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) 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); + /* 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; diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 5102f576bbe..448a0b376a9 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -132,7 +132,7 @@ maybe_clone_body (tree fn) /* Start processing the function. */ push_to_top_level (); - start_function (NULL_TREE, clone, NULL_TREE, SF_PRE_PARSED); + start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); /* Remap the parameters. */ decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 5ad4250ee0a..d86f2039675 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -995,6 +995,181 @@ cp_lexer_stop_debugging (cp_lexer* lexer) } +/* 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 @@ -1366,10 +1541,10 @@ static tree cp_parser_new_expression 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 tree cp_parser_new_declarator_opt - (cp_parser *); -static tree cp_parser_direct_new_declarator +static cp_declarator *cp_parser_direct_new_declarator (cp_parser *); static tree cp_parser_new_initializer (cp_parser *); @@ -1495,9 +1670,9 @@ static void cp_parser_linkage_specification static tree cp_parser_init_declarator (cp_parser *, tree, tree, bool, bool, int, bool *); -static tree cp_parser_declarator +static cp_declarator *cp_parser_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool *); -static tree cp_parser_direct_declarator +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 *); @@ -1511,11 +1686,11 @@ static tree cp_parser_type_id (cp_parser *); static tree cp_parser_type_specifier_seq (cp_parser *); -static tree cp_parser_parameter_declaration_clause +static cp_parameter_declarator *cp_parser_parameter_declaration_clause (cp_parser *); -static tree cp_parser_parameter_declaration_list - (cp_parser *); -static tree cp_parser_parameter_declaration +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 *); @@ -1561,7 +1736,7 @@ 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 +static cp_declarator *cp_parser_conversion_declarator_opt (cp_parser *); static bool cp_parser_ctor_initializer_opt (cp_parser *); @@ -1586,7 +1761,7 @@ static void cp_parser_template_declaration static tree cp_parser_template_parameter_list (cp_parser *); static tree cp_parser_template_parameter - (cp_parser *); + (cp_parser *, bool *); static tree cp_parser_type_parameter (cp_parser *); static tree cp_parser_template_id @@ -1647,7 +1822,7 @@ static tree cp_parser_lookup_name_simple static tree cp_parser_maybe_treat_template_as_class (tree, bool); static bool cp_parser_check_declarator_template_parameters - (cp_parser *, tree); + (cp_parser *, cp_declarator *); static bool cp_parser_check_template_parameters (cp_parser *, unsigned); static tree cp_parser_simple_cast_expression @@ -1659,7 +1834,7 @@ static tree cp_parser_global_scope_opt 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); + (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 @@ -1669,7 +1844,7 @@ static tree cp_parser_single_declaration static tree cp_parser_functional_cast (cp_parser *, tree); static tree cp_parser_save_member_function_body - (cp_parser *, tree, tree, tree); + (cp_parser *, tree, cp_declarator *, tree); static tree cp_parser_enclosed_template_argument_list (cp_parser *); static void cp_parser_save_default_args @@ -1729,7 +1904,7 @@ static bool cp_parser_simulate_error static void cp_parser_check_type_definition (cp_parser *); static void cp_parser_check_for_definition_in_return_type - (tree, int); + (cp_declarator *, int); static void cp_parser_check_for_invalid_template_id (cp_parser *, tree); static bool cp_parser_non_integral_constant_expression @@ -1871,18 +2046,19 @@ cp_parser_check_type_definition (cp_parser* parser) then an error is issued. */ static void -cp_parser_check_for_definition_in_return_type (tree declarator, +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 - && (TREE_CODE (declarator) == INDIRECT_REF - || TREE_CODE (declarator) == ADDR_EXPR)) - declarator = TREE_OPERAND (declarator, 0); + && (declarator->kind == cdk_pointer + || declarator->kind == cdk_reference + || declarator->kind == cdk_ptrmem)) + declarator = declarator->declarator; if (declarator - && TREE_CODE (declarator) == CALL_EXPR + && declarator->kind == cdk_function && declares_class_or_enum & 2) error ("new types may not be defined in a return type"); } @@ -2423,27 +2599,55 @@ cp_parser_identifier (cp_parser* parser) 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)) - break; + { + /* Consume the EOF token. */ + cp_parser_require (parser, CPP_EOF, "end-of-file"); + + /* Finish up. */ + finish_translation_unit (); - /* Otherwise, issue an error message. */ - cp_parser_error (parser, "expected declaration"); - return false; + success = true; + break; + } + else + { + cp_parser_error (parser, "expected declaration"); + success = false; + break; + } } - /* Consume the EOF token. */ - cp_parser_require (parser, CPP_EOF, "end-of-file"); - - /* Finish up. */ - finish_translation_unit (); + /* 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 true; + return success; } /* Expressions [gram.expr] */ @@ -4557,6 +4761,7 @@ cp_parser_new_expression (cp_parser* parser) tree placement; tree type; tree initializer; + tree nelts; /* Look for the optional `::' operator. */ global_scope_p @@ -4593,10 +4798,11 @@ cp_parser_new_expression (cp_parser* parser) 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); + 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)) @@ -4610,7 +4816,7 @@ cp_parser_new_expression (cp_parser* parser) return error_mark_node; /* Create a representation of the new-expression. */ - return build_new (placement, type, initializer, global_scope_p); + return build_new (placement, type, nelts, initializer, global_scope_p); } /* Parse a new-placement. @@ -4637,15 +4843,19 @@ cp_parser_new_placement (cp_parser* parser) 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. */ + 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) +cp_parser_new_type_id (cp_parser* parser, tree *nelts) { tree type_specifier_seq; - tree declarator; + 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 @@ -4659,9 +4869,56 @@ cp_parser_new_type_id (cp_parser* parser) /* Restore the old message. */ parser->type_definition_forbidden_message = saved_message; /* Parse the new-declarator. */ - declarator = cp_parser_new_declarator_opt (parser); + new_declarator = cp_parser_new_declarator_opt (parser); - return build_tree_list (type_specifier_seq, declarator); + /* 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. @@ -4670,10 +4927,9 @@ cp_parser_new_type_id (cp_parser* parser) ptr-operator new-declarator [opt] direct-new-declarator - Returns a representation of the declarator. See - cp_parser_declarator for the representations used. */ + Returns the declarator. */ -static tree +static cp_declarator * cp_parser_new_declarator_opt (cp_parser* parser) { enum tree_code code; @@ -4687,23 +4943,23 @@ cp_parser_new_declarator_opt (cp_parser* parser) /* If that worked, look for more new-declarators. */ if (cp_parser_parse_definitely (parser)) { - tree declarator; + cp_declarator *declarator; /* Parse another optional declarator. */ declarator = cp_parser_new_declarator_opt (parser); /* Create the representation of the declarator. */ - if (code == INDIRECT_REF) + 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); - /* Handle the pointer-to-member case. */ - if (type) - declarator = build_nt (SCOPE_REF, type, declarator); - return declarator; } @@ -4711,7 +4967,7 @@ cp_parser_new_declarator_opt (cp_parser* parser) if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) return cp_parser_direct_new_declarator (parser); - return NULL_TREE; + return NULL; } /* Parse a direct-new-declarator. @@ -4720,13 +4976,12 @@ cp_parser_new_declarator_opt (cp_parser* parser) [ expression ] direct-new-declarator [constant-expression] - Returns an ARRAY_REF, following the same conventions as are - documented for cp_parser_direct_declarator. */ + */ -static tree +static cp_declarator * cp_parser_direct_new_declarator (cp_parser* parser) { - tree declarator = NULL_TREE; + cp_declarator *declarator = NULL; while (true) { @@ -4767,8 +5022,7 @@ cp_parser_direct_new_declarator (cp_parser* parser) cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); /* Add this bound to the declarator. */ - declarator = build_nt (ARRAY_REF, declarator, expression, - NULL_TREE, NULL_TREE); + declarator = make_array_declarator (declarator, expression); /* If the next token is not a `[', then there are no more bounds. */ @@ -6023,7 +6277,7 @@ cp_parser_condition (cp_parser* parser) tree decl; tree asm_specification; tree attributes; - tree declarator; + cp_declarator *declarator; tree initializer = NULL_TREE; /* Parse the declarator. */ @@ -6334,9 +6588,17 @@ cp_parser_jump_statement (cp_parser* parser) static void cp_parser_declaration_statement (cp_parser* parser) { - /* Parse the block-declaration. */ + 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 (); } @@ -6467,6 +6729,7 @@ 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. */ @@ -6495,6 +6758,9 @@ cp_parser_declaration (cp_parser* parser) 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 @@ -6544,6 +6810,9 @@ cp_parser_declaration (cp_parser* parser) 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. @@ -7229,7 +7498,7 @@ cp_parser_conversion_type_id (cp_parser* parser) { tree attributes; tree type_specifiers; - tree declarator; + cp_declarator *declarator; /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); @@ -7250,10 +7519,9 @@ cp_parser_conversion_type_id (cp_parser* parser) conversion-declarator: ptr-operator conversion-declarator [opt] - Returns a representation of the declarator. See - cp_parser_declarator for details. */ + */ -static tree +static cp_declarator * cp_parser_conversion_declarator_opt (cp_parser* parser) { enum tree_code code; @@ -7268,27 +7536,27 @@ cp_parser_conversion_declarator_opt (cp_parser* parser) /* 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, + 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 - declarator = make_reference_declarator (cv_qualifier_seq, + else 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 declarator; } - return NULL_TREE; + return NULL; } /* Parse an (optional) ctor-initializer. @@ -7812,13 +8080,14 @@ cp_parser_template_parameter_list (cp_parser* parser) { tree parameter; cp_token *token; + bool is_non_type; /* Parse the template-parameter. */ - parameter = cp_parser_template_parameter (parser); + parameter = cp_parser_template_parameter (parser, &is_non_type); /* Add it to the list. */ parameter_list = process_template_parm (parameter_list, - parameter); - + parameter, + is_non_type); /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If it's not a `,', we're done. */ @@ -7838,13 +8107,17 @@ cp_parser_template_parameter_list (cp_parser* parser) parameter-declaration Returns a TREE_LIST. The TREE_VALUE represents the parameter. The - TREE_PURPOSE is the default value, if any. */ + 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) +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. */ @@ -7886,9 +8159,16 @@ cp_parser_template_parameter (cp_parser* parser) 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); + *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. @@ -8769,7 +9049,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) } else { - tree declarator; + cp_declarator *declarator; tree decl; /* Parse the declarator. */ @@ -8779,7 +9059,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) /*parenthesized_p=*/NULL); cp_parser_check_for_definition_in_return_type (declarator, declares_class_or_enum); - if (declarator != error_mark_node) + if (declarator != cp_error_declarator) { decl = grokdeclarator (declarator, decl_specifiers, NORMAL, 0, NULL); @@ -10098,7 +10378,7 @@ cp_parser_init_declarator (cp_parser* parser, bool* function_definition_p) { cp_token *token; - tree declarator; + cp_declarator *declarator; tree attributes; tree asm_specification; tree initializer; @@ -10131,7 +10411,7 @@ cp_parser_init_declarator (cp_parser* parser, /* If the DECLARATOR was erroneous, there's no need to go further. */ - if (declarator == error_mark_node) + if (declarator == cp_error_declarator) return error_mark_node; cp_parser_check_for_definition_in_return_type (declarator, @@ -10373,26 +10653,6 @@ cp_parser_init_declarator (cp_parser* parser, 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 @@ -10410,14 +10670,14 @@ cp_parser_init_declarator (cp_parser* parser, If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff the declarator is a direct-declarator of the form "(...)". */ -static tree +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; - tree declarator; + cp_declarator *declarator; enum tree_code code; tree cv_qualifier_seq; tree class_type; @@ -10461,18 +10721,19 @@ cp_parser_declarator (cp_parser* parser, case where the dependent declarator is absent. */ if (dcl_kind != CP_PARSER_DECLARATOR_NAMED && !cp_parser_parse_definitely (parser)) - declarator = NULL_TREE; + declarator = NULL; /* Build the representation of the ptr-operator. */ - if (code == INDIRECT_REF) + 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); - /* Handle the pointer-to-member case. */ - if (class_type) - declarator = build_nt (SCOPE_REF, class_type, declarator); } /* Everything else is a direct-declarator. */ else @@ -10484,8 +10745,8 @@ cp_parser_declarator (cp_parser* parser, ctor_dtor_or_conv_p); } - if (attributes && declarator != error_mark_node) - declarator = tree_cons (attributes, declarator, NULL_TREE); + if (attributes && declarator != cp_error_declarator) + declarator->attributes = attributes; return declarator; } @@ -10515,24 +10776,15 @@ cp_parser_declarator (cp_parser* parser, 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. + 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 +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; - tree declarator = NULL_TREE; + 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; @@ -10585,7 +10837,7 @@ cp_parser_direct_declarator (cp_parser* parser, if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { - tree params; + cp_parameter_declarator *params; unsigned saved_num_template_parameter_lists; cp_parser_parse_tentatively (parser); @@ -10667,8 +10919,8 @@ cp_parser_direct_declarator (cp_parser* parser, first = false; /* Expect a `)'. */ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) - declarator = error_mark_node; - if (declarator == error_mark_node) + declarator = cp_error_declarator; + if (declarator == cp_error_declarator) break; goto handle_declarator; @@ -10711,37 +10963,40 @@ cp_parser_direct_declarator (cp_parser* parser, /* Look for the closing `]'. */ if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'")) { - declarator = error_mark_node; + declarator = cp_error_declarator; break; } - declarator = build_nt (ARRAY_REF, declarator, bounds, - NULL_TREE, NULL_TREE); + 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); - declarator = cp_parser_declarator_id (parser); + id = 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) + id = error_mark_node; + else if (TREE_CODE (id) != IDENTIFIER_NODE) { cp_parser_error (parser, "expected unqualified-id"); - declarator = error_mark_node; + id = error_mark_node; } } - if (declarator == error_mark_node) - break; + if (id == error_mark_node) + { + declarator = cp_error_declarator; + break; + } - if (TREE_CODE (declarator) == SCOPE_REF - && !current_scope ()) + if (TREE_CODE (id) == SCOPE_REF && !current_scope ()) { - tree scope = TREE_OPERAND (declarator, 0); + 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 @@ -10772,53 +11027,54 @@ cp_parser_direct_declarator (cp_parser* parser, TYPE_CONTEXT (scope), TYPE_IDENTIFIER (scope)); /* Build a new DECLARATOR. */ - declarator = build_nt (SCOPE_REF, - type, - TREE_OPERAND (declarator, 1)); + id = build_nt (SCOPE_REF, type, TREE_OPERAND (id, 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 ()))) + declarator = make_id_declarator (id); + if (id) { - tree unqualified_name; tree class_type; + tree unqualified_name; - /* Get the unqualified part of the name. */ - if (TREE_CODE (declarator) == SCOPE_REF) + if (TREE_CODE (id) == SCOPE_REF + && CLASS_TYPE_P (TREE_OPERAND (id, 0))) { - class_type = TREE_OPERAND (declarator, 0); - unqualified_name = TREE_OPERAND (declarator, 1); + class_type = TREE_OPERAND (id, 0); + unqualified_name = TREE_OPERAND (id, 1); } else { class_type = current_class_type; - unqualified_name = declarator; + unqualified_name = id; } - /* 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); - } + 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:; @@ -10829,9 +11085,7 @@ cp_parser_direct_declarator (cp_parser* parser, 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))) + || (declarator && declarator->kind == cdk_id)) /* Default args are only allowed on function declarations. */ parser->default_arg_ok_p = saved_default_arg_ok_p; @@ -11078,7 +11332,7 @@ static tree cp_parser_type_id (cp_parser* parser) { tree type_specifier_seq; - tree abstract_declarator; + cp_declarator *abstract_declarator; /* Parse the type-specifier-seq. */ type_specifier_seq @@ -11094,10 +11348,9 @@ cp_parser_type_id (cp_parser* parser) /*parenthesized_p=*/NULL); /* Check to see if there really was a declarator. */ if (!cp_parser_parse_definitely (parser)) - abstract_declarator = NULL_TREE; + abstract_declarator = NULL; - return groktypename (build_tree_list (type_specifier_seq, - abstract_declarator)); + return groktypename (type_specifier_seq, abstract_declarator); } /* Parse a type-specifier-seq. @@ -11168,19 +11421,17 @@ cp_parser_type_specifier_seq (cp_parser* parser) 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. */ + Returns a representation for the parameter declarations. A return + value of NULL indicates a parameter-declaration-clause consisting + only of an ellipsis. */ -static tree +static cp_parameter_declarator * cp_parser_parameter_declaration_clause (cp_parser* parser) { - tree parameters; + 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); @@ -11189,7 +11440,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) { /* Consume the `...' token. */ cp_lexer_consume_token (parser->lexer); - return NULL_TREE; + return NULL; } else if (token->type == CPP_CLOSE_PAREN) /* There are no parameters. */ @@ -11197,10 +11448,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) #ifndef NO_IMPLICIT_EXTERN_C if (in_system_header && current_class_type == NULL && current_lang_name == lang_name_c) - return NULL_TREE; + return NULL; else #endif - return void_list_node; + return no_parameters; } /* Check for `(void)', too, which is a special case. */ else if (token->keyword == RID_VOID @@ -11210,16 +11461,16 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) /* Consume the `void' token. */ cp_lexer_consume_token (parser->lexer); /* There are no parameters. */ - return void_list_node; + return no_parameters; } /* Parse the parameter-declaration-list. */ - parameters = cp_parser_parameter_declaration_list (parser); + 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 (parameters == error_mark_node) - return error_mark_node; + if (is_error) + return NULL; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -11245,7 +11496,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) ellipsis_p = false; /* Finish the parameter list. */ - return finish_parmlist (parameters, ellipsis_p); + if (parameters && ellipsis_p) + parameters->ellipsis_p = true; + + return parameters; } /* Parse a parameter-declaration-list. @@ -11256,17 +11510,22 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) 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. */ + `void_list_node' is never appended to the list. Upon return, + *IS_ERROR will be true iff an error occurred. */ -static tree -cp_parser_parameter_declaration_list (cp_parser* parser) +static cp_parameter_declarator * +cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) { - tree parameters = NULL_TREE; + cp_parameter_declarator *parameters = NULL; + cp_parameter_declarator **tail = ¶meters; + + /* Assume all will go well. */ + *is_error = false; /* Look for more parameters. */ while (true) { - tree parameter; + cp_parameter_declarator *parameter; bool parenthesized_p; /* Parse the parameter. */ parameter @@ -11276,14 +11535,15 @@ cp_parser_parameter_declaration_list (cp_parser* parser) /* If a parse error occurred parsing the parameter declaration, then the entire parameter-declaration-list is erroneous. */ - if (parameter == error_mark_node) + if (!parameter) { - parameters = error_mark_node; + *is_error = true; + parameters = NULL; break; } /* Add the new parameter to the list. */ - TREE_CHAIN (parameter) = parameters; - parameters = parameter; + *tail = parameter; + tail = ¶meter->next; /* Peek at the next token. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN) @@ -11338,8 +11598,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser) } } - /* We built up the list in reverse order; straighten it out now. */ - return nreverse (parameters); + return parameters; } /* Parse a parameter declaration. @@ -11355,16 +11614,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser) 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)". */ + 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 tree +static cp_parameter_declarator * cp_parser_parameter_declaration (cp_parser *parser, bool template_parm_p, bool *parenthesized_p) @@ -11373,9 +11627,8 @@ cp_parser_parameter_declaration (cp_parser *parser, bool greater_than_is_operator_p; tree decl_specifiers; tree attributes; - tree declarator; + cp_declarator *declarator; tree default_argument; - tree parameter; cp_token *token; const char *saved_message; @@ -11405,7 +11658,7 @@ cp_parser_parameter_declaration (cp_parser *parser, if (cp_parser_error_occurred (parser)) { parser->type_definition_forbidden_message = saved_message; - return error_mark_node; + return NULL; } /* Peek at the next token. */ @@ -11418,7 +11671,7 @@ cp_parser_parameter_declaration (cp_parser *parser, || token->type == CPP_ELLIPSIS || token->type == CPP_GREATER) { - declarator = NULL_TREE; + declarator = NULL; if (parenthesized_p) *parenthesized_p = false; } @@ -11596,11 +11849,10 @@ cp_parser_parameter_declaration (cp_parser *parser, /* 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; + return make_parameter_declarator (decl_specifiers, + declarator, + default_argument); } /* Parse a function-body. @@ -12744,7 +12996,9 @@ cp_parser_member_declaration (cp_parser* parser) attributes = chainon (prefix_attributes, attributes); /* Create the bitfield declaration. */ - decl = grokbitfield (identifier, + decl = grokbitfield (identifier + ? make_id_declarator (identifier) + : NULL, decl_specifiers, width); /* Apply the attributes. */ @@ -12752,7 +13006,7 @@ cp_parser_member_declaration (cp_parser* parser) } else { - tree declarator; + cp_declarator *declarator; tree initializer; tree asm_specification; int ctor_dtor_or_conv_p; @@ -12765,7 +13019,7 @@ cp_parser_member_declaration (cp_parser* parser) /* If something went wrong parsing the declarator, make sure that we at least consume some tokens. */ - if (declarator == error_mark_node) + if (declarator == cp_error_declarator) { /* Skip to the end of the statement. */ cp_parser_skip_to_end_of_statement (parser); @@ -12815,7 +13069,7 @@ cp_parser_member_declaration (cp_parser* parser) 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) + if (declarator->kind == cdk_function) initializer = cp_parser_pure_specifier (parser); else /* Parse the initializer. */ @@ -13352,8 +13606,9 @@ cp_parser_handler (cp_parser* parser) static tree cp_parser_exception_declaration (cp_parser* parser) { + tree decl; tree type_specifiers; - tree declarator; + cp_declarator *declarator; const char *saved_message; /* If it's an ellipsis, it's easy to handle. */ @@ -13373,7 +13628,7 @@ cp_parser_exception_declaration (cp_parser* parser) 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; + declarator = NULL; else declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, /*ctor_dtor_or_conv_p=*/NULL, @@ -13382,7 +13637,16 @@ cp_parser_exception_declaration (cp_parser* parser) /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; - return start_handler_parms (type_specifiers, declarator); + 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. @@ -14028,73 +14292,68 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p) static bool cp_parser_check_declarator_template_parameters (cp_parser* parser, - tree declarator) + cp_declarator *declarator) { unsigned num_templates; /* We haven't seen any classes that involve template parameters yet. */ num_templates = 0; - switch (TREE_CODE (declarator)) + switch (declarator->kind) { - 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 struct S{}; - template <> struct S { void f(); }; - void S::f () {} - - is correct; there shouldn't be a `template <>' for - the definition of `S::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; + case cdk_id: + if (TREE_CODE (declarator->u.id.name) == SCOPE_REF) + { + tree scope; + tree member; - scope = TYPE_CONTEXT (scope); - } - } + scope = TREE_OPERAND (declarator->u.id.name, 0); + member = TREE_OPERAND (declarator->u.id.name, 1); - /* Fall through. */ + 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 struct S{}; + template <> struct S { void f(); }; + void S::f () {} + + is correct; there shouldn't be a `template <>' for + the definition of `S::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); + } + } - default: /* If the DECLARATOR has the form `X' then it uses one additional level of template parameters. */ - if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) + 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; } } @@ -14403,15 +14662,17 @@ cp_parser_function_definition_from_specifiers_and_declarator (cp_parser* parser, tree decl_specifiers, tree attributes, - tree declarator) + const cp_declarator *declarator) { tree fn; bool success_p; /* Begin the function-definition. */ - success_p = begin_function_definition (decl_specifiers, - attributes, - declarator); + 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 @@ -14421,8 +14682,7 @@ cp_parser_function_definition_from_specifiers_and_declarator if (!success_p) { - /* If begin_function_definition didn't like the definition, skip - the entire function. */ + /* Skip the entire function. */ error ("invalid function declaration"); cp_parser_skip_to_end_of_block_or_statement (parser); fn = error_mark_node; @@ -14707,7 +14967,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type) static tree cp_parser_save_member_function_body (cp_parser* parser, tree decl_specifiers, - tree declarator, + cp_declarator *declarator, tree attributes) { cp_token_cache *cache; @@ -14881,8 +15141,8 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) /* 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); + 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, @@ -15050,7 +15310,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) type); /* Call grokdeclarator to figure out what type this is. */ - expr = grokdeclarator (NULL_TREE, + expr = grokdeclarator (NULL, type, TYPENAME, /*initialized=*/0, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1e23acbcf07..e451a29fc20 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2161,21 +2161,20 @@ reduce_template_parm_level (tree index, tree type, int levels) } /* Process information from new template parameter NEXT and append it to the - LIST being built. */ + 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) +process_template_parm (tree list, tree next, bool is_non_type) { tree parm; tree decl = 0; tree defval; - int is_type, idx; + int 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) { @@ -2190,12 +2189,10 @@ process_template_parm (tree list, tree next) else idx = 0; - if (!is_type) + if (is_non_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); + parm = TREE_VALUE (parm); + SET_DECL_TEMPLATE_PARM_P (parm); /* [temp.param] @@ -2222,7 +2219,7 @@ process_template_parm (tree list, tree next) else { tree t; - parm = TREE_VALUE (parm); + parm = TREE_VALUE (TREE_VALUE (parm)); if (parm && TREE_CODE (parm) == TEMPLATE_DECL) { @@ -3757,7 +3754,7 @@ convert_template_argument (tree parm, } } else - val = groktypename (arg); + val = arg; } else { @@ -6600,9 +6597,6 @@ tsubst_call_declarator_parms (tree parms, 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; } @@ -6852,7 +6846,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) case TREE_LIST: { - tree purpose, value, chain, result; + tree purpose, value, chain; if (t == void_list_node) return t; @@ -6882,14 +6876,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) && 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; + return hash_tree_cons (purpose, value, chain); } case TREE_VEC: if (type != NULL_TREE) @@ -7179,20 +7166,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } 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 CALL_EXPR: + abort (); case ARRAY_REF: { @@ -7204,21 +7180,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) return build_nt (ARRAY_REF, e1, e2, NULL_TREE, NULL_TREE); } - 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); @@ -8306,6 +8267,7 @@ tsubst_copy_and_build (tree t, (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: @@ -11198,7 +11160,7 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok) /* Set up context. */ import_export_decl (d); - start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED); + start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED); /* Create substitution entries for the parameters. */ subst_decl = DECL_TEMPLATE_RESULT (template_for_substitution (d)); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 9e4b884c3b3..0d4f4a75a97 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1900,23 +1900,6 @@ finish_fname (tree id) 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 @@ -1998,24 +1981,6 @@ check_template_template_default_arg (tree argument) 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 -- 2.30.2