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