30th Cygnus<->FSF merge.

From-SVN: r6859
This commit is contained in:
Mike Stump 1994-03-23 23:33:53 +00:00
parent d7a58f30d1
commit 51c184be09
24 changed files with 1728 additions and 1109 deletions

View File

@ -44,10 +44,9 @@ X_CPPFLAGS =
T_CPPFLAGS =
CC = cc
# CYGNUS LOCAL: we use byacc instead of bison, DO NOT SEND TO RMS
BISON = `if [ -f ../../byacc/byacc ] ; then echo ../../byacc/byacc ; else echo byacc ; fi`
BISON = bison
BISONFLAGS =
LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ; else echo flex ; fi`
LEX = flex
LEXFLAGS=
AR = ar
OLDAR_FLAGS = qc
@ -204,7 +203,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h lex.h
`echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
@echo expect 28 shift/reduce conflicts, 14 reduce/reduce conflicts.
@echo expect 24 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h

View File

@ -39,7 +39,7 @@ extern int inhibit_warnings;
extern int flag_assume_nonnull_objects;
extern tree ctor_label, dtor_label;
/* From cp-typeck.c: */
/* From typeck.c: */
extern tree unary_complex_lvalue ();
/* Compute the ease with which a conversion can be performed
@ -2821,6 +2821,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
cp_error ("call to destructor for non-type `%D'", name);
return void_zero_node;
}
if (basetype != TREE_TYPE(instance))
basetype = TREE_TYPE(instance);
if (! TYPE_HAS_DESTRUCTOR (basetype))
return void_zero_node;
instance = default_conversion (instance);
@ -3096,6 +3098,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
t = TREE_TYPE (TREE_VALUE (parm));
}
if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
&& TREE_CODE (t) == METHOD_TYPE)
{
TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
}
if (TREE_CODE (t) == ARRAY_TYPE)
{
/* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.

View File

@ -83,7 +83,7 @@ tree the_null_vtable_entry;
/* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack;
static int current_lang_stacksize;
int current_lang_stacksize;
/* Names of languages we recognize. */
tree lang_name_c, lang_name_cplusplus;
@ -94,7 +94,7 @@ tree current_lang_name;
via this node. */
static tree base_layout_decl;
/* Variables shared between cp-class.c and cp-call.c. */
/* Variables shared between class.c and call.c. */
int n_vtables = 0;
int n_vtable_entries = 0;
@ -471,7 +471,8 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
NULL_PTR);
}
assemble_external (vtbl);
if (!flag_vtable_hack)
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
/* Save the intermediate result in a SAVE_EXPR so we don't have to
@ -777,7 +778,8 @@ prepare_fresh_vtable (binfo, base_binfo, for_type)
/* Access the virtual function table entry that logically
contains BASE_FNDECL. VIRTUALS is the virtual function table's
initializer. */
initializer. We can run off the end, when dealing with virtual
destructors in MI situations, return NULL_TREE in that case. */
static tree
get_vtable_entry (virtuals, base_fndecl)
tree virtuals, base_fndecl;
@ -794,7 +796,7 @@ get_vtable_entry (virtuals, base_fndecl)
n_vtable_searches += i;
#endif
while (i > 0)
while (i > 0 && virtuals)
{
virtuals = TREE_CHAIN (virtuals);
i -= 1;
@ -1276,13 +1278,15 @@ modify_vtable_entries (t, fndecl, base_fndecl, pfn)
prepare_fresh_vtable (binfo, base, t);
}
saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl))), 0);
saved_pfn = get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl);
if (saved_pfn)
saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (saved_pfn)), 0);
#ifdef NOTQUITE
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
#endif
/* The this_offset can be wrong, if we try and modify an entry
that had been modified once before. */
if (! SAME_FN (saved_pfn, fndecl))
if (saved_pfn && ! SAME_FN (saved_pfn, fndecl))
{
modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl),
build_vtable_entry (this_offset, pfn),
@ -1738,12 +1742,15 @@ alter_access (t, fdecl, access)
return 0;
}
static tree
/* Return the offset to the main vtable for a given base BINFO. */
tree
get_vfield_offset (binfo)
tree binfo;
{
return size_binop (PLUS_EXPR,
DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
size_binop (FLOOR_DIV_EXPR,
DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
size_int (BITS_PER_UNIT)),
BINFO_OFFSET (binfo));
}
@ -2148,6 +2155,22 @@ finish_base_struct (t, b, t_binfo)
b->cant_synth_copy_ctor = 1;
}
}
{
tree v = get_vbase_types (t_binfo);
for (; v; v = TREE_CHAIN (v))
{
tree basetype = BINFO_TYPE (v);
if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2)
{
if (extra_warnings)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
b->cant_synth_asn_ref = 1;
b->cant_synth_copy_ctor = 1;
}
}
}
{
tree vfields;
@ -2726,7 +2749,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
enum tree_code code = TREE_CODE (t);
register tree x, last_x, method_vec;
int needs_virtual_dtor;
tree name = TYPE_NAME (t), fields, fn_fields, tail;
tree name = TYPE_NAME (t), fields, fn_fields, *tail;
tree *tail_user_methods = &CLASSTYPE_METHODS (t);
enum access_type access;
int all_virtual;
int has_virtual;
@ -2902,8 +2926,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
CLASSTYPE_VFIELDS (t) = vfields;
CLASSTYPE_VFIELD (t) = vfield;
fn_fields = NULL_TREE;
tail = NULL_TREE;
tail = &fn_fields;
if (last_x && list_of_fieldlists)
TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
@ -2961,11 +2984,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x);
if (! fn_fields)
fn_fields = x;
else
TREE_CHAIN (tail) = x;
tail = x;
/* Link x onto end of fn_fields and CLASSTYPE_METHODS. */
*tail = x;
tail = &TREE_CHAIN (x);
*tail_user_methods = x;
tail_user_methods = &DECL_NEXT_METHOD (x);
#if 0
/* ??? What if we have duplicate declarations
@ -3284,8 +3307,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
}
if (tail) TREE_CHAIN (tail) = NULL_TREE;
/* If this type has any constant members which did not come
with their own initialization, mark that fact here. It is
not an error here, since such types can be saved either by their
@ -3306,11 +3327,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_NEEDS_DESTRUCTOR (t) = 0;
else
{
if (! fn_fields)
fn_fields = dtor;
else
TREE_CHAIN (tail) = dtor;
tail = dtor;
/* Link dtor onto end of fn_fields. */
*tail = dtor;
tail = &TREE_CHAIN (dtor);
if (DECL_VINDEX (dtor) == NULL_TREE
&& ! CLASSTYPE_DECLARED_EXCEPTION (t)
@ -3325,6 +3344,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
}
*tail = NULL_TREE;
*tail_user_methods = NULL_TREE;
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
/* Synthesize any needed methods. Note that methods will be synthesized

View File

@ -149,7 +149,7 @@ struct candidate
};
int rank_for_overload ();
/* Variables shared between cp-class.c and cp-call.c. */
/* Variables shared between class.c and call.c. */
extern int n_vtables;
extern int n_vtable_entries;

View File

@ -259,6 +259,11 @@ extern int flag_signed_bitfields;
extern int write_virtuals;
/* True if we want output of vtables to be controlled by whether
we seen the class's first non-inline virtual function.
0 is old behavior; 1 is new behavior. */
extern flag_vtable_hack;
/* INTERFACE_ONLY nonzero means that we are in an "interface"
section of the compiler. INTERFACE_UNKNOWN nonzero means
we cannot trust the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN
@ -486,6 +491,8 @@ struct lang_type
union tree_node *dossier;
union tree_node *methods;
union tree_node *signature;
union tree_node *signature_pointer_to;
union tree_node *signature_reference_to;
@ -604,6 +611,10 @@ struct lang_type
/* The is the VAR_DECL that contains NODE's dossier. */
#define CLASSTYPE_DOSSIER(NODE) (TYPE_LANG_SPECIFIC(NODE)->dossier)
/* List of all explicit methods (chained using DECL_NEXT_METHOD),
in order they were parsed. */
#define CLASSTYPE_METHODS(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
#define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded)
@ -927,7 +938,7 @@ struct lang_decl
struct template_info *template_info;
tree main_decl_variant;
struct pending_inline *pending_inline_info;
tree vbase_init_list;
tree next_method;
tree chain;
};
@ -1007,6 +1018,9 @@ struct lang_decl
#define DECL_CHAIN(NODE) (TREE_CHAIN (NODE))
#endif
/* Next method in CLASSTYPE_METHODS list. */
#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method)
/* Points back to the decl which caused this lang_decl to be allocated. */
#define DECL_MAIN_VARIANT(NODE) (DECL_LANG_SPECIFIC(NODE)->main_decl_variant)
@ -1024,11 +1038,6 @@ struct lang_decl
which this signature member function pointer was created. */
#define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to)
/* Holds information about how virtual base classes should be initialized
by this constructor *if* this constructor is the one to perform
such initialization. */
#define DECL_VBASE_INIT_LIST(NODE) (DECL_LANG_SPECIFIC(NODE)->vbase_init_list)
/* For a TEMPLATE_DECL: template-specific information. */
#define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->template_info)
@ -1218,7 +1227,7 @@ struct lang_decl
#define DECL_TEMPLATE_IS_CLASS(NODE) (DECL_RESULT(NODE) == NULL_TREE)
#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
/* For class templates. */
#define DECL_TEMPLATE_MEMBERS(NODE) DECL_INITIAL(NODE)
#define DECL_TEMPLATE_MEMBERS(NODE) DECL_SIZE(NODE)
/* For function, method, class-data templates. */
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE)
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
@ -1279,7 +1288,7 @@ extern tree truthvalue_conversion PROTO((tree));
extern tree type_for_mode PROTO((enum machine_mode, int));
extern tree type_for_size PROTO((unsigned, int));
/* in cp-decl{2}.c */
/* in decl{2}.c */
extern tree void_list_node;
extern tree void_zero_node;
extern tree default_function_type;
@ -1319,12 +1328,12 @@ extern tree long_long_integer_type_node, long_long_unsigned_type_node;
/* For building calls to `delete'. */
extern tree integer_two_node, integer_three_node;
/* in cp-except.c */
/* in except.c */
extern tree current_exception_type;
extern tree current_exception_decl;
extern tree current_exception_object;
/* in cp-pt.c */
/* in pt.c */
/* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or
PARM_DECLs. BINDINGS, if non-null, is a vector of bindings for those
parameters. */
@ -1358,7 +1367,7 @@ struct tinst_level
extern struct tinst_level *current_tinst_level;
/* in cp-class.c */
/* in class.c */
extern tree current_class_name;
extern tree current_class_type;
extern tree previous_class_type;
@ -1372,7 +1381,7 @@ extern tree original_function_name;
extern tree current_class_name, current_class_type, current_class_decl, C_C_D;
extern tree current_vtable_decl;
/* in cp-init.c */
/* in init.c */
extern tree global_base_init_list;
extern tree current_base_init_list, current_member_init_list;
@ -1568,7 +1577,7 @@ enum access_type {
access_private_virtual
};
/* in cp-lex.c */
/* in lex.c */
extern tree current_unit_name, current_unit_language;
/* Things for handling inline functions. */
@ -1590,7 +1599,7 @@ struct pending_inline
unsigned int interface : 2; /* 0=interface 1=unknown 2=implementation */
};
/* in cp-method.c */
/* in method.c */
extern struct pending_inline *pending_inlines;
/* 1 for -fall-virtual: make every member function (except
@ -1695,7 +1704,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
(TEMPLATE_CONST_TPARMLIST (NODE) = saved_parmlist, \
TEMPLATE_CONST_IDX (NODE) = I)
/* in cp-lex.c */
/* in lex.c */
/* Indexed by TREE_CODE, these tables give C-looking names to
operators represented by TREE_CODES. For example,
opname_tab[(int) MINUS_EXPR] == "-". */
@ -1706,7 +1715,7 @@ extern tree convert_and_check PROTO((tree, tree));
extern void overflow_warning PROTO((tree));
extern void unsigned_conversion_warning PROTO((tree, tree));
/* in cp-call.c */
/* in call.c */
extern struct candidate *ansi_c_bullshit;
extern int rank_for_overload PROTO((struct candidate *, struct candidate *));
@ -1721,12 +1730,13 @@ extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *
extern tree build_overload_call PROTO((tree, tree, int, struct candidate *));
extern tree build_overload_call_maybe PROTO((tree, tree, int, struct candidate *));
/* in cp-class.c */
/* in class.c */
extern tree build_vbase_pointer PROTO((tree, tree));
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
extern tree build_vtable_entry PROTO((tree, tree));
extern tree build_vfn_ref PROTO((tree *, tree, tree));
extern void add_method PROTO((tree, tree *, tree));
extern tree get_vfield_offset PROTO((tree));
extern void duplicate_tag_error PROTO((tree));
extern tree finish_struct PROTO((tree, tree, int));
extern int resolves_to_fixed_type_p PROTO((tree, int *));
@ -1742,7 +1752,7 @@ extern tree instantiate_type PROTO((tree, tree, int));
extern void print_class_statistics PROTO((void));
extern void maybe_push_cache_obstack PROTO((void));
/* in cp-cvt.c */
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, tree, tree, int, char *, int, int));
extern tree convert_from_reference PROTO((tree));
extern tree convert_to_aggr PROTO((tree, tree, char **, int));
@ -1755,7 +1765,7 @@ extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *));
/* cp-decl.c */
/* decl.c */
extern int global_bindings_p PROTO((void));
extern void keep_next_level PROTO((void));
extern int kept_level_p PROTO((void));
@ -1833,7 +1843,7 @@ extern void pop_implicit_try_blocks PROTO((tree));
extern void push_exception_cleanup PROTO((tree));
extern void revert_static_member_fn PROTO((tree *, tree *, tree *));
/* in cp-decl2.c */
/* in decl2.c */
extern int lang_decode_option PROTO((char *));
extern tree grok_method_quals PROTO((tree, tree, tree));
extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree));
@ -1844,7 +1854,7 @@ extern void check_classfn PROTO((tree, tree, tree));
extern tree grokfield PROTO((tree, tree, tree, tree, tree));
extern tree grokbitfield PROTO((tree, tree, tree));
extern tree groktypefield PROTO((tree, tree));
extern tree grokoptypename PROTO((tree, int));
extern tree grokoptypename PROTO((tree, tree));
extern tree build_push_scope PROTO((tree, tree));
extern tree constructor_name_full PROTO((tree));
extern tree constructor_name PROTO((tree));
@ -1862,10 +1872,14 @@ extern void walk_vtables PROTO((void (*)(), void (*)()));
extern void finish_file PROTO((void));
extern void warn_if_unknown_interface PROTO((void));
extern tree grok_x_components PROTO((tree, tree));
extern tree reparse_absdcl_as_expr PROTO((tree, tree));
extern tree reparse_absdcl_as_casts PROTO((tree, tree));
extern tree reparse_decl_as_expr PROTO((tree, tree));
extern tree finish_decl_parsing PROTO((tree));
/* in cp-edsel.c */
/* in edsel.c */
/* in cp-except.c */
/* in except.c */
extern tree lookup_exception_cname PROTO((tree, tree, tree));
extern tree lookup_exception_tname PROTO((tree));
extern tree lookup_exception_object PROTO((tree, tree, int));
@ -1888,13 +1902,13 @@ extern void setup_exception_throw_decl PROTO((void));
extern void init_exception_processing PROTO((void));
extern void init_exception_processing_1 PROTO((void));
/* in cp-expr.c */
/* in expr.c */
/* skip cplus_expand_expr */
extern void init_cplus_expand PROTO((void));
extern void fixup_result_decl PROTO((tree, struct rtx_def *));
extern int decl_in_memory_p PROTO((tree));
/* in cp-gc.c */
/* in gc.c */
extern int type_needs_gc_entry PROTO((tree));
extern int value_safe_from_gc PROTO((tree, tree));
extern void build_static_gc_entry PROTO((tree, tree));
@ -1911,7 +1925,7 @@ extern tree build_typeid PROTO((tree));
extern tree get_typeid PROTO((tree));
extern tree build_dynamic_cast PROTO((tree, tree));
/* in cp-init.c */
/* in init.c */
extern void emit_base_init PROTO((tree, int));
extern void check_base_init PROTO((tree));
extern tree build_virtual_init PROTO((tree, tree, tree));
@ -1941,9 +1955,9 @@ extern tree build_delete PROTO((tree, tree, tree, int, int));
extern tree build_vbase_delete PROTO((tree, tree));
extern tree build_vec_delete PROTO((tree, tree, tree, tree, tree, tree));
/* in cp-input.c */
/* in input.c */
/* in cp-lex.c */
/* in lex.c */
extern tree make_pointer_declarator PROTO((tree, tree));
extern tree make_reference_declarator PROTO((tree, tree));
extern char *operator_name_string PROTO((tree));
@ -1986,7 +2000,7 @@ extern void dump_time_statistics PROTO((void));
extern void compiler_error_with_decl PROTO((tree, char *));
extern void yyerror PROTO((char *));
/* in cp-error.c */
/* in error.c */
extern void init_error PROTO((void));
extern char *fndecl_as_string PROTO((tree, tree, int));
extern char *type_as_string PROTO((tree, int));
@ -1998,7 +2012,7 @@ extern char *language_as_string PROTO((enum languages, int));
extern char *parm_as_string PROTO((int, int));
extern char *op_as_string PROTO((enum tree_code, int));
/* in cp-method.c */
/* in method.c */
extern void init_method PROTO((void));
extern tree make_anon_parm_name PROTO((void));
extern void clear_anon_parm_name PROTO((void));
@ -2017,11 +2031,11 @@ extern tree build_opfncall PROTO((enum tree_code, int, tree, tree, tree));
extern tree hack_identifier PROTO((tree, tree, int));
extern tree build_component_type_expr PROTO((tree, tree, tree, int));
/* in cp-pt.c */
/* in pt.c */
extern void begin_template_parm_list PROTO((void));
extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
extern void end_template_decl PROTO((tree, tree, tree));
extern void end_template_decl PROTO((tree, tree, tree, int));
extern tree lookup_template_class PROTO((tree, tree, tree));
extern void push_template_decls PROTO((tree, tree, int));
extern void pop_template_decls PROTO((tree, tree, int));
@ -2039,7 +2053,7 @@ extern void do_pending_templates PROTO((void));
struct tinst_level *tinst_for_decl PROTO((void));
extern void do_function_instantiation PROTO((tree, tree));
/* in cp-search.c */
/* in search.c */
extern tree make_memoized_table_entry PROTO((tree, tree, int));
extern void push_memoized_context PROTO((tree, int));
extern void pop_memoized_context PROTO((int));
@ -2075,7 +2089,7 @@ extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void));
/* in cp-sig.c */
/* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int));
extern tree build_signature_reference_type PROTO((tree, int, int));
extern tree build_signature_pointer_constructor PROTO((tree, tree));
@ -2084,12 +2098,12 @@ extern tree build_optr_ref PROTO((tree));
extern tree build_sptr_ref PROTO((tree));
extern tree build_vptr_ref PROTO((tree));
/* in cp-spew.c */
/* in spew.c */
extern void init_spew PROTO((void));
extern int yylex PROTO((void));
extern tree arbitrate_lookup PROTO((tree, tree, tree));
/* in cp-tree.c */
/* in tree.c */
extern int lvalue_p PROTO((tree));
extern int lvalue_or_else PROTO((tree, char *));
extern tree build_cplus_new PROTO((tree, tree, int));
@ -2135,7 +2149,7 @@ extern void print_lang_statistics PROTO((void));
extern tree array_type_nelts_total PROTO((tree));
extern tree array_type_nelts_top PROTO((tree));
/* in cp-typeck.c */
/* in typeck.c */
extern tree target_type PROTO((tree));
extern tree require_complete_type PROTO((tree));
extern int type_unknown_p PROTO((tree));
@ -2191,7 +2205,7 @@ extern tree c_expand_start_case PROTO((tree));
extern tree build_component_ref PROTO((tree, tree, tree, int));
extern tree build_ptrmemfunc PROTO((tree, tree, int));
/* in cp-type2.c */
/* in typeck2.c */
extern tree error_not_base_type PROTO((tree, tree));
extern tree binfo_or_else PROTO((tree, tree));
extern void error_with_aggr_type (); /* PROTO((tree, char *, HOST_WIDE_INT)); */
@ -2209,7 +2223,7 @@ extern tree build_functional_cast PROTO((tree, tree));
extern char *enum_name_string PROTO((tree, tree));
extern void report_case_error PROTO((int, tree, tree, tree));
/* in cp-xref.c */
/* in xref.c */
extern void GNU_xref_begin PROTO((char *));
extern void GNU_xref_end PROTO((int));
extern void GNU_xref_file PROTO((char *));

View File

@ -581,7 +581,11 @@ build_up_reference (type, arg, flags, checkconst)
if (TYPE_USES_COMPLEX_INHERITANCE (argtype))
{
TREE_TYPE (rval) = TYPE_POINTER_TO (argtype);
rval = convert_pointer_to (target_type, rval);
if (flags & LOOKUP_PROTECT)
rval = convert_pointer_to (target_type, rval);
else
rval
= convert_to_pointer_force (build_pointer_type (target_type), rval);
TREE_TYPE (rval) = type;
}
TREE_CONSTANT (rval) = literal_flag;
@ -1439,18 +1443,16 @@ convert_force (type, expr)
if (code == POINTER_TYPE)
return fold (convert_to_pointer_force (type, e));
/* From cp-typeck.c convert_for_assignment */
/* From typeck.c convert_for_assignment */
if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR
&& TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE)
|| integer_zerop (e))
|| integer_zerop (e)
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
&& TYPE_PTRMEMFUNC_P (type))
{
/* compatible pointer to member functions. */
e = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
if (e == 0)
return error_mark_node;
return digest_init (type, e, (tree *)0);
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
}
{
int old_equiv = flag_int_enum_equivalence;

View File

@ -444,7 +444,7 @@ extern int flag_conserve_space;
extern tree *current_lang_base, *current_lang_stack;
/* C and C++ flags are in cp-decl2.c. */
/* C and C++ flags are in decl2.c. */
/* Set to 0 at beginning of a constructor, set to 1
if that function does an allocation before referencing its
@ -465,7 +465,7 @@ int current_function_obstack_index;
int current_function_obstack_usage;
/* Flag used when debugging cp-spew.c */
/* Flag used when debugging spew.c */
extern int spew_debug;
@ -1471,6 +1471,9 @@ struct saved_scope {
tree class_name, class_type, class_decl, function_decl;
struct binding_level *class_bindings;
tree previous_class_type;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
tree named_labels;
};
static struct saved_scope *current_saved_scope;
extern tree prev_class_type;
@ -1478,6 +1481,7 @@ extern tree prev_class_type;
void
push_to_top_level ()
{
extern int current_lang_stacksize;
struct saved_scope *s =
(struct saved_scope *) xmalloc (sizeof (struct saved_scope));
struct binding_level *b = current_binding_level;
@ -1543,10 +1547,21 @@ push_to_top_level ()
s->function_decl = current_function_decl;
s->class_bindings = class_binding_level;
s->previous_class_type = previous_class_type;
s->lang_stack = current_lang_stack;
s->lang_base = current_lang_base;
s->lang_stacksize = current_lang_stacksize;
s->lang_name = current_lang_name;
s->named_labels = named_labels;
current_class_name = current_class_type = current_class_decl = NULL_TREE;
current_function_decl = NULL_TREE;
class_binding_level = (struct binding_level *)0;
previous_class_type = NULL_TREE;
current_lang_stacksize = 10;
current_lang_stack = current_lang_base
= (tree *) xmalloc (current_lang_stacksize * sizeof (tree));
current_lang_name = lang_name_cplusplus;
strict_prototype = strict_prototypes_lang_cplusplus;
named_labels = NULL_TREE;
s->prev = current_saved_scope;
s->old_bindings = old_bindings;
@ -1556,6 +1571,7 @@ push_to_top_level ()
void
pop_from_top_level ()
{
extern int current_lang_stacksize;
struct saved_scope *s = current_saved_scope;
tree t;
@ -1584,6 +1600,17 @@ pop_from_top_level ()
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
previous_class_type = s->previous_class_type;
free (current_lang_base);
current_lang_base = s->lang_base;
current_lang_stack = s->lang_stack;
current_lang_name = s->lang_name;
current_lang_stacksize = s->lang_stacksize;
if (current_lang_name == lang_name_cplusplus)
strict_prototype = strict_prototypes_lang_cplusplus;
else if (current_lang_name == lang_name_c)
strict_prototype = strict_prototypes_lang_c;
named_labels = s->named_labels;
free (s);
}
@ -1661,7 +1688,7 @@ set_nested_typename (decl, classname, name, type)
incorrect results with `-g' unless they duplicate this code.
This is currently needed mainly for dbxout.c, but we can make
use of it in cp-method.c later as well. */
use of it in method.c later as well. */
tree
make_type_decl (name, type)
tree name, type;
@ -1958,6 +1985,37 @@ decls_match (newdecl, olddecl)
else
types_match = 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL)
{
tree newargs = DECL_TEMPLATE_PARMS (newdecl);
tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
int i, len = TREE_VEC_LENGTH (newargs);
if (TREE_VEC_LENGTH (oldargs) != len)
return 0;
for (i = 0; i < len; i++)
{
tree newarg = TREE_VEC_ELT (newargs, i);
tree oldarg = TREE_VEC_ELT (oldargs, i);
if (TREE_CODE (newarg) != TREE_CODE (oldarg))
return 0;
else if (TREE_CODE (newarg) == IDENTIFIER_NODE)
/* continue */;
else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
return 0;
}
if (DECL_TEMPLATE_IS_CLASS (newdecl)
!= DECL_TEMPLATE_IS_CLASS (olddecl))
types_match = 0;
else if (DECL_TEMPLATE_IS_CLASS (newdecl))
types_match = 1;
else
types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
DECL_TEMPLATE_RESULT (newdecl));
}
else
{
if (TREE_TYPE (newdecl) == error_mark_node)
@ -2028,7 +2086,7 @@ warn_extern_redeclared_static (newdecl, olddecl)
If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
Otherwise, return 0. */
static int
int
duplicate_decls (newdecl, olddecl)
register tree newdecl, olddecl;
{
@ -2038,8 +2096,7 @@ duplicate_decls (newdecl, olddecl)
int new_defines_function;
tree previous_c_decl = NULL_TREE;
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& is_overloaded_fn (olddecl))
if (TREE_CODE (newdecl) == FUNCTION_DECL && is_overloaded_fn (olddecl))
{
olddecl = get_first_fn (olddecl);
@ -2144,6 +2201,8 @@ duplicate_decls (newdecl, olddecl)
cp_error ("declaration of C function `%#D' conflicts with", newdecl);
cp_error_at ("previous declaration `%#D' here", previous_c_decl);
}
else if (!types_match && TREE_CODE (newdecl) == TEMPLATE_DECL)
return 0;
else if (!types_match)
{
tree oldtype = TREE_TYPE (olddecl);
@ -2238,7 +2297,7 @@ duplicate_decls (newdecl, olddecl)
char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
error_with_decl (newdecl, errmsg);
cp_error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
@ -2295,6 +2354,8 @@ duplicate_decls (newdecl, olddecl)
DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
if (DECL_CHAIN (newdecl) == NULL_TREE)
DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
if (DECL_NEXT_METHOD (newdecl) == NULL_TREE)
DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl);
if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
}
@ -2325,6 +2386,10 @@ duplicate_decls (newdecl, olddecl)
#endif
}
if (TREE_CODE (olddecl) == TEMPLATE_DECL
&& DECL_TEMPLATE_INFO (olddecl)->length)
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
/* Special handling ensues if new decl is a function definition. */
new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != NULL_TREE);
@ -2381,7 +2446,8 @@ duplicate_decls (newdecl, olddecl)
layout_type (TREE_TYPE (newdecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL
&& TREE_CODE (newdecl) != TYPE_DECL
&& TREE_CODE (newdecl) != CONST_DECL)
&& TREE_CODE (newdecl) != CONST_DECL
&& TREE_CODE (newdecl) != TEMPLATE_DECL)
layout_decl (newdecl, 0);
}
else
@ -2630,7 +2696,7 @@ pushdecl (x)
cp_error_at ("`%#D' used prior to declaration", x);
}
if (t != NULL_TREE)
else if (t != NULL_TREE)
{
if (TREE_CODE (t) == PARM_DECL)
{
@ -2639,25 +2705,23 @@ pushdecl (x)
}
file = DECL_SOURCE_FILE (t);
line = DECL_SOURCE_LINE (t);
}
if (t != NULL_TREE
&& (TREE_CODE (t) != TREE_CODE (x) || is_overloaded_fn (t)))
{
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
if (TREE_CODE (t) != TREE_CODE (x))
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
get shadowed, and know that if we need to find a TYPE_DECL
for a given name, we can look in the IDENTIFIER_TYPE_VALUE
slot of the identifier. */
;
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
get shadowed, and know that if we need to find a TYPE_DECL
for a given name, we can look in the IDENTIFIER_TYPE_VALUE
slot of the identifier. */
;
}
else if (duplicate_decls (x, t))
return t;
}
else if (duplicate_decls (x, t))
return t;
}
else if (t != NULL_TREE && duplicate_decls (x, t))
{
{
#if 0
/* This is turned off until I have time to do it right (bpk). */
@ -2682,14 +2746,16 @@ pushdecl (x)
}
#endif
/* Due to interference in memory reclamation (X may be
obstack-deallocated at this point), we must guard against
one really special case. */
if (current_function_decl == x)
current_function_decl = t;
return t;
/* Due to interference in memory reclamation (X may be
obstack-deallocated at this point), we must guard against
one really special case. */
if (current_function_decl == x)
current_function_decl = t;
return t;
}
}
/* If declaring a type as a typedef, and the type has no known
typedef name, install this TYPE_DECL as its typedef name. */
@ -3272,7 +3338,7 @@ redeclaration_error_message (newdecl, olddecl)
if (comptypes (newdecl, olddecl, 0))
return 0;
else
return "redefinition of `%s'";
return "redefinition of `%#D'";
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
@ -3294,12 +3360,18 @@ redeclaration_error_message (newdecl, olddecl)
&& !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "`%s' not declared in class";
return "`%#D' not declared in class";
else
return "redefinition of `%s'";
return "redefinition of `%#D'";
}
return 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl))
return "redefinition of `%#D'";
return 0;
}
else if (current_binding_level == global_binding_level)
{
/* Objects declared at top level: */
@ -3309,11 +3381,11 @@ redeclaration_error_message (newdecl, olddecl)
/* Reject two definitions. */
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
return "redefinition of `%s'";
return "redefinition of `%#D'";
/* Now we have two tentative defs, or one tentative and one real def. */
/* Insist that the linkage match. */
if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
return "conflicting declarations of `%s'";
return "conflicting declarations of `%#D'";
return 0;
}
else
@ -3322,7 +3394,7 @@ redeclaration_error_message (newdecl, olddecl)
/* Reject two definitions, and reject a definition
together with an external reference. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
return "redeclaration of `%s'";
return "redeclaration of `%#D'";
return 0;
}
}
@ -3780,8 +3852,7 @@ lookup_nested_type (type, context)
definitions if there are many, or return 0 if it is undefined.
If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
If PREFER_TYPE is = 0, we prefer non-TYPE_DECLs.
If PREFER_TYPE is < 0, we arbitrate according to lexical context. */
Otherwise we prefer non-TYPE_DECLs. */
tree
lookup_name (name, prefer_type)
@ -3840,9 +3911,8 @@ lookup_name (name, prefer_type)
if (val == val_as_type || prefer_type > 0
|| looking_for_typename > 0)
return val_as_type;
if (prefer_type == 0)
return val;
return arbitrate_lookup (name, val, val_as_type);
return val;
}
if (TREE_TYPE (val) == error_mark_node)
return error_mark_node;
@ -5233,7 +5303,7 @@ start_decl (declarator, declspecs, initialized, raises)
my_friendly_abort (13);
}
else if (TREE_CODE (result) == FUNCTION_DECL)
tem = push_overloaded_decl (tem, 0);
/*tem = push_overloaded_decl (tem, 0)*/;
else if (TREE_CODE (result) == VAR_DECL
|| TREE_CODE (result) == TYPE_DECL)
{
@ -6329,9 +6399,17 @@ complete_array_type (type, initial_value, do_default)
if (maxindex)
{
tree itype;
TYPE_DOMAIN (type) = build_index_type (maxindex);
if (!TREE_TYPE (maxindex))
TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
if (initial_value)
itype = TREE_TYPE (initial_value);
else
itype = NULL;
if (itype && !TYPE_DOMAIN (itype))
TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
}
/* Lay out the type now that we can get the real answer. */
@ -6947,8 +7025,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
case IDENTIFIER_NODE:
dname = decl;
name = IDENTIFIER_POINTER (decl);
decl = NULL_TREE;
if (IDENTIFIER_TYPENAME_P (dname))
{
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
return_type = return_conversion;
}
if (IDENTIFIER_OPNAME_P (dname))
name = operator_name_string (dname);
else
name = IDENTIFIER_POINTER (dname);
break;
case RECORD_TYPE:
@ -6965,15 +7055,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
decl = NULL_TREE;
break;
case TYPE_EXPR:
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
name = "operator <typename>"; /* We don't know the type yet. */
/* Go to the absdcl. */
decl = TREE_OPERAND (decl, 0);
return_type = return_conversion;
break;
/* C++ extension */
case SCOPE_REF:
/*
@ -7214,6 +7295,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = void_type_node;
else if (return_type == return_ctor)
type = TYPE_POINTER_TO (ctor_return_type);
else if (return_type == return_conversion)
type = ctor_return_type;
else if (current_class_type
&& IS_SIGNATURE (current_class_type)
&& (RIDBIT_SETP (RID_TYPEDEF, specbits)
@ -7247,6 +7330,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
error ("return type specification for constructor invalid");
type = TYPE_POINTER_TO (ctor_return_type);
}
else if (return_type == return_conversion)
{
if (comp_target_types (type, ctor_return_type, 1) == 0)
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
cp_pedwarn ("return type specified for `operator %T'",
ctor_return_type);
type = ctor_return_type;
}
ctype = NULL_TREE;
@ -7508,11 +7602,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
error ("typedef declaration includes an initializer");
/* To process a class-local typedef declaration, we descend down
the chain of declspecs looking for the `typedef' spec. When we
find it, we splice it out of the chain of declspecs, and then
recursively call `grokdeclarator' with the original declarator
and with the newly adjusted declspecs. This call should return
a FIELD_DECL node with the TREE_TYPE (and other parts) set
the chain of declspecs looking for the `typedef' spec. When
we find it, we replace it with `static', and then recursively
call `grokdeclarator' with the original declarator and with
the newly adjusted declspecs. This call should return a
FIELD_DECL node with the TREE_TYPE (and other parts) set
appropriately. We can then just change the TREE_CODE on that
from FIELD_DECL to TYPE_DECL and we're done. */
@ -7523,11 +7617,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (TREE_VALUE (scanner) == ridpointers[(int) RID_TYPEDEF])
break;
}
if (previous_declspec)
TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF]))
{
if (previous_declspec)
TREE_CHAIN (previous_declspec)
= IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
else
declspecs
= IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
}
else
declspecs = TREE_CHAIN (scanner);
TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC];
/* In the recursive call to grokdeclarator we need to know
whether we are working on a signature-local typedef. */
if (IS_SIGNATURE (current_class_type))
@ -7650,7 +7752,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
qualify the member name.
an ADDR_EXPR (for &...),
a BIT_NOT_EXPR (for destructors)
a TYPE_EXPR (for operator typenames)
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.
@ -7854,7 +7955,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
&& (friendp == 0 || dname == current_class_name))
ctype = current_class_type;
if (ctype && flags == TYPENAME_FLAG)
if (ctype && return_type == return_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
if (ctype && constructor_name (ctype) == dname)
{
@ -7910,17 +8011,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
return void_type_node;
}
{
int inlinep, staticp;
inlinep = RIDBIT_SETP (RID_INLINE, specbits);
staticp = RIDBIT_SETP (RID_STATIC, specbits);
RIDBIT_RESET (RID_INLINE, specbits);
RIDBIT_RESET (RID_STATIC, specbits);
if (RIDBIT_ANY_SET (specbits))
RID_BIT_TYPE tmp_bits;
bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE));
RIDBIT_RESET (RID_INLINE, tmp_bits);
RIDBIT_RESET (RID_STATIC, tmp_bits);
if (RIDBIT_ANY_SET (tmp_bits))
error ("return value type specifier for constructor ignored");
if (inlinep)
RIDBIT_SET (RID_INLINE, specbits);
if (staticp)
RIDBIT_SET (RID_STATIC, specbits);
}
type = TYPE_POINTER_TO (ctype);
if (decl_context == FIELD &&
@ -7982,9 +8078,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
funcdef_p =
(inner_decl &&
(TREE_CODE (inner_decl) == IDENTIFIER_NODE
|| TREE_CODE (inner_decl) == TYPE_EXPR)) ? funcdef_flag : 0;
(inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE)
? funcdef_flag : 0;
/* FIXME: This is where default args should be fully
processed. */
@ -8242,12 +8337,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
return t;
}
if (flags == TYPENAME_FLAG)
cp_error ("type conversion is not a member of structure `%T'", ctype);
else
cp_error
("field `%D' is not a member of structure `%T'",
sname, ctype);
cp_error
("field `%D' is not a member of structure `%T'",
sname, ctype);
}
if (current_class_type)
@ -8283,28 +8375,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
declarator = sname;
}
else if (TREE_CODE (sname) == TYPE_EXPR)
{
/* A TYPE_EXPR will change types out from under us.
So do the TYPE_EXPR now, and make this SCOPE_REF
inner to the TYPE_EXPR's CALL_EXPR.
This does not work if we don't get a CALL_EXPR back.
I did not think about error recovery, hence the
my_friendly_abort. */
/* Get the CALL_EXPR. */
sname = grokoptypename (sname, 0);
my_friendly_assert (TREE_CODE (sname) == CALL_EXPR, 157);
type = TREE_TYPE (TREE_OPERAND (sname, 0));
/* Scope the CALL_EXPR's name. */
TREE_OPERAND (declarator, 1) = TREE_OPERAND (sname, 0);
/* Put the SCOPE_EXPR in the CALL_EXPR's innermost position. */
TREE_OPERAND (sname, 0) = declarator;
/* Now work from the CALL_EXPR. */
declarator = sname;
continue;
}
else if (TREE_CODE (sname) == SCOPE_REF)
my_friendly_abort (17);
else
@ -8329,21 +8399,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
declarator = TREE_OPERAND (declarator, 0);
break;
case TYPE_EXPR:
declarator = grokoptypename (declarator, 0);
if (explicit_int != -1)
{
tree stype = TREE_TYPE (TREE_OPERAND (declarator, 0));
if (comp_target_types (type, stype, 1) == 0)
cp_error ("`operator %T' declared to return `%T'", stype,
type);
else
cp_pedwarn ("return type specified for `operator %T'", type);
}
dname = declarator;
type = TREE_TYPE (TREE_OPERAND (declarator, 0));
break;
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
@ -8667,6 +8722,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
&& ! funcdef_flag
&& RIDBIT_NOTSETP (RID_STATIC, specbits)
&& RIDBIT_NOTSETP (RID_INLINE, specbits)));
if (TREE_CODE (type) == METHOD_TYPE)
publicp
|= (ctype && CLASSTYPE_INTERFACE_KNOWN (ctype))
|| (!funcdef_flag && RIDBIT_NOTSETP (RID_INLINE, specbits));
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
raises, friendp ? -1 : 0, publicp);
@ -8843,8 +8902,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
into some other file, so we don't clear TREE_PUBLIC for them. */
publicp
= ((ctype
&& CLASSTYPE_INTERFACE_KNOWN (ctype)
&& ! CLASSTYPE_INTERFACE_ONLY (ctype))
&& CLASSTYPE_INTERFACE_KNOWN (ctype))
|| !(RIDBIT_SETP (RID_STATIC, specbits)
|| RIDBIT_SETP (RID_INLINE, specbits)));
@ -10212,7 +10270,7 @@ build_enumerator (name, value)
if (value)
STRIP_TYPE_NOPS (value);
/* Make up for hacks in cp-lex.c. */
/* Make up for hacks in lex.c. */
if (value == integer_zero_node)
value = build_int_2 (0, 0);
else if (value == integer_one_node)
@ -10573,7 +10631,9 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
else if (pre_parsed_p == 0)
{
current_function_decl = pushdecl (decl1);
if (TREE_CODE (current_function_decl) == TREE_LIST)
if (TREE_CODE (current_function_decl) == TREE_LIST
|| (DECL_ASSEMBLER_NAME (current_function_decl)
!= DECL_ASSEMBLER_NAME (decl1)))
{
/* @@ revert to modified original declaration. */
decl1 = DECL_MAIN_VARIANT (decl1);

View File

@ -58,7 +58,7 @@ static int temp_name_counter;
can have the same name. */
static int global_temp_name_counter;
/* Flag used when debugging cp-spew.c */
/* Flag used when debugging spew.c */
extern int spew_debug;
@ -129,6 +129,10 @@ int warn_implicit = 1;
int warn_ctor_dtor_privacy = 1;
/* True if we want output of vtables to be controlled by whether
we seen the class's first non-inline virtual function. */
int flag_vtable_hack = 0;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
@ -360,6 +364,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"ansi-overloading", &flag_ansi_overloading, 1},
{"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1},
{"vtable-hack", &flag_vtable_hack, 1},
};
/* Decode the string P as a language-specific option.
@ -1619,107 +1624,12 @@ groktypefield (declspecs, parmlist)
return decl;
}
/* The precedence rules of this grammar (or any other deterministic LALR
grammar, for that matter), place the CALL_EXPR somewhere where we
may not want it. The solution is to grab the first CALL_EXPR we see,
pretend that that is the one that belongs to the parameter list of
the type conversion function, and leave everything else alone.
We pull it out in place.
CALL_REQUIRED is non-zero if we should complain if a CALL_EXPR
does not appear in DECL. */
tree
grokoptypename (decl, call_required)
tree decl;
int call_required;
grokoptypename (declspecs, declarator)
tree declspecs, declarator;
{
tree tmp, last;
my_friendly_assert (TREE_CODE (decl) == TYPE_EXPR, 195);
tmp = TREE_OPERAND (decl, 0);
last = NULL_TREE;
while (tmp)
{
switch (TREE_CODE (tmp))
{
case CALL_EXPR:
{
tree parms = TREE_OPERAND (tmp, 1);
if (last)
TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
else
TREE_OPERAND (decl, 0) = TREE_OPERAND (tmp, 0);
last = grokdeclarator (TREE_OPERAND (decl, 0),
TREE_TYPE (decl),
TYPENAME, 0, NULL_TREE);
TREE_OPERAND (tmp, 0) = build_typename_overload (last);
TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;
if (parms
&& TREE_CODE (TREE_VALUE (parms)) == TREE_LIST)
TREE_VALUE (parms)
= grokdeclarator (TREE_VALUE (TREE_VALUE (parms)),
TREE_PURPOSE (TREE_VALUE (parms)),
TYPENAME, 0, NULL_TREE);
if (parms)
{
if (TREE_VALUE (parms) != void_type_node)
cp_error ("`operator %T' requires empty parameter list",
last);
else
/* Canonicalize parameter lists. */
TREE_OPERAND (tmp, 1) = void_list_node;
}
return tmp;
}
case INDIRECT_REF:
case ADDR_EXPR:
case ARRAY_REF:
break;
case SCOPE_REF:
/* This is legal when declaring a conversion to
something of type pointer-to-member. */
if (TREE_CODE (TREE_OPERAND (tmp, 1)) == INDIRECT_REF)
{
tmp = TREE_OPERAND (tmp, 1);
}
else
{
#if 0
/* We may need to do this if grokdeclarator cannot handle this. */
error ("type `member of class %s' invalid return type",
TYPE_NAME_STRING (TREE_OPERAND (tmp, 0)));
TREE_OPERAND (tmp, 1) = build_parse_node (INDIRECT_REF, TREE_OPERAND (tmp, 1));
#endif
tmp = TREE_OPERAND (tmp, 1);
}
break;
default:
my_friendly_abort (196);
}
last = tmp;
tmp = TREE_OPERAND (tmp, 0);
}
last = grokdeclarator (TREE_OPERAND (decl, 0),
TREE_TYPE (decl),
TYPENAME, 0, NULL_TREE);
if (call_required)
cp_error ("`operator %T' construct requires parameter list", last);
tmp = build_parse_node (CALL_EXPR, build_typename_overload (last),
void_list_node, NULL_TREE);
TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;
return tmp;
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
return build_typename_overload (t);
}
/* When a function is declared with an initializer,
@ -2420,6 +2330,22 @@ static void
finish_vtable_vardecl (prev, vars)
tree prev, vars;
{
tree ctype = DECL_CONTEXT (vars);
if (flag_vtable_hack && !CLASSTYPE_INTERFACE_KNOWN (ctype))
{
tree method;
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
method = DECL_NEXT_METHOD (method))
{
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method))
{
TREE_PUBLIC (vars) = 1;
DECL_EXTERNAL (vars) = DECL_EXTERNAL (method);
break;
}
}
}
if (write_virtuals >= 0
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
{
@ -2468,6 +2394,8 @@ finish_vtable_vardecl (prev, vars)
rest_of_decl_compilation (vars, 0, 1, 1);
}
else if (TREE_USED (vars) && flag_vtable_hack)
assemble_external (vars);
/* We know that PREV must be non-zero here. */
TREE_CHAIN (prev) = TREE_CHAIN (vars);
}
@ -2783,7 +2711,7 @@ finish_file ()
There are several ways of getting the same effect, from changing the
way that iterators over the chain treat the elements that pertain to
virtual function tables, moving the implementation of this code to
cp-decl.c (where we can manipulate global_binding_level directly),
decl.c (where we can manipulate global_binding_level directly),
popping the garbage after pushing it and slicing away the vtable
stuff, or just leaving it alone. */
@ -2821,3 +2749,134 @@ finish_file ()
if (flag_detailed_statistics)
dump_time_statistics ();
}
/* This is something of the form 'A()()()()()+1' that has turned out to be an
expr. Since it was parsed like a type, we need to wade through and fix
that. Unfortunately, since operator() is left-associative, we can't use
tail recursion. In the above example, TYPE is `A', and DECL is
`()()()()()'.
Maybe this shouldn't be recursive, but how often will it actually be
used? (jason) */
tree
reparse_absdcl_as_expr (type, decl)
tree type, decl;
{
/* do build_functional_cast (type, NULL_TREE) at bottom */
if (TREE_OPERAND (decl, 0) == NULL_TREE)
return build_functional_cast (type, NULL_TREE);
/* recurse */
decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
decl = build_x_function_call (decl, NULL_TREE, current_class_decl);
if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
decl = require_complete_type (decl);
return decl;
}
/* This is something of the form `int ((int)(int)(int)1)' that has turned
out to be an expr. Since it was parsed like a type, we need to wade
through and fix that. Since casts are right-associative, we are
reversing the order, so we don't have to recurse.
In the above example, DECL is the `(int)(int)(int)', and EXPR is the
`1'. */
tree
reparse_absdcl_as_casts (decl, expr)
tree decl, expr;
{
tree type;
if (TREE_CODE (expr) == CONSTRUCTOR)
{
type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
decl = TREE_OPERAND (decl, 0);
if (IS_SIGNATURE (type))
{
error ("cast specifies signature type");
return error_mark_node;
}
expr = digest_init (type, expr, (tree *) 0);
if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
{
int failure = complete_array_type (type, expr, 1);
if (failure)
my_friendly_abort (78);
}
}
while (decl)
{
type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
decl = TREE_OPERAND (decl, 0);
expr = build_c_cast (type, expr);
}
return expr;
}
/* Recursive helper function for reparse_decl_as_expr. It may be a good
idea to reimplement this using an explicit stack, rather than recursion. */
static tree
reparse_decl_as_expr1 (decl)
tree decl;
{
switch (TREE_CODE (decl))
{
case IDENTIFIER_NODE:
return do_identifier (decl);
case INDIRECT_REF:
return build_x_indirect_ref
(reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), "unary *");
case ADDR_EXPR:
return build_x_unary_op (ADDR_EXPR,
reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
case BIT_NOT_EXPR:
return build_x_unary_op (BIT_NOT_EXPR,
reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
}
my_friendly_abort (5);
}
/* This is something of the form `int (*a)++' that has turned out to be an
expr. It was only converted into parse nodes, so we need to go through
and build up the semantics. Most of the work is done by
reparse_decl_as_expr1, above.
In the above example, TYPE is `int' and DECL is `*a'. */
tree
reparse_decl_as_expr (type, decl)
tree type, decl;
{
decl = build_tree_list (NULL_TREE, reparse_decl_as_expr1 (decl));
return build_functional_cast (type, decl);
}
/* This is something of the form `int (*a)' that has turned out to be a
decl. It was only converted into parse nodes, so we need to do the
checking that make_{pointer,reference}_declarator do. */
tree
finish_decl_parsing (decl)
tree decl;
{
switch (TREE_CODE (decl))
{
case IDENTIFIER_NODE:
return decl;
case INDIRECT_REF:
return make_pointer_declarator
(NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
case ADDR_EXPR:
return make_reference_declarator
(NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
case BIT_NOT_EXPR:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
}
}

View File

@ -25,7 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* cp_printer is the type of a function which converts an argument into
a string for digestion by printf. The cp_printer function should deal
with all memory management; the functions in this file will not free
the char*s returned. See cp-error.c for an example use of this code. */
the char*s returned. See error.c for an example use of this code. */
typedef char* cp_printer PROTO((HOST_WIDE_INT, int));
extern cp_printer * cp_printers[256];

View File

@ -76,6 +76,7 @@ static char *scratch_firstobj;
# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
# define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \
OB_PUTCP (digit_buffer); } while (0)
# define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));
# define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
@ -131,11 +132,11 @@ dump_type (t, v)
switch (TREE_CODE (t))
{
case ERROR_MARK:
OB_PUTS ("<error>");
OB_PUTS ("{error}");
break;
case UNKNOWN_TYPE:
OB_PUTS ("<unknown type>");
OB_PUTS ("{unknown type}");
break;
case TREE_LIST:
@ -206,9 +207,7 @@ dump_type (t, v)
break;
case TEMPLATE_TYPE_PARM:
OB_PUTS ("<template type parm ");
OB_PUTID (TYPE_IDENTIFIER (t));
OB_PUTC ('>');
break;
case UNINSTANTIATED_P_TYPE:
@ -230,11 +229,27 @@ dump_type (t, v)
break;
default:
my_friendly_abort (68);
sorry ("`%s' not supported by dump_type",
tree_code_name[(int) TREE_CODE (t)]);
}
}
static char *
aggr_variety (t)
tree t;
{
if (TREE_CODE (t) == ENUMERAL_TYPE)
return "enum";
else if (TREE_CODE (t) == UNION_TYPE)
return "union";
else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
return "class";
else if (TYPE_LANG_SPECIFIC (t) && IS_SIGNATURE (t))
return "signature";
else
return "struct";
}
/* Print out a class declaration, in the form `class foo'. */
static void
dump_aggr_type (t, v)
@ -242,18 +257,7 @@ dump_aggr_type (t, v)
int v; /* verbose? */
{
tree name;
char *variety;
if (TREE_CODE (t) == ENUMERAL_TYPE)
variety = "enum";
else if (TREE_CODE (t) == UNION_TYPE)
variety = "union";
else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
variety = "class";
else if (TYPE_LANG_SPECIFIC (t) && IS_SIGNATURE (t))
variety = "signature";
else
variety = "struct";
char *variety = aggr_variety (t);
dump_readonly_or_volatile (t, after);
@ -278,13 +282,13 @@ dump_aggr_type (t, v)
if (ANON_AGGRNAME_P (name))
{
OB_PUTS ("<anonymous");
OB_PUTS ("{anonymous");
if (!v)
{
OB_PUTC (' ');
OB_PUTCP (variety);
}
OB_PUTC ('>');
OB_PUTC ('}');
}
else
OB_PUTID (name);
@ -369,13 +373,12 @@ dump_type_prefix (t, v)
case OFFSET_TYPE:
offset_type:
dump_type_prefix (TREE_TYPE (t), v);
if (NEXT_CODE (t) != FUNCTION_TYPE && NEXT_CODE (t) != METHOD_TYPE)
OB_PUTC (' ');
if (TREE_CODE (t) == OFFSET_TYPE)
dump_type (TYPE_OFFSET_BASETYPE (t), 0);
else /* pointer to member function */
dump_type (TYPE_METHOD_BASETYPE (TREE_TYPE (t)), 0);
OB_PUTC2 (':', ':');
if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */
{
OB_PUTC (' ');
dump_type (TYPE_OFFSET_BASETYPE (t), 0);
OB_PUTC2 (':', ':');
}
OB_PUTC ('*');
dump_readonly_or_volatile (t, none);
break;
@ -416,7 +419,8 @@ dump_type_prefix (t, v)
break;
default:
my_friendly_abort (65);
sorry ("`%s' not supported by dump_type_prefix",
tree_code_name[(int) TREE_CODE (t)]);
}
}
@ -483,7 +487,8 @@ dump_type_suffix (t, v)
break;
default:
my_friendly_abort (67);
sorry ("`%s' not supported by dump_type_suffix",
tree_code_name[(int) TREE_CODE (t)]);
}
}
@ -576,7 +581,7 @@ dump_decl (t, v)
if (DECL_NAME (t))
dump_decl (DECL_NAME (t), v);
else
OB_PUTS ("<anon>");
OB_PUTS ("{anon}");
if (v > 0) dump_type_suffix (TREE_TYPE (t), v);
break;
@ -636,16 +641,41 @@ dump_decl (t, v)
break;
case TEMPLATE_DECL:
switch (NEXT_CODE (t))
{
case METHOD_TYPE:
case FUNCTION_TYPE:
dump_function_decl (t, v);
break;
{
tree args = DECL_TEMPLATE_PARMS (t);
int i, len = TREE_VEC_LENGTH (args);
OB_PUTS ("template <");
for (i = 0; i < len; i++)
{
tree arg = TREE_VEC_ELT (args, i);
if (TREE_CODE (arg) == IDENTIFIER_NODE)
{
OB_PUTS ("class ");
OB_PUTID (arg);
}
else
dump_decl (arg, 1);
OB_PUTC2 (',', ' ');
}
OB_UNPUT (2);
OB_PUTC2 ('>', ' ');
default:
my_friendly_abort (353);
}
if (DECL_TEMPLATE_IS_CLASS (t))
{
OB_PUTS ("class ");
OB_PUTID (DECL_NAME (t));
}
else switch (NEXT_CODE (t))
{
case METHOD_TYPE:
case FUNCTION_TYPE:
dump_function_decl (t, v);
break;
default:
my_friendly_abort (353);
}
}
break;
case LABEL_DECL:
@ -667,7 +697,8 @@ dump_decl (t, v)
break;
default:
my_friendly_abort (70);
sorry ("`%s' not supported by dump_decl",
tree_code_name[(int) TREE_CODE (t)]);
}
}
@ -1157,6 +1188,22 @@ dump_expr (t, nop)
OB_PUTC ('}');
break;
case OFFSET_REF:
{
tree ob = TREE_OPERAND (t, 0);
if (TREE_CODE (ob) == NOP_EXPR
&& TREE_OPERAND (ob, 0) == error_mark_node
&& TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
/* A::f */
dump_expr (TREE_OPERAND (t, 1), 0);
else
{
sorry ("operand of OFFSET_REF not understood");
goto error;
}
break;
}
/* This list is incomplete, but should suffice for now.
It is very important that `sorry' does not call
`report_error_function'. That could cause an infinite loop. */
@ -1167,7 +1214,7 @@ dump_expr (t, nop)
/* fall through to ERROR_MARK... */
case ERROR_MARK:
error:
OB_PUTCP ("/* error */");
OB_PUTCP ("{error}");
break;
}
}
@ -1321,7 +1368,7 @@ op_as_string (p, v)
static char buf[] = "operator ";
if (p == 0)
return "<unknown>";
return "{unknown}";
strcpy (buf + 9, opname_tab [p]);
return buf;

View File

@ -349,7 +349,7 @@ void
finish_exception_decl (cname, decl)
tree cname, decl;
{
/* In cp-decl.h. */
/* In decl.h. */
extern tree last_function_parms;
/* An exception declaration. */

View File

@ -22,6 +22,8 @@ Questions and comments to mrs@@cygnus.com.
* Templates::
* Access Control::
* Error Reporting::
* Parser::
* Copying Objects::
* Concept Index::
@end menu
@ -77,19 +79,19 @@ An example would be:
@example
extern "C" int printf(const char*, ...);
struct A { virtual void f() { } };
struct B : virtual A { int b; B() : b(0) {} void f() { b++; } };
struct C : B {};
struct D : B {};
struct E : C, D {};
struct A @{ virtual void f() @{ @} @};
struct B : virtual A @{ int b; B() : b(0) @{@} void f() @{ b++; @} @};
struct C : B @{@};
struct D : B @{@};
struct E : C, D @{@};
int main()
{
@{
E e;
C& c = e; D& d = e;
c.f(); d.f();
printf ("C::b = %d, D::b = %d\n", e.C::b, e.D::b);
return 0;
}
@}
@end example
This will print out 2, 0, instead of 1,1.
@ -984,7 +986,7 @@ TREE_PROTECTED and TREE_PRIVATE are used to record the access levels
granted by the containing class. BEWARE: TREE_PUBLIC means something
completely unrelated to access control!
@node Error Reporting, Concept Index, Access Control, Top
@node Error Reporting, Parser, Access Control, Top
@section Error Reporting
The C++ frontend uses a call-back mechanism to allow functions to print
@ -1022,7 +1024,110 @@ To have the line number on the error message indicate the line of the
DECL, use @code{cp_error_at} and its ilk; to indicate which argument you want,
use @code{%+D}, or it will default to the first.
@node Concept Index, , Error Reporting, Top
@node Parser, Copying Objects, Error Reporting, Top
@section Parser
Some comments on the parser:
The @code{after_type_declarator} / @code{notype_declarator} hack is
necessary in order to allow redeclarations of @code{TYPENAME}s, for
instance
@example
typedef int foo;
class A @{
char *foo;
@};
@end example
In the above, the first @code{foo} is parsed as a @code{notype_declarator},
and the second as a @code{after_type_declarator}.
Ambiguities:
There are currently four reduce/reduce ambiguities in the parser. They are:
1) Between @code{template_parm} and
@code{named_class_head_sans_basetype}, for the tokens @code{aggr
identifier}. This situation occurs in code looking like
@example
template <class T> class A @{ @};
@end example
It is ambiguous whether @code{class T} should be parsed as the
declaration of a template type parameter named @code{T} or an unnamed
constant parameter of type @code{class T}. Section 14.6, paragraph 3 of
the January '94 working paper states that the first interpretation is
the correct one. This ambiguity results in four reduce/reduce conflicts.
2) Between @code{primary} and @code{typename} for code like @samp{int()}
in places where both can be accepted, such as the argument to
@code{sizeof}. Section 8.1 of the pre-San Diego working paper specifies
that these ambiguous constructs will be interpreted as @code{typename}s.
This ambiguity results in six reduce/reduce conflicts.
3) Between @code{primary}/@code{functional_cast} and
@code{expr_or_declarator}/@code{complex_direct_notype_declarator}, for
various token strings. This situation occurs in code looking like
@example
int (*a);
@end example
This code is ambiguous; it could be a declaration of the variable
@samp{a} as a pointer to @samp{int}, or it could be a functional cast of
@samp{*a} to @samp{int}. Section 6.8 specifies that the former
interpretation is correct. This ambiguity results in 12 reduce/reduce
conflicts. Ack.
4) Between @code{after_type_declarator} and @code{parm}, for the token
@code{TYPENAME}. This occurs in (as one example) code like
@example
typedef int foo, bar;
class A @{
foo (bar);
@};
@end example
What is @code{bar} inside the class definition? We currently interpret
it as a @code{parm}, as does Cfront, but IBM xlC interprets it as an
@code{after_type_declarator}. I suspect that xlC is correct, in light
of 7.1p2, which says "The longest sequence of @i{decl-specifiers} that
could possibly be a type name is taken as the @i{decl-specifier-seq} of
a @i{declaration}." However, it seems clear that this rule must be
violated in the case of constructors, so...
Unlike the others, this ambiguity is not recognized by the Working Paper.
@node Copying Objects, Concept Index, Parser, Top
@section Copying Objects
The generated copy assignment operator in g++ does not currently do the
right thing for multiple inheritance involving virtual bases; it just
calls the copy assignment operators for its direct bases. What it
should probably do is:
1) Split up the copy assignment operator for all classes that have
vbases into "copy my vbases" and "copy everything else" parts. Or do
the trickiness that the constructors do to ensure that vbases don't get
initialized by intermediate bases.
2) Wander through the class lattice, find all vbases for which no
intermediate base has a user-defined copy assignment operator, and call
their "copy everything else" routines. If not all of my vbases satisfy
this criterion, warn, because this may be surprising behavior.
3) Call the "copy everything else" routine for my direct bases.
If we only have one direct base, we can just foist everything off onto
them.
This issue is currently under discussion in the core reflector
(2/28/94).
@node Concept Index, , Copying Objects, Top
@section Concept Index
@printindex cp

View File

@ -1872,7 +1872,7 @@ get_type_value (name)
}
/* This code could just as well go in `cp-class.c', but is placed here for
/* This code could just as well go in `class.c', but is placed here for
modularity. */
/* For an expression of the form CNAME :: NAME (PARMLIST), build
@ -1992,7 +1992,7 @@ build_member_call (cname, name, parmlist)
@@ Prints out lousy diagnostics for operator <typename>
@@ fields.
@@ This function should be rewritten and placed in cp-search.c. */
@@ This function should be rewritten and placed in search.c. */
tree
build_offset_ref (cname, name)
tree cname, name;
@ -2024,12 +2024,8 @@ build_offset_ref (cname, name)
name);
return error_mark_node;
}
if (TREE_CODE (t) == TYPE_DECL)
{
cp_error ("member `%D' is just a type declaration", t);
return error_mark_node;
}
if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == CONST_DECL)
{
TREE_USED (t) = 1;
return t;
@ -2170,8 +2166,8 @@ build_offset_ref (cname, name)
if (TREE_CODE (t) == TYPE_DECL)
{
cp_error ("member `%D' is just a type declaration", t);
return error_mark_node;
TREE_USED (t) = 1;
return t;
}
/* static class members and class-specific enum
values can be returned without further ado. */
@ -3036,6 +3032,13 @@ build_new (placement, decl, init, use_global_new)
/* 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)
@ -3369,6 +3372,12 @@ build_new (placement, decl, init, use_global_new)
}
}
done:
if (rval && TREE_TYPE (rval) != build_pointer_type (type))
{
/* The type of new int [3][3] is not int *, but int [3] * */
rval = build_c_cast (build_pointer_type (type), rval);
}
if (pending_sizes)
rval = build_compound_expr (chainon (pending_sizes,
build_tree_list (NULL_TREE, rval)));

View File

@ -25,7 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
the GNU library available, so FILE objects just don't cut it.
This file is written as a separate module, but can be included by
cp-lex.c for very minor efficiency gains (primarily in function
lex.c for very minor efficiency gains (primarily in function
inlining). */
#include <stdio.h>
@ -97,7 +97,7 @@ free_input (inp)
static int putback_char = -1;
/* Some of these external functions are declared inline in case this file
is included in cp-lex.c. */
is included in lex.c. */
inline
void

View File

@ -313,7 +313,7 @@ my_get_run_time ()
/* Table indexed by tree code giving a string containing a character
classifying the tree code. Possibilities are
t, d, s, c, r, <, 1 and 2. See cp-tree.def for details. */
t, d, s, c, r, <, 1 and 2. See cp/tree.def for details. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
@ -1036,7 +1036,7 @@ extract_interface_info ()
interface_unknown = TREE_INT_CST_HIGH (fileinfo);
}
/* Return nonzero if S and T are not considered part of an
/* Return nonzero if S is not considered part of an
INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
static int
interface_strcmp (s)
@ -1046,8 +1046,6 @@ interface_strcmp (s)
struct impl_files *ifiles;
char *s1;
s = FILE_NAME_NONDIRECTORY (s);
for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
{
char *t1 = ifiles->filename;
@ -1087,7 +1085,7 @@ set_typedecl_interface_info (prev, vars)
tree type = TREE_TYPE (vars);
CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
= interface_strcmp (DECL_SOURCE_FILE (vars));
= interface_strcmp (FILE_NAME_NONDIRECTORY (DECL_SOURCE_FILE (vars)));
}
void
@ -1109,7 +1107,7 @@ set_vardecl_interface_info (prev, vars)
/* Called from the top level: if there are any pending inlines to
do, set up to process them now. This function sets up the first function
to be parsed; after it has been, the rule for fndef in cp-parse.y will
to be parsed; after it has been, the rule for fndef in parse.y will
call process_next_inline to start working on the next one. */
void
do_pending_inlines ()
@ -2432,19 +2430,39 @@ check_newline ()
&& getch () == 'e'
&& ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
{
int warned_interface = 0;
int warned_already = 0;
char *main_filename = input_filename;
/* Read to newline. */
main_filename = FILE_NAME_NONDIRECTORY (main_filename);
while (c == ' ' || c == '\t')
c = getch ();
if (c != '\n')
{
put_back (c);
token = real_yylex ();
if (token != STRING
|| TREE_CODE (yylval.ttype) != STRING_CST)
{
error ("invalid `#pragma interface'");
goto skipline;
}
main_filename = TREE_STRING_POINTER (yylval.ttype);
c = getch();
put_back (c);
}
while (c == ' ' || c == '\t')
c = getch ();
while (c != '\n')
{
c = getch ();
if (!warned_interface && extra_warnings
if (!warned_already && extra_warnings
&& c != ' ' && c != '\t' && c != '\n')
{
warning ("garbage after `#pragma interface' ignored");
warned_interface = 1;
warned_already = 1;
}
c = getch ();
}
write_virtuals = 3;
@ -2459,6 +2477,7 @@ check_newline ()
if (main_input_filename == 0)
main_input_filename = input_filename;
#ifdef AUTO_IMPLEMENT
filename = FILE_NAME_NONDIRECTORY (main_input_filename);
fi = get_time_identifier (filename);
fi = IDENTIFIER_CLASS_VALUE (fi);
@ -2468,9 +2487,10 @@ check_newline ()
impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
impl_file_chain->filename = filename;
impl_file_chain->next = 0;
#endif
}
interface_only = interface_strcmp (input_filename);
interface_only = interface_strcmp (main_filename);
interface_unknown = 0;
TREE_INT_CST_LOW (fileinfo) = interface_only;
TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
@ -2490,8 +2510,10 @@ check_newline ()
&& getch () == 'n'
&& ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
{
int warned_already = 0;
char *main_filename = main_input_filename ? main_input_filename : input_filename;
main_filename = FILE_NAME_NONDIRECTORY (main_filename);
while (c == ' ' || c == '\t')
c = getch ();
if (c != '\n')
@ -2505,13 +2527,24 @@ check_newline ()
goto skipline;
}
main_filename = TREE_STRING_POINTER (yylval.ttype);
c = getch();
put_back (c);
}
main_filename = FILE_NAME_NONDIRECTORY (main_filename);
/* read to newline. */
while (c != '\n')
while (c == ' ' || c == '\t')
c = getch ();
while (c != '\n')
{
if (!warned_already && extra_warnings
&& c != ' ' && c != '\t' && c != '\n')
{
warning ("garbage after `#pragma implementation' ignored");
warned_already = 1;
}
c = getch ();
}
if (write_virtuals == 3)
{
struct impl_files *ifiles = impl_file_chain;

View File

@ -1,4 +1,4 @@
/* Define constants and variables for communication with cp-parse.y.
/* Define constants and variables for communication with parse.y.
Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
and by Brendan Kehoe (brendan@cygnus.com).

View File

@ -929,6 +929,8 @@ build_typename_overload (type)
build_overload_name (type, 0, 1);
id = get_identifier (obstack_base (&scratch_obstack));
IDENTIFIER_OPNAME_P (id) = 1;
IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);
TREE_TYPE (id) = type;
return id;
}

File diff suppressed because it is too large Load Diff

View File

@ -169,8 +169,9 @@ end_template_parm_list (parms)
D1 is template header; D2 is class_head_sans_basetype or a
TEMPLATE_DECL with its DECL_RESULT field set. */
void
end_template_decl (d1, d2, is_class)
end_template_decl (d1, d2, is_class, defn)
tree d1, d2, is_class;
int defn;
{
tree decl;
struct template_info *tmpl;
@ -254,37 +255,47 @@ end_template_decl (d1, d2, is_class)
}
DECL_TEMPLATE_INFO (decl) = tmpl;
DECL_TEMPLATE_PARMS (decl) = d1;
lose:
if (decl)
/* So that duplicate_decls can do the right thing. */
if (defn)
DECL_INITIAL (decl) = error_mark_node;
/* If context of decl is non-null (i.e., method template), add it
to the appropriate class template, and pop the binding levels. */
if (! DECL_TEMPLATE_IS_CLASS (decl)
&& DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
{
/* If context of decl is non-null (i.e., method template), add it
to the appropriate class template, and pop the binding levels. */
if (! DECL_TEMPLATE_IS_CLASS (decl)
&& DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
{
tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
tree tmpl;
my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
tmpl = UPT_TEMPLATE (ctx);
DECL_TEMPLATE_MEMBERS (tmpl) =
perm_tree_cons (DECL_NAME (decl), decl,
DECL_TEMPLATE_MEMBERS (tmpl));
poplevel (0, 0, 0);
poplevel (0, 0, 0);
}
/* Otherwise, go back to top level first, and push the template decl
again there. */
else
{
poplevel (0, 0, 0);
poplevel (0, 0, 0);
if (TREE_TYPE (decl)
&& IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl)) != NULL_TREE)
push_overloaded_decl (decl, 0);
else
pushdecl (decl);
}
tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
tree tmpl;
my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
tmpl = UPT_TEMPLATE (ctx);
DECL_TEMPLATE_MEMBERS (tmpl) =
perm_tree_cons (DECL_NAME (decl), decl,
DECL_TEMPLATE_MEMBERS (tmpl));
poplevel (0, 0, 0);
poplevel (0, 0, 0);
}
/* Otherwise, go back to top level first, and push the template decl
again there. */
else
{
poplevel (0, 0, 0);
poplevel (0, 0, 0);
if (TREE_TYPE (decl))
{
/* Function template */
tree t = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl));
if (t && is_overloaded_fn (t))
for (t = get_first_fn (t); t; t = DECL_CHAIN (t))
if (TREE_CODE (t) == TEMPLATE_DECL
&& duplicate_decls (decl, t))
decl = t;
push_overloaded_decl (decl, 0);
}
else
pushdecl (decl);
}
lose:
#if 0 /* It happens sometimes, with syntactic or semantic errors.
One specific case:
@ -671,7 +682,7 @@ pop_template_decls (parmlist, arglist, class_level)
poplevel (0, 0, 0);
}
/* Should be defined in cp-parse.h. */
/* Should be defined in parse.h. */
extern int yychar;
int
@ -1842,8 +1853,7 @@ end_template_instantiation (name)
extract_interface_info ();
}
/* Store away the text of an inline template function. No rtl is
generated for this function until it is actually needed. */
/* Store away the text of an template. */
void
reinit_parse_for_template (yychar, d1, d2)
@ -1851,7 +1861,7 @@ reinit_parse_for_template (yychar, d1, d2)
tree d1, d2;
{
struct template_info *template_info;
extern struct obstack inline_text_obstack; /* see comment in cp-lex.c */
extern struct obstack inline_text_obstack; /* see comment in lex.c */
if (d2 == NULL_TREE || d2 == error_mark_node)
{
@ -1912,7 +1922,7 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);
/* ARGS could be NULL (via a call from cp-parse.y to
/* ARGS could be NULL (via a call from parse.y to
build_x_function_call). */
if (args)
my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);

View File

@ -435,6 +435,8 @@ get_binfo (parent, binfo, protect)
type = BINFO_TYPE (binfo);
else if (TREE_CODE (binfo) == RECORD_TYPE)
type = binfo;
else if (TREE_CODE (binfo) == UNION_TYPE)
return NULL_TREE;
else
my_friendly_abort (90);
@ -479,9 +481,10 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
}
else
{
int same_object = tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
BINFO_OFFSET (binfo));
int same_object = (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
BINFO_OFFSET (binfo))
&& *via_virtual_ptr && via_virtual);
if (*via_virtual_ptr && via_virtual==0)
{
*rval_private_ptr = is_private;
@ -2535,7 +2538,8 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
tree addr;
tree vtbl = BINFO_VTABLE (vbases);
tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
assemble_external (vtbl);
if (!flag_vtable_hack)
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
if (use_computed_offsets)
@ -2580,112 +2584,42 @@ static void
dfs_get_vbase_types (binfo)
tree binfo;
{
tree binfos = BINFO_BASETYPES (binfo);
tree type = BINFO_TYPE (binfo);
tree these_vbase_types = CLASSTYPE_VBASECLASSES (type);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
if (these_vbase_types)
if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
{
while (these_vbase_types)
{
tree this_type = BINFO_TYPE (these_vbase_types);
/* We really need to start from a fresh copy of this
virtual basetype! CLASSTYPE_MARKED2 is the shortcut
for BINFO_VBASE_MARKED. */
if (! CLASSTYPE_MARKED2 (this_type))
{
vbase_types = make_binfo (integer_zero_node,
this_type,
TYPE_BINFO_VTABLE (this_type),
TYPE_BINFO_VIRTUALS (this_type),
vbase_types);
TREE_VIA_VIRTUAL (vbase_types) = 1;
SET_CLASSTYPE_MARKED2 (this_type);
}
these_vbase_types = TREE_CHAIN (these_vbase_types);
}
}
else for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
if (TREE_VIA_VIRTUAL (base_binfo) && ! BINFO_VBASE_MARKED (base_binfo))
{
vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (base_binfo),
BINFO_VTABLE (base_binfo),
BINFO_VIRTUALS (base_binfo), vbase_types);
TREE_VIA_VIRTUAL (vbase_types) = 1;
SET_BINFO_VBASE_MARKED (base_binfo);
}
vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (binfo),
BINFO_VTABLE (binfo),
BINFO_VIRTUALS (binfo), vbase_types);
TREE_VIA_VIRTUAL (vbase_types) = 1;
SET_BINFO_VBASE_MARKED (binfo);
}
SET_BINFO_MARKED (binfo);
}
/* Some virtual baseclasses might be virtual baseclasses for
other virtual baseclasses. We sort the virtual baseclasses
topologically: in the list returned, the first virtual base
classes have no virtual baseclasses themselves, and any entry
on the list has no dependency on virtual base classes later in the
list. */
/* get a list of virtual base classes in dfs order. */
tree
get_vbase_types (type)
tree type;
{
tree ordered_vbase_types = NULL_TREE, prev, next;
tree vbases;
tree binfo;
if (TREE_CODE (type) == TREE_VEC)
binfo = type;
else
binfo = TYPE_BINFO (type);
vbase_types = NULL_TREE;
dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp);
dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
dfs_walk (binfo, dfs_get_vbase_types, unmarkedp);
dfs_walk (binfo, dfs_unmark, markedp);
/* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
reverse it so that we get normal dfs ordering. */
vbase_types = nreverse (vbase_types);
/* Almost all of the below is not needed now. We should be able to just
return vbase_types directly... (mrs) */
while (vbase_types)
{
/* Now sort these types. This is essentially a bubble merge. */
/* unmark marked vbases */
for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
CLEAR_BINFO_VBASE_MARKED (vbases);
/* Farm out virtual baseclasses which have no marked ancestors. */
for (vbases = vbase_types, prev = NULL_TREE;
vbases; vbases = next)
{
next = TREE_CHAIN (vbases);
/* If VBASES does not have any vbases itself, or it's
topologically safe, it goes into the sorted list. */
if (1 /* ANSI C++ specifies dfs ordering now. */
|| ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases))
|| BINFO_VBASE_MARKED (vbases) == 0)
{
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (vbases);
else
vbase_types = TREE_CHAIN (vbases);
TREE_CHAIN (vbases) = NULL_TREE;
ordered_vbase_types = chainon (ordered_vbase_types, vbases);
CLEAR_BINFO_VBASE_MARKED (vbases);
}
else
prev = vbases;
}
/* Now unmark types all of whose ancestors are now on the
`ordered_vbase_types' list. */
for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
{
/* If all our virtual baseclasses are unmarked, ok. */
tree t = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases));
while (t && (BINFO_VBASE_MARKED (t) == 0
|| ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (t))))
t = TREE_CHAIN (t);
if (t == NULL_TREE)
CLEAR_BINFO_VBASE_MARKED (vbases);
}
}
return ordered_vbase_types;
return vbase_types;
}
static void

View File

@ -20,7 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG
when compiling cp-parse.c and cp-spew.c. */
when compiling parse.c and spew.c. */
#include "config.h"
#include <stdio.h>
@ -50,7 +50,7 @@ static struct token hack_scope ();
static tree hack_ptype ();
static tree hack_more_ids ();
/* From cp-lex.c: */
/* From lex.c: */
/* the declaration found for the last IDENTIFIER token read in.
yylex must look this up to detect typedefs, which get token type TYPENAME,
so it is left around in case the identifier is not a typedef but is
@ -74,7 +74,7 @@ static char follows_typename[END_OF_SAVED_INPUT+1];
static char follows_identifier[END_OF_SAVED_INPUT+1];
/* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
* of the last template_type parsed in cp-parse.y if it is followed by a
* of the last template_type parsed in parse.y if it is followed by a
* scope operator. It will be reset inside the next invocation of yylex().
* This is used for recognizing nested types inside templates.
* - niklas@appli.se */
@ -271,7 +271,7 @@ probe_obstack (h, obj, nlevels)
return nlevels != 0 && lp != 0;
}
/* from cp-lex.c: */
/* from lex.c: */
/* Value is 1 if we should try to make the next identifier look like a
typename (when it may be a local variable or a class variable).
Value is 0 if we treat this name in a default fashion.
@ -306,7 +306,7 @@ yylex()
{
/* Sync back again, leaving SCOPE on the token stream, because we
* failed to substitute the original SCOPE token with a
* SCOPED_TYPENAME. See rule "template_type" in cp-parse.y */
* SCOPED_TYPENAME. See rule "template_type" in parse.y */
consume_token ();
}
else
@ -364,7 +364,6 @@ yylex()
goto retry;
case IDENTIFIER:
/* Note: this calls arbitrate_lookup. */
trrr = lookup_name (tmp_token.yylval.ttype, -2);
if (trrr)
{
@ -436,6 +435,7 @@ yylex()
case TYPESPEC:
consume_token ();
finish_typename_processing:
#if 0
/* Now see if we should insert a START_DECLARATOR token.
Here are the cases caught:
@ -487,6 +487,7 @@ yylex()
nth_token (0)->yychar = START_DECLARATOR;
}
}
#endif
break;
#if 0
@ -708,6 +709,7 @@ frob_identifier ()
return rt;
}
#if 0
/* When this function is called, nth_token(0) is the current
token we are scanning. This means that the next token we'll
scan is nth_token (1). Usually the next token we'll scan
@ -874,6 +876,7 @@ arbitrate_lookup (name, exp_decl, type_decl)
return t;
}
}
#endif
/* now returns decl_node */
@ -1125,7 +1128,7 @@ static int
debug_yychar (yy)
int yy;
{
/* In cp-parse.y: */
/* In parse.y: */
extern char *debug_yytranslate ();
int i;

View File

@ -83,13 +83,8 @@ lvalue_p (ref)
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
if (TREE_CODE (TREE_OPERAND (ref, 1)) == VAR_DECL)
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
else
return 1;
return lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1));
break;
case ADDR_EXPR:
@ -940,6 +935,44 @@ hash_chainon (list1, list2)
hash_chainon (TREE_CHAIN (list1), list2));
}
static tree
get_identifier_list (value)
tree value;
{
tree list = IDENTIFIER_AS_LIST (value);
if (list != NULL_TREE
&& (TREE_CODE (list) != TREE_LIST
|| TREE_VALUE (list) != value))
list = NULL_TREE;
else if (IDENTIFIER_HAS_TYPE_VALUE (value)
&& TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
{
tree type = IDENTIFIER_TYPE_VALUE (value);
if (TYPE_PTRMEMFUNC_P (type))
list = NULL_TREE;
else if (type == current_class_type)
/* Don't mess up the constructor name. */
list = tree_cons (NULL_TREE, value, NULL_TREE);
else
{
register tree id;
/* This will return the correct thing for regular types,
nested types, and templates. Yay! */
if (TYPE_NESTED_NAME (type))
id = TYPE_NESTED_NAME (type);
else
id = TYPE_IDENTIFIER (type);
if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
CLASSTYPE_ID_AS_LIST (type)
= perm_tree_cons (NULL_TREE, id, NULL_TREE);
list = CLASSTYPE_ID_AS_LIST (type);
}
}
return list;
}
tree
get_decl_list (value)
tree value;
@ -947,35 +980,7 @@ get_decl_list (value)
tree list = NULL_TREE;
if (TREE_CODE (value) == IDENTIFIER_NODE)
{
list = IDENTIFIER_AS_LIST (value);
if (list != NULL_TREE
&& (TREE_CODE (list) != TREE_LIST
|| TREE_VALUE (list) != value))
list = NULL_TREE;
else if (IDENTIFIER_HAS_TYPE_VALUE (value)
&& TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
{
register tree id;
tree type = IDENTIFIER_TYPE_VALUE (value);
if (TYPE_PTRMEMFUNC_P (type))
list = NULL_TREE;
else
{
/* This will return the correct thing for regular types,
nested types, and templates. Yay! */
if (DECL_NESTED_TYPENAME (TYPE_NAME (type)))
value = DECL_NESTED_TYPENAME (TYPE_NAME (type));
id = value;
if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE,
id, NULL_TREE);
list = CLASSTYPE_ID_AS_LIST (type);
}
}
}
list = get_identifier_list (value);
else if (TREE_CODE (value) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (value))
list = CLASSTYPE_AS_LIST (value);
@ -1003,39 +1008,7 @@ list_hash_lookup_or_cons (value)
tree list = NULL_TREE;
if (TREE_CODE (value) == IDENTIFIER_NODE)
{
list = IDENTIFIER_AS_LIST (value);
if (list != NULL_TREE
&& (TREE_CODE (list) != TREE_LIST
|| TREE_VALUE (list) != value))
list = NULL_TREE;
else if (IDENTIFIER_HAS_TYPE_VALUE (value)
&& TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
{
/* If the type name and constructor name are different, don't
write constructor name into type. */
if (identifier_typedecl_value (value)
&& identifier_typedecl_value (value) != constructor_name (value))
list = tree_cons (NULL_TREE, value, NULL_TREE);
else
{
tree type = IDENTIFIER_TYPE_VALUE (value);
if (TYPE_PTRMEMFUNC_P (type))
list = NULL_TREE;
else
{
if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
{
/* Not just `value', which could be a template parm. */
tree id = DECL_NAME (TYPE_NAME (type));
CLASSTYPE_ID_AS_LIST (type) =
perm_tree_cons (NULL_TREE, id, NULL_TREE);
}
list = CLASSTYPE_ID_AS_LIST (type);
}
}
}
}
list = get_identifier_list (value);
else if (TREE_CODE (value) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (TREE_TYPE (value)))

View File

@ -541,10 +541,10 @@ comptypes (type1, type2, strict)
t1 = type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
t2 = type_for_size (TYPE_PRECISION (t2), 1);
}
if (t1 == t2)
return 1;
if (t1 == t2)
return 1;
}
/* Different classes of types can't be compatible. */
@ -643,6 +643,8 @@ comptypes (type1, type2, strict)
/* Target types must match incl. qualifiers. */
return comp_array_types (comptypes, t1, t2, strict);
case TEMPLATE_TYPE_PARM:
return 1;
}
return 0;
}
@ -2109,8 +2111,15 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
tree e2;
tree e3;
tree aref, vtbl;
tree aux_delta;
vtbl = build1 (ADDR_EXPR, ptr_type_node, instance);
/* convert down to the right base, before using the instance. */
instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
build_unary_op (ADDR_EXPR, instance, 0));
if (instance == error_mark_node)
return instance;
vtbl = convert_pointer_to (ptr_type_node, instance);
vtbl = build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtable_entry_type)),
vtbl, convert (sizetype, delta2));
@ -2398,6 +2407,12 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
val = integer_zero_node;
}
}
else if (TREE_CODE (val) == OFFSET_REF
&& TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
{
/* This is unclean. Should be handled elsewhere. */
val = build_unary_op (ADDR_EXPR, val, 0);
}
else if (TREE_CODE (val) == OFFSET_REF)
val = resolve_offset_ref (val);
@ -3075,7 +3090,11 @@ build_binary_op_nodefault (code, op0, op1, error_code)
}
else
index1 = integer_neg_one_node;
op1 = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type0), op1);
{
tree nop1 = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type0), op1);
TREE_CONSTANT (nop1) = TREE_CONSTANT (op1);
op1 = nop1;
}
e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, build_binary_op (EQ_EXPR, delta20, delta21, 1), 1);
@ -3577,11 +3596,14 @@ build_component_addr (arg, argtype, msg)
if (TREE_CODE (field) == FIELD_DECL
&& TYPE_USES_COMPLEX_INHERITANCE (basetype))
/* Can't convert directly to ARGTYPE, since that
may have the same pointer type as one of our
baseclasses. */
rval = build1 (NOP_EXPR, argtype,
convert_pointer_to (basetype, rval));
{
/* Can't convert directly to ARGTYPE, since that
may have the same pointer type as one of our
baseclasses. */
rval = build1 (NOP_EXPR, argtype,
convert_pointer_to (basetype, rval));
TREE_CONSTANT (rval) == TREE_CONSTANT (TREE_OPERAND (rval, 0));
}
else
/* This conversion is harmless. */
rval = convert (argtype, rval);
@ -4787,20 +4809,6 @@ build_c_cast (type, expr)
}
}
/* When converting into a reference type, just convert into a pointer to
the new type and deference it. While this is not exactly what ARM 5.4
calls for [why not? -jason], it is pretty close for now.
(int &)ri ---> *(int*)&ri */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
value = build_unary_op (ADDR_EXPR, value, 0);
if (value != error_mark_node)
value = convert (build_pointer_type (TREE_TYPE (type)), value);
if (value != error_mark_node)
value = build_indirect_ref (value, "reference conversion");
return value;
}
if (IS_SIGNATURE (type))
{
error ("cast specifies signature type");
@ -5819,6 +5827,59 @@ language_lvalue_valid (exp)
return 1;
}
/* Get differnce in deltas for different pointer to member function
types. Return inetger_zero_node, if FROM cannot be converted to a
TO type. If FORCE is true, then allow reverse conversions as well. */
static tree
get_delta_difference (from, to, force)
tree from, to;
{
tree delta = integer_zero_node;
tree binfo;
if (to == from)
return delta;
binfo = get_binfo (from, to, 1);
if (binfo == error_mark_node)
{
error (" in pointer to member function conversion");
return delta;
}
if (binfo == 0)
{
if (!force)
{
error_not_base_type (from, to);
error (" in pointer to member function conversion");
return delta;
}
binfo = get_binfo (to, from, 1);
if (binfo == error_mark_node)
{
error (" in pointer to member function conversion");
return delta;
}
if (binfo == 0)
{
error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
return delta;
}
if (TREE_VIA_VIRTUAL (binfo))
{
warning ("pointer to member conversion from virtual base class will only work if your very careful");
}
return fold (size_binop (MINUS_EXPR,
integer_zero_node,
BINFO_OFFSET (binfo)));
}
if (TREE_VIA_VIRTUAL (binfo))
{
warning ("pointer to member conversion from virtual base class will only work if your very careful");
}
return BINFO_OFFSET (binfo);
}
/* Build a constructor for a pointer to member function. It can be
used to initialize global variables, local variable, or used
as a value in expressions. TYPE is the POINTER to METHOD_TYPE we
@ -5826,62 +5887,104 @@ language_lvalue_valid (exp)
If FORCE is non-zero, then force this conversion, even if
we would rather not do it. Usually set when using an explicit
cast. */
cast.
Return error_mark_node, if something goes wrong. */
tree
build_ptrmemfunc (type, pfn, force)
tree type, pfn;
int force;
{
tree index;
tree index = integer_zero_node;
tree delta = integer_zero_node;
tree delta2 = integer_zero_node;
tree vfield_offset;
tree npfn;
tree u;
/* Handle multiple conversions of pointer to member fucntions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
{
tree ndelta, ndelta2, nindex;
/* Is is already the right type? */
#if 0
/* Sorry, can't do this, the backend is too stupid. */
if (TYPE_METHOD_BASETYPE (TREE_TYPE (type))
== TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))))
{
if (type != TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
{
npfn = build1 (NOP_EXPR, TYPE_GET_PTRMEMFUNC_TYPE (type), pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
}
return pfn;
}
#else
if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
return pfn;
#endif
if (TREE_CODE (pfn) != CONSTRUCTOR)
{
tree e1, e2, e3;
ndelta = convert (sizetype, build_component_ref (pfn, delta_identifier, 0, 0));
ndelta2 = convert (sizetype, DELTA2_FROM_PTRMEMFUNC (pfn));
index = build_component_ref (pfn, index_identifier, 0, 0);
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
delta = fold (size_binop (PLUS_EXPR, delta, ndelta));
delta2 = fold (size_binop (PLUS_EXPR, ndelta2, delta2));
e1 = fold (build (GT_EXPR, integer_type_node, index, integer_zero_node));
u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, index,
tree_cons (NULL_TREE, u, NULL_TREE))));
e2 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
pfn = PFN_FROM_PTRMEMFUNC (pfn);
npfn = build1 (NOP_EXPR, type, pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, index,
tree_cons (NULL_TREE, u, NULL_TREE))));
e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
return build_conditional_expr (e1, e2, e3);
}
ndelta = TREE_VALUE (CONSTRUCTOR_ELTS (pfn));
nindex = TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn)));
npfn = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn))));
npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn));
if (integer_zerop (nindex))
pfn = integer_zero_node;
else
{
sorry ("value casting of varible nonnull pointer to member functions not supported");
return error_mark_node;
}
}
/* Handle null pointer to member function conversions. */
if (integer_zerop (pfn))
{
pfn = build_c_cast (type, integer_zero_node);
u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
return build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node,
tree_cons (NULL_TREE, integer_zero_node,
tree_cons (NULL_TREE, u, NULL_TREE))));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node,
tree_cons (NULL_TREE, integer_zero_node,
tree_cons (NULL_TREE, u, NULL_TREE))));
return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
}
/* Allow pointer to member conversions here. */
if (type != TREE_TYPE (pfn))
{
tree binfo
= get_binfo (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
1);
if (binfo == error_mark_node)
{
error (" in pointer to member function conversion");
return NULL_TREE;
}
if (binfo == 0)
{
if (!force)
{
error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)));
error (" in pointer to member function conversion");
return NULL_TREE;
}
/* Just something handy with an offset of zero. */
binfo = TYPE_BINFO (TYPE_METHOD_BASETYPE (TREE_TYPE (type)));
}
if (TREE_VIA_VIRTUAL (binfo))
{
sorry ("pointer to member conversion from virtual base class");
}
delta = BINFO_OFFSET (binfo);
delta2 = size_binop (PLUS_EXPR, delta2, delta);
}
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
delta2 = fold (size_binop (PLUS_EXPR, delta2, delta));
if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
warning ("assuming pointer to member function is non-virtual");
@ -5890,10 +5993,10 @@ build_ptrmemfunc (type, pfn, force)
&& DECL_VINDEX (TREE_OPERAND (pfn, 0)))
{
/* Find the offset to the vfield pointer in the object. */
vfield_offset = TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn)));
vfield_offset = CLASSTYPE_VFIELD (vfield_offset);
vfield_offset = DECL_FIELD_BITPOS (vfield_offset);
vfield_offset = size_binop (FLOOR_DIV_EXPR, vfield_offset, size_int (BITS_PER_UNIT));
vfield_offset = get_binfo (DECL_CONTEXT (TREE_OPERAND (pfn, 0)),
DECL_CLASS_CONTEXT (TREE_OPERAND (pfn, 0)),
0);
vfield_offset = get_vfield_offset (vfield_offset);
delta2 = size_binop (PLUS_EXPR, vfield_offset, delta2);
/* Map everything down one to make room for the null pointer to member. */
@ -5901,22 +6004,21 @@ build_ptrmemfunc (type, pfn, force)
DECL_VINDEX (TREE_OPERAND (pfn, 0)),
integer_one_node);
u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
return build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, index,
tree_cons (NULL_TREE, u, NULL_TREE))));
}
else
index = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
{
index = fold (size_binop (MINUS_EXPR, integer_zero_node, integer_one_node));
npfn = build1 (NOP_EXPR, type, pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
npfn = build1 (NOP_EXPR, type, pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
}
return build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, index,
tree_cons (NULL_TREE, u, NULL_TREE))));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, index,
tree_cons (NULL_TREE, u, NULL_TREE))));
return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
}
/* Convert value RHS to type TYPE as preparation for an assignment
@ -6125,21 +6227,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else
pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s",
errtype);
else if (pedantic
&& ((TYPE_MAIN_VARIANT (ttl) == void_type_node
&& (TREE_CODE (ttr) == FUNCTION_TYPE
|| TREE_CODE (ttr) == METHOD_TYPE))
||
(TYPE_MAIN_VARIANT (ttr) == void_type_node
&& (TREE_CODE (ttl) == FUNCTION_TYPE
|| TREE_CODE (ttl) == METHOD_TYPE))))
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D'",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `void *' from `%T'", errtype, rhstype);
}
/* Const and volatile mean something different for function types,
so the usual warnings are not appropriate. */
else if ((TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttr) != METHOD_TYPE)
@ -6334,14 +6421,12 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else if (((coder == POINTER_TYPE && TREE_CODE (rhs) == ADDR_EXPR
&& TREE_CODE (rhstype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (rhstype)) == METHOD_TYPE)
|| integer_zerop (rhs))
|| integer_zerop (rhs)
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
&& TYPE_PTRMEMFUNC_P (type))
{
/* compatible pointer to member functions. */
rhs = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), rhs, 0);
if (rhs == 0)
return error_mark_node;
return digest_init (type, rhs, (tree *)0);
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), rhs, 0);
}
else if (codel == ERROR_MARK || coder == ERROR_MARK)
return error_mark_node;
@ -6353,7 +6438,11 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
/* Force an abort. */
my_friendly_assert (codel != REFERENCE_TYPE, 317);
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (rhs)))
return build1 (NOP_EXPR, type, rhs);
{
tree nrhs = build1 (NOP_EXPR, type, rhs);
TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
return nrhs;
}
else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
return convert (type, rhs);
@ -6512,7 +6601,11 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
rhs = convert_from_reference (rhs);
if (type != rhstype)
return build1 (NOP_EXPR, type, rhs);
{
tree nrhs = build1 (NOP_EXPR, type, rhs);
TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
rhs = nrhs;
}
return rhs;
}

View File

@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
/* First used: 0 (reserved), Last used: 355. Free: 5. */
/* First used: 0 (reserved), Last used: 355. */
static int abortcount = 0;
@ -641,13 +641,17 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
if (init && TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (type))
init = default_conversion (init);
if (init && TYPE_PTRMEMFUNC_P (type)
&& ((TREE_CODE (init) == ADDR_EXPR
&& TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE)
|| integer_zerop (init)))
|| integer_zerop (init)
|| (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))))
{
init = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), init, 0);
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), init, 0);
}
raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
@ -999,19 +1003,8 @@ process_init_constructor (type, init, elts)
{
tree tail1 = tail;
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (field)))
{
tree t
= build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (field)),
default_conversion (TREE_VALUE (tail)),
0);
if (t == NULL_TREE)
return error_mark_node;
next1 = digest_init (TREE_TYPE (field), t, &tail1);
}
else
next1 = digest_init (TREE_TYPE (field),
TREE_VALUE (tail), &tail1);
next1 = digest_init (TREE_TYPE (field),
TREE_VALUE (tail), &tail1);
my_friendly_assert (tail1 == 0
|| TREE_CODE (tail1) == TREE_LIST, 320);
tail = tail1;
@ -1377,22 +1370,22 @@ build_m_component_ref (datum, component)
if (datum == error_mark_node || component == error_mark_node)
return error_mark_node;
if (! IS_AGGR_TYPE (objtype))
{
cp_error ("cannot apply member pointer `%D' to `%E'", component, datum);
cp_error ("which is of non-aggregate type `%T'", objtype);
return error_mark_node;
}
if (TREE_CODE (type) != OFFSET_TYPE && TREE_CODE (type) != METHOD_TYPE)
{
error ("non-member type composed with object");
cp_error ("`%E' cannot be used as a member pointer, since it is of type `%T'", component, type);
return error_mark_node;
}
if (TREE_CODE (objtype) == REFERENCE_TYPE)
objtype = TREE_TYPE (objtype);
if (! IS_AGGR_TYPE (objtype))
{
cp_error ("cannot apply member pointer `%E' to `%E'", component, datum);
cp_error ("which is of non-aggregate type `%T'", objtype);
return error_mark_node;
}
if (! comptypes (TYPE_METHOD_BASETYPE (type), objtype, 0))
{
cp_error ("member type `%T::' incompatible with object type `%T'",