Commit 51c184be by Mike Stump

30th Cygnus<->FSF merge.

From-SVN: r6859
parent d7a58f30
......@@ -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;
......
......@@ -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;
......
......@@ -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];
......
......@@ -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,30 +229,35 @@ dump_type (t, v)
break;
default:
my_friendly_abort (68);
sorry ("`%s' not supported by dump_type",
tree_code_name[(int) TREE_CODE (t)]);
}
}
/* Print out a class declaration, in the form `class foo'. */
static void
dump_aggr_type (t, v)
static char *
aggr_variety (t)
tree t;
int v; /* verbose? */
{
tree name;
char *variety;
if (TREE_CODE (t) == ENUMERAL_TYPE)
variety = "enum";
return "enum";
else if (TREE_CODE (t) == UNION_TYPE)
variety = "union";
return "union";
else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
variety = "class";
return "class";
else if (TYPE_LANG_SPECIFIC (t) && IS_SIGNATURE (t))
variety = "signature";
return "signature";
else
variety = "struct";
return "struct";
}
/* Print out a class declaration, in the form `class foo'. */
static void
dump_aggr_type (t, v)
tree t;
int v; /* verbose? */
{
tree name;
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
......
......@@ -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;
......
/* 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;
}
......
......@@ -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))
{
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);
/* 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);
}
/* 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);
}
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);
......
......@@ -435,6 +435,8 @@ get_binfo (parent, binfo, protect)
type = BINFO_TYPE (binfo);
else if (TREE_CODE (binfo) == RECORD_TYPE)
type = binfo;
else if (TREE_CODE (binfo) == UNION_TYPE)
return NULL_TREE;
else
my_friendly_abort (90);
......@@ -479,9 +481,10 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
}
else
{
int same_object = tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
BINFO_OFFSET (binfo));
int same_object = (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
BINFO_OFFSET (binfo))
&& *via_virtual_ptr && via_virtual);
if (*via_virtual_ptr && via_virtual==0)
{
*rval_private_ptr = is_private;
......@@ -2535,7 +2538,8 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
tree addr;
tree vtbl = BINFO_VTABLE (vbases);
tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
assemble_external (vtbl);
if (!flag_vtable_hack)
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
if (use_computed_offsets)
......@@ -2580,112 +2584,42 @@ static void
dfs_get_vbase_types (binfo)
tree binfo;
{
tree binfos = BINFO_BASETYPES (binfo);
tree type = BINFO_TYPE (binfo);
tree these_vbase_types = CLASSTYPE_VBASECLASSES (type);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
if (these_vbase_types)
{
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++)
if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
{
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. */
/* 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);
}
}
/* unmark marked vbases */
for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
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;
......
......@@ -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,42 +935,52 @@ hash_chainon (list1, list2)
hash_chainon (TREE_CHAIN (list1), list2));
}
tree
get_decl_list (value)
static tree
get_identifier_list (value)
tree value;
{
tree list = NULL_TREE;
if (TREE_CODE (value) == IDENTIFIER_NODE)
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)
{
list = IDENTIFIER_AS_LIST (value);
if (list != NULL_TREE
&& (TREE_CODE (list) != TREE_LIST
|| TREE_VALUE (list) != value))
tree type = IDENTIFIER_TYPE_VALUE (value);
if (TYPE_PTRMEMFUNC_P (type))
list = NULL_TREE;
else if (IDENTIFIER_HAS_TYPE_VALUE (value)
&& TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
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;
tree type = IDENTIFIER_TYPE_VALUE (value);
if (TYPE_PTRMEMFUNC_P (type))
list = NULL_TREE;
/* 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
{
/* 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);
}
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;
{
tree list = NULL_TREE;
if (TREE_CODE (value) == IDENTIFIER_NODE)
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)))
......
......@@ -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'",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment