Commit 2ee887f2 by Mike Stump

81st Cygnus<->FSF merge

From-SVN: r11187
parent 258ae59d
Thu Feb 8 15:15:14 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokfndecl): Move code that looks for virtuals in base
classes...
* class.c (fixup_virtual): ... to a new function.
(finish_struct_1): Call it.
* cp-tree.h: Declare warn_sign_compare.
* typeck.c (build_binary_op_nodefault): Check warn_sign_compare
rather than extra_warnings to decide whether to warn about
comparison of signed and unsigned.
* decl2.c (lang_decode_option): Handle warn_sign_compare. -Wall
implies -Wsign-compare. -Wall doesn't imply -W.
Wed Feb 7 15:27:57 1996 Mike Stump <mrs@cygnus.com>
* typeck.c (build_component_ref): Fix to handle anon unions in base
classes as well.
Wed Feb 7 14:29:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* class.c (resolves_to_fixed_type_p): Delete code dealing with
a WITH_CLEANUP_EXPR, since we don't generate them any more.
* cvt.c (build_up_reference): Likewise.
* decl.c (grok_reference_init): Likewise.
(cp_finish_decl): Likewise.
* error.c (dump_expr): Likewise.
* tree.c (real_lvalue_p): Likewise.
(lvalue_p): Likewise.
(build_cplus_new): Likewise.
(unsave_expr_now): Likewise.
* typeck.c (unary_complex_lvalue, build_modify_expr,
c_expand_return): Likewise.
Tue Feb 6 13:39:22 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
Make the C++ front-end pay attention to attributes for structures.
* class.c (finish_struct): New argument ATTRIBUTES, passed down into
finish_struct_1.
(finish_struct_1): New argument ATTRIBUTES; call cplus_decl_attributes.
Take out old round_up_size use and setting the DECL_ALIGN possibly
using it. Take out setting of TYPE_ALIGN to round_up_size, which
can override what the attribute set.
* cp-tree.h (finish_struct): Update prototype.
* parse.y (template_instantiate_once): Pass a NULL_TREE for the
attributes to finish_struct.
(structsp): For a CLASS decl, add maybe_attribute to rule and pass that
value down into finish_struct.
* Makefile.in (CONFLICTS): Switch to 7 shift/reduce conflicts.
Tue Feb 6 13:12:15 1996 Per Bothner <bothner@kalessin.cygnus.com>
* decl.c (poplevel): Re-word dead for local handling.
(pushdecl): Remove useless DECL_DEAD_FOR_LOCAL test.
(cp_finish_decl): If is_for_scope, check for duplicates so
we can disable is_for_scope. Otherwise, preserve_temp_slots.
* lex.c (do_identifier): Use global binding in preference of
dead for local variable.
Mon Feb 5 17:46:46 1996 Mike Stump <mrs@cygnus.com>
* init.c (initializing_context): Handle anon union changes, the
context where fields of anon unions can be initialized now has to be
found by walking up the TYPE_CONTEXT chain.
Fri Feb 2 14:54:04 1996 Doug Evans <dje@charmed.cygnus.com>
* decl.c (start_decl): #ifdef out code to set DECL_COMMON
if ASM_OUTPUT{,_ALIGNED}_BSS is defined.
(obscure_complex_init): If bss is supported, always set
DECL_INITIAL to error_mark_node.
Thu Feb 1 16:19:56 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
* init.c (is_friend): Make sure there's a context before we see if
it's an aggr type.
Thu Feb 1 15:44:53 1996 Mike Stump <mrs@cygnus.com>
* init.c (is_friend): Classes are not friendly with nested classes.
Thu Feb 1 15:27:37 1996 Doug Evans <dje@charmed.cygnus.com>
* lex.c (check_newline): Pass last character read to HANDLE_PRAGMA,
and record its result.
Thu Feb 1 09:27:01 1996 Mike Stump <mrs@cygnus.com>
* class.c (finish_struct_anon): Switch around code to not move anon
......@@ -10187,9 +10276,3 @@ Mon Nov 8 13:50:49 1993 Jason Merrill (jason@deneb.cygnus.com)
Tue Sep 7 20:03:33 1993 Jason Merrill (jason@deneb.cygnus.com)
* cp-decl.c: Allow references and template type parameters as well
Local Variables:
eval: (auto-fill-mode)
left-margin: 8
fill-column: 76
End:
......@@ -196,7 +196,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
CONFLICTS = expect 5 shift/reduce conflicts and 38 reduce/reduce conflicts.
CONFLICTS = expect 7 shift/reduce conflicts and 38 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y
@echo $(CONFLICTS)
......
......@@ -2753,6 +2753,77 @@ mark_overriders (fndecl, base_fndecls)
}
}
/* If this declaration supersedes the declaration of
a method declared virtual in the base class, then
mark this field as being virtual as well. */
void
fixup_virtual (decl, ctype)
tree decl, ctype;
{
tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int virtualp = DECL_VIRTUAL_P (decl);
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo))
|| flag_all_virtual == 1)
{
tree tmp = get_matching_virtual
(base_binfo, decl,
DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
if (tmp)
{
/* If this function overrides some virtual in some base
class, then the function itself is also necessarily
virtual, even if the user didn't explicitly say so. */
DECL_VIRTUAL_P (decl) = 1;
/* The TMP we really want is the one from the deepest
baseclass on this path, taking care not to
duplicate if we have already found it (via another
path to its virtual baseclass. */
if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
{
cp_error_at ("method `%D' may not be declared static",
decl);
cp_error_at ("(since `%D' declared virtual in base class.)",
tmp);
break;
}
virtualp = 1;
{
/* The argument types may have changed... */
tree type = TREE_TYPE (decl);
tree argtypes = TYPE_ARG_TYPES (type);
tree base_variant = TREE_TYPE (TREE_VALUE (argtypes));
tree raises = TYPE_RAISES_EXCEPTIONS (type);
argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))),
TREE_CHAIN (argtypes));
/* But the return type has not. */
type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
if (raises)
type = build_exception_variant (type, raises);
TREE_TYPE (decl) = type;
DECL_VINDEX (decl)
= tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
}
break;
}
}
}
if (virtualp)
{
if (DECL_VINDEX (decl) == NULL_TREE)
DECL_VINDEX (decl) = error_mark_node;
IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
}
}
/* Warn about hidden virtual functions that are not overridden in t. */
void
warn_hidden (t)
......@@ -2889,6 +2960,8 @@ extern int interface_only, interface_unknown;
TREE_LIST elements, whose TREE_PURPOSE field tells what access
the list has, and the TREE_VALUE slot gives the actual fields.
ATTRIBUTES is the set of decl attributes to be applied, if any.
If flag_all_virtual == 1, then we lay all functions into
the virtual function table, as though they were declared
virtual. Constructors do not lay down in the virtual function table.
......@@ -2920,13 +2993,11 @@ extern int interface_only, interface_unknown;
or otherwise in a type-consistent manner. */
tree
finish_struct_1 (t, warn_anon)
tree t;
finish_struct_1 (t, attributes, warn_anon)
tree t, attributes;
int warn_anon;
{
int old;
int round_up_size = 1;
tree name = TYPE_IDENTIFIER (t);
enum tree_code code = TREE_CODE (t);
tree fields = TYPE_FIELDS (t);
......@@ -2986,6 +3057,8 @@ finish_struct_1 (t, warn_anon)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
cplus_decl_attributes (t, attributes, NULL_TREE);
#if 0
/* This is in general too late to do this. I moved the main case up to
left_curly, what else needs to move? */
......@@ -3104,6 +3177,8 @@ finish_struct_1 (t, warn_anon)
DECL_SAVED_INSNS (x) = NULL_RTX;
DECL_FIELD_SIZE (x) = 0;
fixup_virtual (x, t);
/* The name of the field is the original field name
Save this in auxiliary field for later overloading. */
if (DECL_VINDEX (x)
......@@ -3329,13 +3404,7 @@ finish_struct_1 (t, warn_anon)
if (width == 0)
{
#ifdef EMPTY_FIELD_BOUNDARY
/* field size 0 => mark following field as "aligned" */
if (TREE_CHAIN (x))
DECL_ALIGN (TREE_CHAIN (x))
= MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY);
/* field of size 0 at the end => round up the size. */
else
round_up_size = EMPTY_FIELD_BOUNDARY;
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
#endif
#ifdef PCC_BITFIELD_TYPE_MATTERS
DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
......@@ -3716,10 +3785,6 @@ finish_struct_1 (t, warn_anon)
TYPE_FIELDS (t) = fields;
/* If there's a :0 field at the end, round the size to the
EMPTY_FIELD_BOUNDARY. */
TYPE_ALIGN (t) = round_up_size;
/* Pass layout information about base classes to layout_type, if any. */
if (n_baseclasses)
{
......@@ -4168,9 +4233,8 @@ finish_struct_1 (t, warn_anon)
}
tree
finish_struct (t, list_of_fieldlists, warn_anon)
tree t;
tree list_of_fieldlists;
finish_struct (t, list_of_fieldlists, attributes, warn_anon)
tree t, list_of_fieldlists, attributes;
int warn_anon;
{
tree fields = NULL_TREE;
......@@ -4301,7 +4365,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
return t;
}
else
return finish_struct_1 (t, warn_anon);
return finish_struct_1 (t, attributes, warn_anon);
}
/* Return non-zero if the effective type of INSTANCE is static.
......@@ -4374,10 +4438,6 @@ resolves_to_fixed_type_p (instance, nonnull)
case COMPONENT_REF:
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull);
case WITH_CLEANUP_EXPR:
if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
/* fall through... */
case VAR_DECL:
case FIELD_DECL:
if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE
......
......@@ -37,7 +37,7 @@ DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2)
/* For a UNSAVE_EXPR, operand 0 is the value to unsave. By unsave, we
mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs,
WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs, that are protected
CALL_EXPRs and RTL_EXPRs, that are protected
from being evaluated more than once should be reset so that a new
expand_expr call of this expr will cause those to be re-evaluated.
This is useful when we want to reuse a tree in different places,
......
......@@ -219,6 +219,10 @@ extern int warn_redundant_decls;
extern int warn_missing_braces;
/* Warn about comparison of signed and unsigned values. */
extern int warn_sign_compare;
/* Warn about a subscript that has type char. */
extern int warn_char_subscripts;
......@@ -1061,7 +1065,7 @@ struct lang_decl
#endif
/* In a VAR_DECL for a variable declared in a for statement,
this is the shadowed variable. */
this is the shadowed (local) variable. */
#define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE)
/* Points back to the decl which caused this lang_decl to be allocated. */
......@@ -1936,7 +1940,7 @@ extern tree build_vfn_ref PROTO((tree *, tree, tree));
extern void add_method PROTO((tree, tree *, tree));
extern tree get_vfield_offset PROTO((tree));
extern void duplicate_tag_error PROTO((tree));
extern tree finish_struct PROTO((tree, tree, int));
extern tree finish_struct PROTO((tree, tree, tree, int));
extern int resolves_to_fixed_type_p PROTO((tree, int *));
extern void init_class_processing PROTO((void));
extern void pushclass PROTO((tree, int));
......
......@@ -565,12 +565,6 @@ build_up_reference (type, arg, flags, checkconst)
build_up_reference (type, TREE_OPERAND (targ, 1),
LOOKUP_PROTECT, checkconst));
case WITH_CLEANUP_EXPR:
return build (WITH_CLEANUP_EXPR, type,
build_up_reference (type, TREE_OPERAND (targ, 0),
LOOKUP_PROTECT, checkconst),
0, TREE_OPERAND (targ, 2));
case BIND_EXPR:
arg = TREE_OPERAND (targ, 1);
if (arg == NULL_TREE)
......@@ -593,11 +587,6 @@ build_up_reference (type, arg, flags, checkconst)
if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))
{
temp = build_cplus_new (argtype, targ, 1);
if (TREE_CODE (temp) == WITH_CLEANUP_EXPR)
rval = build (WITH_CLEANUP_EXPR, type,
build1 (ADDR_EXPR, type, TREE_OPERAND (temp, 0)),
0, TREE_OPERAND (temp, 2));
else
rval = build1 (ADDR_EXPR, type, temp);
goto done;
}
......
......@@ -196,6 +196,10 @@ int warn_redundant_decls;
int warn_missing_braces;
/* Warn about comparison of signed and unsigned values. */
int warn_sign_compare;
/* Warn about *printf or *scanf format/argument anomalies. */
int warn_format;
......@@ -541,6 +545,8 @@ lang_decode_option (p)
warn_redundant_decls = setting;
else if (!strcmp (p, "missing-braces"))
warn_missing_braces = setting;
else if (!strcmp (p, "sign-compare"))
warn_sign_compare = setting;
else if (!strcmp (p, "format"))
warn_format = setting;
else if (!strcmp (p, "conversion"))
......@@ -565,7 +571,6 @@ lang_decode_option (p)
; /* cpp handles this one. */
else if (!strcmp (p, "all"))
{
extra_warnings = setting;
warn_return_type = setting;
warn_unused = setting;
warn_implicit = setting;
......@@ -574,6 +579,7 @@ lang_decode_option (p)
warn_format = setting;
warn_parentheses = setting;
warn_missing_braces = setting;
warn_sign_compare = setting;
warn_extern_inline = setting;
warn_nonvdtor = setting;
/* We save the value of warn_uninitialized, since if they put
......
......@@ -1082,12 +1082,6 @@ dump_expr (t, nop)
}
break;
case WITH_CLEANUP_EXPR:
/* Note that this only works for G++ cleanups. If somebody
builds a general cleanup, there's no way to represent it. */
dump_expr (TREE_OPERAND (t, 0), 0);
break;
case TARGET_EXPR:
/* Note that this only works for G++ target exprs. If somebody
builds a general TARGET_EXPR, there's no way to represent that
......
......@@ -865,6 +865,20 @@ do_member_init (s_id, name, init)
expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
}
/* Find the context in which this FIELD can be initialized. */
static tree
initializing_context (field)
tree field;
{
tree t = DECL_CONTEXT (field);
/* Anonymous union members can be initialized in the first enclosing
non-anonymous union context. */
while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
t = TYPE_CONTEXT (t);
return t;
}
/* Function to give error message if member initialization specification
is erroneous. FIELD is the member we decided to initialize.
TYPE is the type for which the initialization is being performed.
......@@ -880,7 +894,7 @@ member_init_ok_or_else (field, type, member_name)
{
if (field == error_mark_node)
return 0;
if (field == NULL_TREE || DECL_CONTEXT (field) != type)
if (field == NULL_TREE || initializing_context (field) != type)
{
cp_error ("class `%T' does not have any field named `%s'", type,
member_name);
......@@ -2204,7 +2218,14 @@ is_friend (type, supplicant)
tree context;
if (! declp)
{
/* Are we a nested or local class? If so, we aren't friends
with the CONTEXT. */
if (IS_AGGR_TYPE (supplicant))
context = NULL_TREE;
else
context = DECL_CONTEXT (TYPE_NAME (supplicant));
}
else if (DECL_FUNCTION_MEMBER_P (supplicant))
context = DECL_CLASS_CONTEXT (supplicant);
else
......
......@@ -2283,8 +2283,7 @@ check_newline ()
tricks. */
else
{
ungetc (c, finput);
HANDLE_PRAGMA (finput);
c = HANDLE_PRAGMA (finput, c);
}
#endif
#endif
......@@ -2940,6 +2939,11 @@ do_identifier (token)
if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
{
tree shadowed = DECL_SHADOWED_FOR_VAR (id);
while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
&& DECL_DEAD_FOR_LOCAL (shadowed))
shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
if (!shadowed)
shadowed = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (id));
if (shadowed)
{
if (!DECL_ERROR_REPORTED (id))
......
......@@ -901,7 +901,7 @@ template_instantiate_once:
}
left_curly opt.component_decl_list '}'
{
tree t = finish_struct ($<ttype>3, $5, 0);
tree t = finish_struct ($<ttype>3, $5, NULL_TREE, 0);
pop_obstacks ();
end_template_instantiation ($1);
......@@ -2187,7 +2187,7 @@ structsp:
| TYPENAME_KEYWORD complex_type_name
{ $$ = $2; }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
| class_head left_curly opt.component_decl_list '}'
| class_head left_curly opt.component_decl_list '}' maybe_attribute
{
int semi;
tree id;
......@@ -2209,7 +2209,7 @@ structsp:
/* $$ = $1 from default rule. */;
else
{
$$ = finish_struct ($$, $3, semi);
$$ = finish_struct ($$, $3, $5, semi);
if (semi) note_got_semicolon ($$);
}
......
......@@ -74,9 +74,6 @@ real_lvalue_p (ref)
return 1;
break;
case WITH_CLEANUP_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 0));
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
......@@ -147,9 +144,6 @@ lvalue_p (ref)
return 1;
break;
case WITH_CLEANUP_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case TARGET_EXPR:
return 1;
......@@ -206,12 +200,7 @@ lvalue_or_else (ref, string)
Build an encapsulation of the initialization to perform
and return it so that it can be processed by language-independent
and language-specific expression expanders.
If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression.
Otherwise, cleanups are not built here. For example, when building
an initialization for a stack slot, since the called function handles
the cleanup, we would not want to do it here. */
and language-specific expression expanders. */
tree
build_cplus_new (type, init, with_cleanup_p)
tree type;
......@@ -231,19 +220,6 @@ build_cplus_new (type, init, with_cleanup_p)
TREE_SIDE_EFFECTS (rval) = 1;
TREE_ADDRESSABLE (rval) = 1;
#if 0
if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type))
{
TREE_OPERAND (rval, 2) = error_mark_node;
rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
build_delete (build_pointer_type (type),
build_unary_op (ADDR_EXPR, slot, 0),
integer_two_node,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0));
TREE_SIDE_EFFECTS (rval) = 1;
TREE_ADDRESSABLE (rval) = 1;
}
#endif
return rval;
}
......@@ -1808,11 +1784,6 @@ unsave_expr_now (expr)
}
}
break;
case WITH_CLEANUP_EXPR:
warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR");
RTL_EXPR_RTL (expr) = NULL_RTX;
break;
}
switch (TREE_CODE_CLASS (code))
......
......@@ -1798,20 +1798,19 @@ build_component_ref (datum, component, basetype_path, protect)
}
}
/* See if we have to do any conversions so that we pick up the field from the
right context. */
if (DECL_FIELD_CONTEXT (field) != basetype)
{
tree context = DECL_FIELD_CONTEXT (field);
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
tree base = context;
while (base != basetype && ANON_AGGRNAME_P (TYPE_IDENTIFIER (base)))
{
tree subfield = lookup_anon_field (basetype, context);
tree subdatum = build_component_ref (datum, subfield,
basetype_path, protect);
return build_component_ref (subdatum, field, basetype_path, protect);
}
base = TYPE_CONTEXT (base);
}
if (DECL_FIELD_CONTEXT (field) != basetype
&& TYPE_USES_COMPLEX_INHERITANCE (basetype))
/* Handle base classes here... */
if (base != basetype && TYPE_USES_COMPLEX_INHERITANCE (basetype))
{
tree addr = build_unary_op (ADDR_EXPR, datum, 0);
if (integer_zerop (addr))
......@@ -1823,15 +1822,27 @@ build_component_ref (datum, component, basetype_path, protect)
{
/* It doesn't matter which vbase pointer we grab, just
find one of them. */
tree binfo = get_binfo (DECL_FIELD_CONTEXT (field),
tree binfo = get_binfo (base,
TREE_TYPE (TREE_TYPE (addr)), 0);
addr = convert_pointer_to_real (binfo, addr);
}
else
addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
addr = convert_pointer_to (base, addr);
datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 311);
}
basetype = base;
/* Handle things from anon unions here... */
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
{
tree subfield = lookup_anon_field (basetype, context);
tree subdatum = build_component_ref (datum, subfield,
basetype_path, protect);
return build_component_ref (subdatum, field, basetype_path, protect);
}
}
ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
break_out_cleanups (datum), field));
......@@ -3486,7 +3497,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
resultcode = xresultcode;
}
if (short_compare && extra_warnings)
if (short_compare && warn_sign_compare)
{
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
......@@ -4308,14 +4319,6 @@ unary_complex_lvalue (code, arg)
return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
}
if (TREE_CODE (arg) == WITH_CLEANUP_EXPR)
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
real_result = build (WITH_CLEANUP_EXPR, TREE_TYPE (real_result),
real_result, 0, TREE_OPERAND (arg, 2));
return real_result;
}
if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
|| TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
......@@ -4402,17 +4405,6 @@ unary_complex_lvalue (code, arg)
if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
return build (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
TREE_OPERAND (targ, 0), current_function_decl, NULL);
/* We shouldn't wrap WITH_CLEANUP_EXPRs inside of SAVE_EXPRs, but in case
we do, here's how to handle it. */
if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == WITH_CLEANUP_EXPR)
{
#if 0
/* Not really a bug, but something to turn on when testing. */
compiler_error ("WITH_CLEANUP_EXPR wrapped in SAVE_EXPR");
#endif
return unary_complex_lvalue (ADDR_EXPR, targ);
}
}
/* Don't let anything else be handled specially. */
......@@ -5661,38 +5653,10 @@ build_modify_expr (lhs, modifycode, rhs)
TREE_OPERAND (newrhs, 2))));
}
}
else if (modifycode != INIT_EXPR && TREE_CODE (newrhs) == WITH_CLEANUP_EXPR)
{
tree cleanup = TREE_OPERAND (newrhs, 2);
tree slot;
/* Finish up by running cleanups and having the "value" of the lhs. */
tree exprlist = tree_cons (NULL_TREE, cleanup,
build_tree_list (NULL_TREE, lhs));
newrhs = TREE_OPERAND (newrhs, 0);
if (TREE_CODE (newrhs) == TARGET_EXPR)
slot = TREE_OPERAND (newrhs, 0);
else if (TREE_CODE (newrhs) == ADDR_EXPR)
{
/* Bad but valid. */
slot = newrhs;
warning ("address taken of temporary object");
}
else
my_friendly_abort (118);
/* Copy the value computed in SLOT into LHS. */
exprlist = tree_cons (NULL_TREE,
build_modify_expr (lhs, modifycode, slot),
exprlist);
/* Evaluate the expression that needs CLEANUP. This will
compute the value into SLOT. */
exprlist = tree_cons (NULL_TREE, newrhs, exprlist);
result = convert (lhstype, build_compound_expr (exprlist));
}
else
result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1;
/* If we got the LHS in a different type for storing in,
......@@ -6788,8 +6752,7 @@ c_expand_return (retval)
{
whats_returned = TREE_OPERAND (whats_returned, 0);
while (TREE_CODE (whats_returned) == NEW_EXPR
|| TREE_CODE (whats_returned) == TARGET_EXPR
|| TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR)
|| TREE_CODE (whats_returned) == TARGET_EXPR)
{
/* Get the target. */
whats_returned = TREE_OPERAND (whats_returned, 0);
......
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