parent
d7a58f30d1
commit
51c184be09
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *));
|
||||
|
|
16
gcc/cp/cvt.c
16
gcc/cp/cvt.c
|
@ -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;
|
||||
|
|
304
gcc/cp/decl.c
304
gcc/cp/decl.c
|
@ -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,15 +2746,17 @@ 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;
|
||||
/* 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;
|
||||
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. */
|
||||
if (TREE_CODE (x) == TYPE_DECL)
|
||||
|
@ -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,10 +7617,18 @@ 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. */
|
||||
|
@ -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);
|
||||
|
|
261
gcc/cp/decl2.c
261
gcc/cp/decl2.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
131
gcc/cp/error.c
131
gcc/cp/error.c
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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
|
||||
|
|
63
gcc/cp/lex.c
63
gcc/cp/lex.c
|
@ -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;
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
1052
gcc/cp/parse.y
1052
gcc/cp/parse.y
File diff suppressed because it is too large
Load Diff
80
gcc/cp/pt.c
80
gcc/cp/pt.c
|
@ -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);
|
||||
|
|
118
gcc/cp/search.c
118
gcc/cp/search.c
|
@ -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,8 +481,9 @@ 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)
|
||||
{
|
||||
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
111
gcc/cp/tree.c
111
gcc/cp/tree.c
|
@ -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)))
|
||||
|
|
287
gcc/cp/typeck.c
287
gcc/cp/typeck.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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'",
|
||||
|
|
Loading…
Reference in New Issue