45th Cygnus<->FSF merge

From-SVN: r7862
This commit is contained in:
Mike Stump 1994-08-05 20:25:20 +00:00
parent fd67d2b620
commit a292b002ee
18 changed files with 538 additions and 273 deletions

View File

@ -1,18 +1,148 @@
Fri Aug 5 01:12:20 1994 Mike Stump (mrs@cygnus.com)
* class.c (get_class_offset_1, get_class_offset): New routine to
find the offset of the class where a virtual function is defined,
from the complete type.
* class.c (modify_one_vtable, fixup_vtable_deltas): Use
get_class_offset instead of virtual_offset as get_class_offset will
always provide the right answer.
* tree.c (virtual_offset): Remove. It only ever worked some of the
time.
Tue Aug 2 12:44:21 1994 Jason Merrill (jason@deneb.cygnus.com)
* call.c (build_method_call): Put back unary_complex_lvalue call
that I thought was redundant.
* typeck.c (c_expand_return): Fix a case I missed before.
Sun Jul 31 17:54:02 1994 Jason Merrill (jason@deneb.cygnus.com)
* pt.c (unify): Strip cv-quals from template type arguments (when
'const T*' is matched to 'const char*', that does not mean that T is
'const char').
Fri Jul 29 01:03:06 1994 Jason Merrill (jason@deneb.cygnus.com)
* pt.c (do_type_instantiation): Instantiate nested TAGS, not
typedefs. Third time's the charm?
* parse.y (template_parm): Support default template parms.
* pt.c (process_template_parm): Ditto.
(end_template_parm_list): Ditto.
(coerce_template_parms): Ditto.
(mangle_class_name_for_template): Ditto.
(push_template_decls): Ditto.
(unify): Ditto.
* method.c (build_overload_identifier): Ditto.
* error.c (dump_decl): Ditto.
Wed Jul 27 17:47:00 1994 Jason Merrill (jason@deneb.cygnus.com)
* pt.c (do_type_instantiation): Only instantiate nested *classes*.
Tue Jul 26 13:22:40 1994 Jason Merrill (jason@deneb.cygnus.com)
* search.c (note_debug_info_needed): Also emit debugging information
for the types of fields.
Mon Jul 25 00:34:44 1994 Jason Merrill (jason@deneb.cygnus.com)
* pt.c (lookup_template_class): Pass 'template' to
coerce_template_parms instead of 'in_decl', since it's a more
meaningful context.
* typeck.c (c_expand_return): Make sure any cleanups for the return
expression get run.
(build_c_cast): Use CONVERT_EXPR for conversion to void.
* pt.c (do_type_instantiation): Also instantiate nested types.
* typeck.c (convert_for_assignment): Don't die when comparing
pointers with different levels of indirection.
* decl.c (grokdeclarator): The sub-call to grokdeclarator for
class-local typedefs sets DECL_ARGUMENTS, so we need to clear it
out.
* decl2.c (finish_anon_union): Don't die if the union has no
members.
* decl.c (grokdeclarator): Undo changes to declspecs when we're done
so that 'typedef int foo, bar;' will work.
* decl2.c (finish_file): Don't call expand_aggr_init for
non-aggregates.
Mon Jul 25 00:03:10 1994 Teemu Torma (tot@trema.fi)
* decl.c (finish_function): We can't inline constructors and
destructors under some conditions with -fpic, but don't unset
DECL_INLINE.
Mon Jul 25 00:03:10 1994 Jason Merrill (jason@deneb.cygnus.com)
* typeck.c (build_object_ref): Make sure 'datum' is a valid object.
Sun Jul 24 14:19:31 1994 Jason Merrill (jason@deneb.cygnus.com)
* class.c (finish_struct): Don't set DECL_FIELD_BITPOS on
non-fields.
(finish_struct_methods): Use copy_assignment_arg_p.
* cvt.c (cp_convert): If expr is an OFFSET_REF, resolve it instead
of giving an error.
* typeck.c (build_binary_op_nodefault): Don't set result_type if we
don't know how to compare the operands.
* decl.c (grokdeclarator): Avoid seg fault when someone uses '__op'
as a declarator-id in their program. Like the Linux headers do.
Arrgh.
* tree.c (lvalue_p): Treat calls to functions returning objects by
value as lvalues again.
* typeck.c (build_component_addr): Use convert_force to convert the
pointer in case the component type is also a private base class.
* search.c (get_matching_virtual): Fix bogus warning of overloaded
virtual.
* pt.c (overload_template_name): Set DECL_ARTIFICIAL on the created
TYPE_DECL to fix bogus shadowing warnings.
Fri Jul 22 01:15:32 1994 Jason Merrill (jason@deneb.cygnus.com)
* init.c (expand_aggr_init_1): const and volatile mismatches do not
prevent a TARGET_EXPR from initializing an object directly.
Tue Jul 19 17:55:37 1994 Jason Merrill (jason@deneb.cygnus.com)
* cvt.c (build_up_reference): Allow building up references to
`this', don't warn about making references to artificial variables
(like `this').
* tree.c (lvalue_p): `this' is not an lvalue.
* call.c (build_method_call): Accept using a typedef name (or
template type parameter) for explicit destructor calls.
Wed Jul 13 03:57:54 1994 Jason Merrill (jason@deneb.cygnus.com)
* method.c (hack_identifier): Put back old code so lists of
non-functions will be handled properly.
* method.c (hack_identifier): Put back old code so lists of
non-functions will be handled properly.
* cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now
defined in the language-independent tree.h.
* cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now
defined in the language-independent tree.h.
* tree.c (count_functions): Avoid bogus warning when compiling this
function.
* tree.c (count_functions): Avoid bogus warning when compiling this
function.
Mon Jul 11 18:37:20 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (grok_reference_init): Always save the initializer of a
reference.
* decl.c (grok_reference_init): Always save the initializer of a
reference.
Fri Jul 8 17:41:46 1994 Mike Stump (mrs@cygnus.com)
@ -36,7 +166,7 @@ Fri Jul 8 02:27:41 1994 Jason Merrill (jason@deneb.cygnus.com)
* decl.c (push_overloaded_decl): Don't create overloads of one when
shadowing a class type.
* typeck.c (build_x_function_call): Complain about overloads of one
* typeck.c (build_x_function_call): Complain about overloads of one.
* decl.c (grokdeclarator): Don't try to treat a char* as a tree.
(grokdeclarator): Fix setting of TREE_STATIC.

View File

@ -193,7 +193,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
`echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
@echo expect 1 shift/reduce confict and 33 reduce/reduce conflicts.
@echo expect 1 shift/reduce confict and 34 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h

View File

@ -1604,21 +1604,15 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (parms)
error ("destructors take no parameters");
basetype = TREE_TYPE (instance);
if (IS_AGGR_TYPE (basetype))
if (! ((IS_AGGR_TYPE (basetype)
&& name == constructor_name (basetype))
|| basetype == get_type_value (name)))
{
if (name == constructor_name (basetype))
goto huzzah;
cp_error ("destructor name `~%D' does not match type `%T' of expression",
name, basetype);
return void_zero_node;
}
else
{
if (basetype == get_type_value (name))
goto huzzah;
}
cp_error ("destructor name `~%D' does not match type `%T' of expression",
name, basetype);
return void_zero_node;
huzzah:
if (! TYPE_HAS_DESTRUCTOR (basetype))
return void_zero_node;
instance = default_conversion (instance);

View File

@ -1830,8 +1830,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
{
tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t)
if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields)))
{
if (TREE_PROTECTED (fn_fields))
TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1;
@ -2151,6 +2150,86 @@ overrides (fndecl, base_fndecl)
return 0;
}
static tree
get_class_offset_1 (parent, binfo, context, t, fndecl)
tree parent, binfo, context, t, fndecl;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree rval = NULL_TREE;
if (binfo == parent)
return error_mark_node;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree nrval;
if (TREE_VIA_VIRTUAL (base_binfo))
base_binfo = binfo_member (BINFO_TYPE (base_binfo),
CLASSTYPE_VBASECLASSES (t));
nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl);
/* See if we have a new value */
if (nrval && (nrval != error_mark_node || rval==0))
{
/* Only compare if we have two offsets */
if (rval && rval != error_mark_node
&& ! tree_int_cst_equal (nrval, rval))
{
/* Only give error if the two offsets are different */
error ("every virtual function must have a unique final overrider");
cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t);
cp_error (" with virtual `%D' from virtual base class", fndecl);
return rval;
}
rval = nrval;
}
if (rval && BINFO_TYPE (binfo) == context)
{
my_friendly_assert (rval == error_mark_node
|| tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999);
rval = BINFO_OFFSET (binfo);
}
}
return rval;
}
/* Get the offset to the CONTEXT subobject that is related to the
given BINFO. */
static tree
get_class_offset (context, t, binfo, fndecl)
tree context, t, binfo, fndecl;
{
tree first_binfo = binfo;
tree offset;
int i;
if (context == t)
return integer_zero_node;
if (BINFO_TYPE (binfo) == context)
return BINFO_OFFSET (binfo);
/* Check less derived binfos first. */
while (BINFO_BASETYPES (binfo)
&& (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
{
tree binfos = BINFO_BASETYPES (binfo);
binfo = TREE_VEC_ELT (binfos, i);
if (BINFO_TYPE (binfo) == context)
return BINFO_OFFSET (binfo);
}
/* Ok, not found in the less derived binfos, now check the more
derived binfos. */
offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl);
if (offset==0 || TREE_CODE (offset) != INTEGER_CST)
my_friendly_abort (999); /* we have to find it. */
return offset;
}
static void
modify_one_vtable (binfo, t, fndecl, pfn)
tree binfo, t, fndecl, pfn;
@ -2174,16 +2253,7 @@ modify_one_vtable (binfo, t, fndecl, pfn)
tree vfield = CLASSTYPE_VFIELD (t);
tree this_offset;
offset = integer_zero_node;
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
{
offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
if (offset == NULL_TREE)
{
tree binfo = get_binfo (context, t, 0);
offset = BINFO_OFFSET (binfo);
}
}
offset = get_class_offset (context, t, binfo, fndecl);
/* Find the right offset for the this pointer based on the
base class we just found. We have to take into
@ -2288,16 +2358,7 @@ fixup_vtable_deltas (binfo, t)
tree vfield = CLASSTYPE_VFIELD (t);
tree this_offset;
offset = integer_zero_node;
if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
{
offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
if (offset == NULL_TREE)
{
tree binfo = get_binfo (context, t, 0);
offset = BINFO_OFFSET (binfo);
}
}
offset = get_class_offset (context, t, binfo, fndecl);
/* Find the right offset for the this pointer based on the
base class we just found. We have to take into
@ -3498,6 +3559,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
for (; uelt; uelt = TREE_CHAIN (uelt))
{
if (TREE_CODE (uelt) != FIELD_DECL)
continue;
DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field);
DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field);
}
@ -3552,6 +3616,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
for (; uelt; uelt = TREE_CHAIN (uelt))
{
if (TREE_CODE (uelt) != FIELD_DECL)
continue;
DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field);
DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field);
}

View File

@ -2254,7 +2254,6 @@ extern tree copy_binfo PROTO((tree));
extern tree binfo_value PROTO((tree, tree));
extern tree reverse_path PROTO((tree));
extern tree virtual_member PROTO((tree, tree));
extern tree virtual_offset PROTO((tree, tree, tree));
extern void debug_binfo PROTO((tree));
extern int decl_list_length PROTO((tree));
extern int count_functions PROTO((tree));

View File

@ -425,10 +425,11 @@ build_up_reference (type, arg, flags, checkconst)
break;
case PARM_DECL:
#if 0
if (targ == current_class_decl)
{
error ("address of `this' not available");
#if 0
/* #if 0 */
/* This code makes the following core dump the compiler on a sun4,
if the code below is used.
@ -465,16 +466,18 @@ build_up_reference (type, arg, flags, checkconst)
TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */
put_var_into_stack (targ);
break;
#else
/* #else */
return error_mark_node;
#endif
/* #endif */
}
#endif
/* Fall through. */
case VAR_DECL:
case CONST_DECL:
if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ))
warning ("address needed to build reference for `%s', which is declared `register'",
IDENTIFIER_POINTER (DECL_NAME (targ)));
if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ)
&& !DECL_ARTIFICIAL (targ))
cp_warning ("address needed to build reference for `%D', which is declared `register'",
targ);
else if (staticp (targ))
literal_flag = 1;
@ -1206,6 +1209,9 @@ cp_convert (type, expr, convtype, flags)
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
if (TREE_CODE (e) == OFFSET_REF)
e = resolve_offset_ref (e);
if (TREE_READONLY_DECL_P (e))
e = decl_constant_value (e);
@ -1223,10 +1229,7 @@ cp_convert (type, expr, convtype, flags)
if (flag_pedantic_errors)
return error_mark_node;
}
if (form == OFFSET_TYPE)
cp_error_at ("pointer-to-member expression object not composed with type `%D' object",
TYPE_NAME (TYPE_OFFSET_BASETYPE (intype)));
else if (IS_AGGR_TYPE (intype))
if (IS_AGGR_TYPE (intype))
{
tree rval;
rval = build_type_conversion (CONVERT_EXPR, type, e, 1);

View File

@ -7091,7 +7091,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
dname = decl;
decl = NULL_TREE;
if (IDENTIFIER_OPNAME_P (dname))
if (! IDENTIFIER_OPNAME_P (dname)
/* Linux headers use '__op'. Arrgh. */
|| IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname))
name = IDENTIFIER_POINTER (dname);
else
{
if (IDENTIFIER_TYPENAME_P (dname))
{
@ -7102,8 +7106,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
name = operator_name_string (dname);
}
else
name = IDENTIFIER_POINTER (dname);
break;
case RECORD_TYPE:
@ -7688,17 +7690,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
break;
}
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]);
}
if (previous_declspec)
TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
else
TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC];
declspecs = TREE_CHAIN (scanner);
declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
declspecs);
/* In the recursive call to grokdeclarator we need to know
whether we are working on a signature-local typedef. */
@ -7707,6 +7705,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
loc_typedecl =
grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE);
if (previous_declspec)
TREE_CHAIN (previous_declspec) = scanner;
if (loc_typedecl != error_mark_node)
{
@ -7714,6 +7715,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
register int *pi;
TREE_SET_CODE (loc_typedecl, TYPE_DECL);
/* This is the same field as DECL_ARGUMENTS, which is set for
function typedefs by the above grokdeclarator. */
DECL_NESTED_TYPENAME (loc_typedecl) = 0;
pi = (int *) permalloc (sizeof (struct lang_decl_flags));
while (i > 0)
@ -11529,20 +11533,19 @@ finish_function (lineno, call_poplevel)
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
/* ??? Compensate for Sun brain damage in dealing with data segments
of PIC code. */
if (flag_pic
&& (DECL_CONSTRUCTOR_P (fndecl)
|| DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
&& CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))
DECL_INLINE (fndecl) = 0;
if (DECL_EXTERNAL (fndecl)
/* This function is just along for the ride. If we can make
it inline, that's great. Otherwise, just punt it. */
&& (DECL_INLINE (fndecl) == 0
|| flag_no_inline
|| function_cannot_inline_p (fndecl)))
|| function_cannot_inline_p (fndecl)
/* ??? Compensate for Sun brain damage in dealing with
data segments of PIC code. */
|| (flag_pic
&& (DECL_CONSTRUCTOR_P (fndecl)
|| DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
&& CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))))
{
extern int rtl_dump_and_exit;
int old_rtl_dump_and_exit = rtl_dump_and_exit;

View File

@ -2100,8 +2100,16 @@ finish_anon_union (anon_union_decl)
}
if (static_p)
{
make_decl_rtl (main_decl, 0, global_bindings_p ());
DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
if (main_decl)
{
make_decl_rtl (main_decl, 0, global_bindings_p ());
DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
}
else
{
warning ("anonymous union with no members");
return;
}
}
/* The following call assumes that there are never any cleanups
@ -2712,7 +2720,6 @@ finish_file ()
}
}
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| init == 0
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0);
else if (TREE_CODE (init) == TREE_VEC)

View File

@ -671,13 +671,22 @@ dump_decl (t, v)
for (i = 0; i < len; i++)
{
tree arg = TREE_VEC_ELT (args, i);
if (TREE_CODE (arg) == IDENTIFIER_NODE)
tree defval = TREE_PURPOSE (arg);
arg = TREE_VALUE (arg);
if (TREE_CODE (arg) == TYPE_DECL)
{
OB_PUTS ("class ");
OB_PUTID (arg);
OB_PUTID (DECL_NAME (arg));
}
else
dump_decl (arg, 1);
if (defval)
{
OB_PUTS (" = ");
dump_decl (defval, 1);
}
OB_PUTC2 (',', ' ');
}
OB_UNPUT (2);

View File

@ -1392,7 +1392,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
separately from the object being initialized. */
if (TREE_CODE (init) == TARGET_EXPR)
{
if (init_type == type)
if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
{
if (TREE_CODE (exp) == VAR_DECL
|| TREE_CODE (exp) == RESULT_DECL)

View File

@ -2875,7 +2875,7 @@ linenum:
if (c_header_level && --c_header_level == 0)
{
if (entering_c_header)
warning ("Badly nested C headers from preprocessor");
warning ("badly nested C headers from preprocessor");
--pending_lang_change;
}
if (flag_cadillac)

View File

@ -463,9 +463,9 @@ build_overload_identifier (name)
icat (nparms);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VEC_ELT (parmlist, i);
tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i);
if (TREE_CODE (parm) == IDENTIFIER_NODE)
if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
OB_PUTC ('Z');

View File

@ -221,7 +221,7 @@ empty_parms ()
%type <ttype> type_id absdcl type_quals
%type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_type_id new_declarator direct_new_declarator
%type <ttype> xexpr parmlist parms parm bad_parm
%type <ttype> xexpr parmlist parms parm bad_parm full_parm
%type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr
%type <ttype> expr_or_declarator complex_notype_declarator
@ -250,6 +250,7 @@ empty_parms ()
%type <ttype> nonmomentary_expr
%type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list
%type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type_parm
%type <ttype> template_type template_arg_list template_arg
%type <ttype> template_instantiation template_type_name tmpl.2
%type <ttype> template_instantiate_once template_instantiate_some
@ -373,6 +374,20 @@ template_parm_list:
{ $$ = process_template_parm ($1, $3); }
;
template_type_parm:
aggr
{
$$ = build_tree_list ($1, NULL_TREE);
ttpa:
if (TREE_PURPOSE ($$) == signature_type_node)
sorry ("signature as template type parameter");
else if (TREE_PURPOSE ($$) != class_type_node)
pedwarn ("template type parameters must use the keyword `class'");
}
| aggr identifier
{ $$ = build_tree_list ($1, $2); goto ttpa; }
;
template_parm:
/* The following rules introduce a new reduce/reduce
conflict on the ',' and '>' input tokens: they are valid
@ -381,24 +396,11 @@ template_parm:
By putting them before the `parm' rule, we get
their match before considering them nameless parameter
declarations. */
aggr identifier
{
if ($1 == signature_type_node)
sorry ("signature as template type parameter");
else if ($1 != class_type_node)
error ("template type parameter must use keyword `class'");
$$ = build_tree_list ($2, NULL_TREE);
}
| aggr identifier_defn ':' base_class.1
{
if ($1 == signature_type_node)
sorry ("signature as template type parameter");
else if ($1 != class_type_node)
error ("template type parameter must use keyword `class'");
warning ("restricted template type parameters not yet implemented");
$$ = build_tree_list ($2, $4);
}
| parm
template_type_parm
{ $$ = build_tree_list (NULL_TREE, $$); }
| template_type_parm '=' typespec
{ $$ = build_tree_list ($3, $$); }
| full_parm
;
overloaddef:
@ -782,6 +784,8 @@ template_type:
template_type_name:
PTYPENAME '<' template_arg_list '>'
{ $$ = lookup_template_class ($$, $3, NULL_TREE); }
| PTYPENAME '<' '>'
{ $$ = lookup_template_class ($$, NULL_TREE, NULL_TREE); }
| TYPENAME '<' template_arg_list '>'
{ $$ = lookup_template_class ($$, $3, NULL_TREE); }
;
@ -3550,10 +3554,8 @@ parms:
{ $$ = build_tree_list (NULL_TREE, $$); }
| parm '=' init
{ $$ = build_tree_list ($3, $$); }
| parms_comma parm
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
| parms_comma parm '=' init
{ $$ = chainon ($$, build_tree_list ($4, $2)); }
| parms_comma full_parm
{ $$ = chainon ($$, $2); }
| parms_comma bad_parm
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
| parms_comma bad_parm '=' init
@ -3599,6 +3601,13 @@ named_parm:
{ $$ = build_tree_list ($$, $2); }
;
full_parm:
parm
{ $$ = build_tree_list (NULL_TREE, $$); }
| parm '=' init
{ $$ = build_tree_list ($3, $$); }
;
parm:
named_parm
| type_id

View File

@ -81,18 +81,19 @@ process_template_parm (list, next)
{
tree parm;
tree decl = 0;
tree defval;
int is_type;
parm = next;
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
is_type = TREE_CODE (TREE_PURPOSE (parm)) == IDENTIFIER_NODE;
defval = TREE_PURPOSE (parm);
parm = TREE_VALUE (parm);
is_type = TREE_PURPOSE (parm) == class_type_node;
if (!is_type)
{
tree tinfo = 0;
parm = TREE_PURPOSE (parm);
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 260);
parm = TREE_VALUE (parm);
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
parm = grokdeclarator (TREE_VALUE (next), TREE_PURPOSE (next),
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL_TREE);
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
@ -117,11 +118,19 @@ process_template_parm (list, next)
else
{
tree t = make_node (TEMPLATE_TYPE_PARM);
decl = build_decl (TYPE_DECL, TREE_PURPOSE (parm), t);
TYPE_NAME (t) = decl;
TREE_VALUE (parm) = t;
decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);
TYPE_MAIN_DECL (t) = decl;
parm = decl;
if (defval)
{
if (IDENTIFIER_HAS_TYPE_VALUE (defval))
defval = IDENTIFIER_TYPE_VALUE (defval);
else
defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
}
}
pushdecl (decl);
parm = build_tree_list (defval, parm);
return chainon (list, parm);
}
@ -135,6 +144,7 @@ end_template_parm_list (parms)
tree parms;
{
int nparms = 0;
int saw_default = 0;
tree saved_parmlist;
tree parm;
for (parm = parms; parm; parm = TREE_CHAIN (parm))
@ -143,13 +153,19 @@ end_template_parm_list (parms)
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
{
tree p = parm;
if (TREE_CODE (p) == TREE_LIST)
tree p = TREE_VALUE (parm);
if (TREE_PURPOSE (parm))
saw_default = 1;
else if (saw_default)
{
tree t = TREE_VALUE (p);
TREE_VALUE (p) = NULL_TREE;
p = TREE_PURPOSE (p);
my_friendly_assert (TREE_CODE (p) == IDENTIFIER_NODE, 261);
error ("if a default argument is given for one template parameter");
error ("default arguments must be given for all subsequent");
error ("parameters as well");
}
if (TREE_CODE (p) == TYPE_DECL)
{
tree t = TREE_TYPE (p);
TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms);
}
else
@ -158,7 +174,7 @@ end_template_parm_list (parms)
DECL_INITIAL (p) = NULL_TREE;
TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms);
}
TREE_VEC_ELT (saved_parmlist, nparms) = p;
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
}
set_current_level_tags_transparency (1);
processing_template_decl++;
@ -354,47 +370,63 @@ coerce_template_parms (parms, arglist, in_decl)
tree parms, arglist;
tree in_decl;
{
int nparms, i, lost = 0;
int nparms, nargs, i, lost = 0;
tree vec;
if (TREE_CODE (arglist) == TREE_VEC)
nparms = TREE_VEC_LENGTH (arglist);
if (arglist == NULL_TREE)
nargs = 0;
else if (TREE_CODE (arglist) == TREE_VEC)
nargs = TREE_VEC_LENGTH (arglist);
else
nparms = list_length (arglist);
if (nparms != TREE_VEC_LENGTH (parms))
nargs = list_length (arglist);
nparms = TREE_VEC_LENGTH (parms);
if (nargs > nparms
|| (nargs < nparms
&& TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
{
error ("incorrect number of parameters (%d, should be %d)",
nparms, TREE_VEC_LENGTH (parms));
nargs, nparms);
if (in_decl)
cp_error_at ("in template expansion for decl `%D'", in_decl);
return error_mark_node;
}
if (TREE_CODE (arglist) == TREE_VEC)
if (arglist && TREE_CODE (arglist) == TREE_VEC)
vec = copy_node (arglist);
else
{
vec = make_tree_vec (nparms);
for (i = 0; i < nparms; i++)
{
tree arg = arglist;
arglist = TREE_CHAIN (arglist);
if (arg == error_mark_node)
lost++;
tree arg;
if (arglist)
{
arg = arglist;
arglist = TREE_CHAIN (arglist);
if (arg == error_mark_node)
lost++;
else
arg = TREE_VALUE (arg);
}
else
arg = TREE_VALUE (arg);
arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
TREE_VEC_ELT (vec, i) = arg;
}
}
for (i = 0; i < nparms; i++)
{
tree arg = TREE_VEC_ELT (vec, i);
tree parm = TREE_VEC_ELT (parms, i);
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree val = 0;
int is_type, requires_type;
is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
requires_type = TREE_CODE (parm) == TYPE_DECL;
if (is_type != requires_type)
{
if (in_decl)
@ -415,7 +447,7 @@ coerce_template_parms (parms, arglist, in_decl)
{
grok_template_type (vec, &TREE_TYPE (parm));
val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
if (val == error_mark_node)
;
@ -489,12 +521,13 @@ mangle_class_name_for_template (name, parms, arglist)
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VEC_ELT (parms, i), arg = TREE_VEC_ELT (arglist, i);
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree arg = TREE_VEC_ELT (arglist, i);
if (i)
ccat (',');
if (TREE_CODE (parm) == IDENTIFIER_NODE)
if (TREE_CODE (parm) == TYPE_DECL)
{
cat (type_as_string (arg, 0));
continue;
@ -573,7 +606,7 @@ lookup_template_class (d1, arglist, in_decl)
}
parmlist = DECL_TEMPLATE_PARMS (template);
arglist = coerce_template_parms (parmlist, arglist, in_decl);
arglist = coerce_template_parms (parmlist, arglist, template);
if (arglist == error_mark_node)
return error_mark_node;
if (uses_template_parms (arglist))
@ -619,11 +652,11 @@ push_template_decls (parmlist, arglist, class_level)
for (i = 0; i < nparms; i++)
{
int requires_type, is_type;
tree parm = TREE_VEC_ELT (parmlist, i);
tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i);
tree decl = 0;
requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
requires_type = TREE_CODE (parm) == TYPE_DECL;
is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
if (is_type)
{
@ -635,7 +668,7 @@ push_template_decls (parmlist, arglist, class_level)
}
decl = arg;
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
decl = build_decl (TYPE_DECL, parm, decl);
decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl);
}
else
{
@ -878,9 +911,8 @@ instantiate_member_templates (classname)
case 1:
/* Failure. */
failure:
cp_error ("type unification error instantiating %T::%D",
classname, tdecl);
cp_error_at ("for template declaration `%D'", tdecl);
cp_error_at ("type unification error instantiating `%D'", tdecl);
cp_error ("while instantiating members of `%T'", classname);
continue /* loop of members */;
default:
@ -1781,6 +1813,7 @@ overload_template_name (id, classlevel)
|| TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
decl = build_decl (TYPE_DECL, template, t);
SET_DECL_ARTIFICIAL (decl);
#if 0 /* fix this later */
/* We don't want to call here if the work has already been done. */
@ -2035,22 +2068,20 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 1;
}
idx = TEMPLATE_TYPE_IDX (parm);
/* Template type parameters cannot contain cv-quals; i.e.
template <class T> void f (T& a, T& b) will not generate
void f (const int& a, const int& b). */
if (TYPE_READONLY (arg) > TYPE_READONLY (parm)
|| TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))
return 1;
arg = TYPE_MAIN_VARIANT (arg);
/* Simple cases: Value already set, does match or doesn't. */
if (targs[idx] == arg)
return 0;
else if (targs[idx])
{
if (TYPE_MAIN_VARIANT (targs[idx]) == TYPE_MAIN_VARIANT (arg))
/* allow different parms to have different cv-qualifiers */;
else
return 1;
}
/* Check for mixed types and values. */
if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE)
return 1;
/* Allow trivial conversions. */
if (TYPE_READONLY (parm) < TYPE_READONLY (arg)
|| TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
/* Check for mixed types and values. */
if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
return 1;
targs[idx] = arg;
return 0;
@ -2399,12 +2430,11 @@ do_type_instantiation (name, storage)
tree t = TREE_TYPE (name);
int extern_p;
/* With -fexternal-templates, explicit instantiations are treated the same
as implicit ones. */
if (flag_external_templates)
return;
if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t))
return;
if (TYPE_SIZE (t) == NULL_TREE)
{
cp_error ("explicit instantiation of `%#T' before definition of template",
@ -2423,6 +2453,14 @@ do_type_instantiation (name, storage)
extern_p = 0;
}
/* We've already instantiated this. */
if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t))
{
if (! extern_p)
cp_pedwarn ("multiple explicit instantiation of `%#T'", t);
return;
}
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
SET_CLASSTYPE_INTERFACE_KNOWN (t);
@ -2436,17 +2474,26 @@ do_type_instantiation (name, storage)
/* this should really be done by instantiate_member_templates */
{
tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; method; method = TREE_CHAIN (method))
tree tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; tmp; tmp = TREE_CHAIN (tmp))
{
SET_DECL_EXPLICIT_INSTANTIATION (method);
TREE_PUBLIC (method) = 1;
DECL_EXTERNAL (method)
= (extern_p || (DECL_INLINE (method) && ! flag_implement_inlines));
SET_DECL_EXPLICIT_INSTANTIATION (tmp);
TREE_PUBLIC (tmp) = 1;
DECL_EXTERNAL (tmp)
= (extern_p || (DECL_INLINE (tmp) && ! flag_implement_inlines));
}
}
/* and data member templates, too */
#if 0
for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
{
if (TREE_CODE (tmp) == VAR_DECL)
/* eventually do something */;
}
#endif
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
do_type_instantiation (TREE_VALUE (tmp), storage);
}
}
tree

View File

@ -1913,6 +1913,10 @@ get_matching_virtual (binfo, fndecl, dtorp)
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
return NULL_TREE;
baselink = get_virtuals_named_this (binfo);
if (baselink == NULL_TREE)
return NULL_TREE;
drettype = TREE_TYPE (TREE_TYPE (fndecl));
dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
if (DECL_STATIC_FUNCTION_P (fndecl))
@ -1920,8 +1924,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
else
instptr_type = TREE_TYPE (TREE_VALUE (dtypes));
for (baselink = get_virtuals_named_this (binfo);
baselink; baselink = next_baselink (baselink))
for (; baselink; baselink = next_baselink (baselink))
{
for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp))
{
@ -1945,7 +1948,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
&& ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
{
cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
cp_error ("overriding definition as `%#D'", tmp);
cp_error_at ("overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
break;
@ -2697,13 +2700,22 @@ free_mi_matrix ()
/* If we want debug info for a type TYPE, make sure all its base types
are also marked as being potentially interesting. This avoids
the problem of not writing any debug info for intermediate basetypes
that have abstract virtual functions. */
that have abstract virtual functions. Also mark member types. */
void
note_debug_info_needed (type)
tree type;
{
tree field;
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
tree ttype;
if (TREE_CODE (field) == FIELD_DECL
&& IS_AGGR_TYPE (ttype = target_type (TREE_TYPE (field)))
&& dfs_debug_unmarkedp (TYPE_BINFO (ttype)))
note_debug_info_needed (ttype);
}
}
/* Subroutines of push_class_decls (). */

View File

@ -35,66 +35,75 @@ int
lvalue_p (ref)
tree ref;
{
register enum tree_code code = TREE_CODE (ref);
if (! language_lvalue_valid (ref))
return 0;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
if (language_lvalue_valid (ref))
if (ref == current_class_decl && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
return 1;
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
switch (code)
{
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
break;
case STRING_CST:
return 1;
case WITH_CLEANUP_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref))
return 0;
case INDIRECT_REF:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
case TARGET_EXPR:
return 1;
case TARGET_EXPR:
case WITH_CLEANUP_EXPR:
return 1;
case CALL_EXPR:
if (TREE_ADDRESSABLE (TREE_TYPE (ref)))
return 1;
break;
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
return lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1));
break;
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
return lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 1))
&& lvalue_p (TREE_OPERAND (ref, 2)));
case COND_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 1))
&& lvalue_p (TREE_OPERAND (ref, 2)));
case MODIFY_EXPR:
return 1;
case MODIFY_EXPR:
return 1;
case COMPOUND_EXPR:
return lvalue_p (TREE_OPERAND (ref, 1));
}
case COMPOUND_EXPR:
return lvalue_p (TREE_OPERAND (ref, 1));
}
return 0;
}
@ -1184,50 +1193,6 @@ virtual_member (elem, list)
return rval;
}
/* Return the offset (as an INTEGER_CST) for ELEM in LIST.
INITIAL_OFFSET is the value to add to the offset that ELEM's
binfo entry in LIST provides.
Returns NULL if ELEM does not have an binfo value in LIST. */
tree
virtual_offset (elem, list, initial_offset)
tree elem;
tree list;
tree initial_offset;
{
tree vb, offset;
tree rval, nval;
for (vb = list; vb; vb = TREE_CHAIN (vb))
if (elem == BINFO_TYPE (vb))
return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb));
rval = 0;
for (vb = list; vb; vb = TREE_CHAIN (vb))
{
tree binfos = BINFO_BASETYPES (vb);
int i;
if (binfos == NULL_TREE)
continue;
for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
{
nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
if (nval)
{
if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
my_friendly_abort (105);
offset = BINFO_OFFSET (vb);
rval = nval;
}
}
}
if (rval == NULL_TREE)
return rval;
return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval));
}
void
debug_binfo (elem)
tree elem;

View File

@ -1410,8 +1410,19 @@ tree
build_object_ref (datum, basetype, field)
tree datum, basetype, field;
{
tree dtype;
if (datum == error_mark_node)
return error_mark_node;
dtype = TREE_TYPE (datum);
if (TREE_CODE (dtype) == REFERENCE_TYPE)
dtype = TREE_TYPE (dtype);
if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))
{
cp_error ("request for member `%T::%D' in expression of non-aggregate type `%T'",
basetype, field, dtype);
return error_mark_node;
}
else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype)))
{
warning ("signature name in scope resolution ignored");
@ -3247,6 +3258,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
result_type = bool_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
@ -3295,7 +3307,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
warning ("comparison between pointer and integer");
op0 = convert (TREE_TYPE (op1), op0);
}
result_type = bool_type_node;
else
result_type = 0;
converted = 1;
break;
}
@ -3717,7 +3730,7 @@ build_component_addr (arg, argtype, msg)
}
else
/* This conversion is harmless. */
rval = convert (argtype, rval);
rval = convert_force (argtype, rval);
if (! integer_zerop (DECL_FIELD_BITPOS (field)))
{
@ -4939,7 +4952,7 @@ build_c_cast (type, expr)
value = TREE_VALUE (value);
if (TREE_CODE (type) == VOID_TYPE)
value = build1 (NOP_EXPR, type, value);
value = build1 (CONVERT_EXPR, type, value);
else if (TREE_TYPE (value) == NULL_TREE
|| type_unknown_p (value))
{
@ -6445,7 +6458,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
add_quals = 1;
left_const &= TYPE_READONLY (ttl);
if (TREE_CODE (ttl) != POINTER_TYPE)
if (TREE_CODE (ttl) != POINTER_TYPE
|| TREE_CODE (ttr) != POINTER_TYPE)
break;
}
unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr);
@ -7028,6 +7042,7 @@ c_expand_return (retval)
&& TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR)
retval = TREE_OPERAND (retval, 0);
expand_aggr_init (result, retval, 0);
expand_cleanups_to (NULL_TREE);
DECL_INITIAL (result) = NULL_TREE;
retval = 0;
}
@ -7046,6 +7061,7 @@ c_expand_return (retval)
&& any_pending_cleanups (1))
{
retval = get_temp_regvar (valtype, retval);
expand_cleanups_to (NULL_TREE);
use_temp = obey_regdecls;
result = 0;
}
@ -7071,7 +7087,10 @@ c_expand_return (retval)
{
/* Everything's great--RETVAL is in RESULT. */
if (original_result_rtx)
store_expr (result, original_result_rtx, 0);
{
store_expr (result, original_result_rtx, 0);
expand_cleanups_to (NULL_TREE);
}
else if (retval && retval != result)
{
/* Clear this out so the later call to decl_function_context
@ -7083,6 +7102,7 @@ c_expand_return (retval)
RESULT from cleanups. */
retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
TREE_SIDE_EFFECTS (retval) = 1;
retval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), retval);
expand_return (retval);
}
else

View File

@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
/* First used: 0 (reserved), Last used: 360. Free: */
/* First used: 0 (reserved), Last used: 360. Free: 261. */
static int abortcount = 0;