59th Cygnus<->FSF merge

From-SVN: r9225
This commit is contained in:
Mike Stump 1995-03-23 00:44:31 +00:00
parent e96a50ccad
commit 28cbf42c14
17 changed files with 619 additions and 191 deletions

View File

@ -1,3 +1,188 @@
Wed Mar 22 15:10:34 1995 Mike Stump <mrs@cygnus.com>
* decl2.c (finish_prevtable_vardecl, finish_vtable_vardecl): Revert
Brendan's last change and fix latent problem that causes TD entries
to not come out when the things that need them has yet to be
expanded.
Wed Mar 22 15:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_binary_op_nodefault, comparison ops): Update type0
and type1, since we might have changed op0 or op1.
Wed Mar 22 13:33:45 1995 Jason Merrill <jason@python.cygnus.com>
* typeck.c (common_type): Don't mess up templates.
Wed Mar 22 04:56:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (common_type): Handle ptms properly. Also handle
T* -> void*.
(build_binary_op_nodefault): New variable build_type controls what
type is given to the expression when it is created. Set this to
boolean_type_node for comparison ops instead of using result_type.
(comp_target_types): Allow T * -> void *.
* cvt.c (cp_convert_to_pointer): Do access control when converting
ptms, too.
Tue Mar 21 17:25:06 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* parse.y (extern_lang_string): Catch use of linkage specs that
aren't all naming the same language.
* class.c (finish_struct): Delete accidental duplicate code.
Tue Mar 21 14:00:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_binary_op_nodefault): Disable pedwarns about
comparing functions and incomplete types.
* decl.c (finish_function): Only unset current_function_decl if
!nested.
(duplicate_decls): Last change went too far; we only want to stop
checking for value/reference ambiguity.
Tue Mar 21 01:26:39 1995 Mike Stump <mrs@cygnus.com>
* gc.c (build_generic_desc): Zap the DECL_SIZE so that we can lay it
out fresh, as the new type may be larger.
Mon Mar 20 19:01:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* expr.c (extract_init): Try to expand the RTL for the
initialization and figure out what it will look like so we can avoid
run-time initialization. Disabled for now.
(extract_scalar_init): Helper for scalar initialization.
(extract_aggr_init): Helper for aggregate initialization.
* decl.c (duplicate_decls): Don't complain about ambiguous
declarations.
(obscure_complex_init): Now returns a tree. Call extract_init if
we're optimizing and this is a toplevel decl.
(finish_decl): Update accordingly.
* lex.c (check_newline): If we're just changing files (not pushing
or popping), update input_file_stack->name.
Mon Mar 20 17:55:04 1995 Mike Stump <mrs@cygnus.com>
* pt.c (type_unification): Only TEMPLATE_DECLs are handled right now
in the transitive unification code.
Mon Mar 20 16:07:50 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (shadow_tag): Don't allow inline, virtual, or explicit on
non-functions.
(grokdeclarator): Don't allow friends to be defined in local classes.
Sat Mar 18 04:03:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl2.c (finish_prevtable_vardecl): Use DECL_DECLARED_STATIC
rather than DECL_SAVED_INSNS to decide whether or not this method
was declared inline.
* method.c (synthesize_method): Turn off DECL_INLINE if
function_cannot_inline_p thinks we're too large.
* typeck.c (build_indirect_ref): Use build_expr_type_conversion.
Fri Mar 17 17:47:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* class.c (instantiate_type): Handle pmfs.
* typeck.c (convert_for_assignment): Check types when assigning one
pmf to another.
* decl.c (define_label): Fix logic for printing out the name of the
label in an error message.
* error.c (dump_expr): Support ARRAY_REF.
Fri Mar 17 17:43:02 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl2.c (finish_vtable_vardecl): Call build_t_desc here.
(finish_prevtable_vardecl): Instead of here.
Fri Mar 17 14:40:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (expand_static_init): Also use expand_aggr_init if the
initializer is a TREE_LIST.
(grokdeclarator): Only pedwarn about extra qualification if -pedantic.
* pt.c (unify): Fix unification of return type.
* expr.c (fixup_result_decl): Use store_expr, rather than
emit_move_insn, to move the return value into the place where
callers will expect it.
Thu Mar 16 22:05:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* init.c (build_offset_ref): Call assmble_external on functions.
* typeck.c (build_component_ref): Ditto.
Thu Mar 16 20:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (struct saved_scope): Add members base_init_list and
member_init_list.
(push_to_top_level): Save current_base_init_list and
current_member_init_list to them.
(pop_from_top_level): Put it back.
Thu Mar 16 19:21:14 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* pt.c (instantiate_template): Call assemble_external.
Thu Mar 16 18:07:54 1995 Brendan Kehoe (brendan@phydeaux.cygnus.com)
* class.c: Include rtl.h, to get NULL_RTX.
(finish_struct): Also zero out DECL_SAVED_INSNS, to avoid problems
on hosts with different sizes for each part of the union.
* tree.c: Also include rtl.h.
(layout_basetypes): Same change for DECL_SAVED_INSNS.
Thu Mar 16 13:57:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* pt.c (unify): Fix array domain unification for 64-bit targets.
* decl2.c (finish_file): Push bizarre type decl before walking the
vtables the first time.
(walk_vtables): OK, don't set prev to vars if the vardecl_fn messed
with TREE_CHAIN (prev).
* init.c (emit_base_init): Use convert_pointer_to_real instead of
convert_pointer_to when converting to a direct base.
Wed Mar 15 20:26:29 1995 Mike Stump <mrs@cygnus.com>
* pt.c (type_unification): Handle transitive unification better.
Wed Mar 15 13:56:16 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl2.c (walk_vtables): Always set prev to vars.
(mark_vtable_entries): Call assemble_external on the vtable entries.
* class.c (finish_struct): Set the vtable's size to NULL_TREE before
calling layout_decl, so that it gets updated properly.
Finally re-enable dynamic synthesis. This time it works.
* method.c (synthesize_method): Pass decl_function_context (fndecl)
to {push,pop}_cp_function_context.
* decl.c (push_cp_function_context): Now takes a tree argument.
(pop_cp_function_context): Ditto.
* call.c (build_method_call): Enable synthesis.
* lex.c (cons_up_default_function): Ditto.
Tue Mar 14 19:14:19 1995 Doug Evans <dje@chestnut.cygnus.com>
* parse.y (setattrs): Chain onto prefix_attributes rather than
setting it.
Wed Mar 15 13:00:00 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (pushdecl): Check if the type of the VAR_DECL is an
error_mark_node before trying to read TYPE_LANG_SPECIFIC.
Mon Mar 13 21:00:28 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold,

View File

@ -167,6 +167,7 @@ OBJDEPS = ../stamp-objlist ../c-common.o ../c-pragma.o
compiler: ../cc1plus
../cc1plus: $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
rm -f $@
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o ../cc1plus \
$(CXX_OBJS) $(OBJS) $(LIBS)

View File

@ -2379,7 +2379,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
/* Declare external function if necessary. */
assemble_external (function);
#if 0
#if 1
/* Is it a synthesized method that needs to be synthesized? */
if (DECL_ARTIFICIAL (function) && ! flag_no_inline
&& DECL_SAVED_INSNS (function) == 0

View File

@ -26,6 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "cp-tree.h"
#include "flags.h"
#include "rtl.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
@ -2963,6 +2964,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
DECL_CLASS_CONTEXT (x) = t;
/* Do both of these, even though they're in the same union;
if the insn `r' member and the size `i' member are
different sizes, as on the alpha, the larger of the two
will end up with garbage in it. */
DECL_SAVED_INSNS (x) = NULL_RTX;
DECL_FIELD_SIZE (x) = 0;
/* The name of the field is the original field name
@ -3027,6 +3033,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
fields = x;
last_x = x;
DECL_SAVED_INSNS (x) = NULL_RTX;
DECL_FIELD_SIZE (x) = 0;
/* When this goes into scope, it will be a non-local reference. */
@ -3505,6 +3512,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
DECL_FIELD_CONTEXT (vfield) = t;
DECL_CLASS_CONTEXT (vfield) = t;
DECL_FCONTEXT (vfield) = t;
DECL_SAVED_INSNS (vfield) = NULL_RTX;
DECL_FIELD_SIZE (vfield) = 0;
DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
if (CLASSTYPE_RTTI (t))
@ -3576,47 +3584,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
TYPE_ALIGN (t) = round_up_size;
/* Pass layout information about base classes to layout_type, if any. */
{
tree field;
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
{
if (TREE_STATIC (field))
continue;
if (TREE_CODE (field) != FIELD_DECL)
continue;
/* If this field is an anonymous union,
give each union-member the same position as the union has.
??? This is a real kludge because it makes the structure
of the types look strange. This feature is only used by
C++, which should have build_component_ref build two
COMPONENT_REF operations, one for the union and one for
the inner field. We set the offset of this field to zero
so that either the old or the correct method will work.
Setting DECL_FIELD_CONTEXT is wrong unless the inner fields are
moved into the type of this field, but nothing seems to break
by doing this. */
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
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);
}
DECL_FIELD_BITPOS (field) = integer_zero_node;
}
}
}
if (n_baseclasses)
{
tree pseudo_basetype = TREE_TYPE (base_layout_decl);
@ -3911,6 +3878,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype)
{
TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype;
DECL_SIZE (TYPE_BINFO_VTABLE (t)) = 0;
layout_decl (TYPE_BINFO_VTABLE (t), 0);
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
@ -4726,6 +4694,9 @@ instantiate_type (lhstype, rhs, complain)
functions or member functions. May have to undo what
`default_conversion' might do to lhstype. */
if (TYPE_PTRMEMFUNC_P (lhstype))
lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
if (TREE_CODE (lhstype) == POINTER_TYPE)
if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE)
@ -4884,8 +4855,7 @@ instantiate_type (lhstype, rhs, complain)
#endif
}
if (complain)
error ("no compatible member functions named `%s'",
IDENTIFIER_POINTER (name));
cp_error ("no compatible member functions named `%D'", name);
return error_mark_node;
}

View File

@ -1,5 +1,5 @@
/* Definitions for C++ parsing and type checking.
Copyright (C) 1987, 1993, 1995 Free Software Foundation, Inc.
Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.

View File

@ -155,6 +155,18 @@ cp_convert_to_pointer (type, expr)
&& TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE)
return convert_fn_ptr (type, expr);
if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
&& TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE)
{
tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype));
tree binfo = get_binfo (b1, b2, 1);
if (binfo == NULL_TREE)
binfo = get_binfo (b2, b1, 1);
if (binfo == error_mark_node)
return error_mark_node;
}
return build1 (NOP_EXPR, type, expr);
}

View File

@ -1443,6 +1443,7 @@ struct saved_scope {
tree old_bindings;
struct saved_scope *prev;
tree class_name, class_type, class_decl, function_decl;
tree base_init_list, member_init_list;
struct binding_level *class_bindings;
tree previous_class_type;
tree *lang_base, *lang_stack, lang_name;
@ -1519,6 +1520,8 @@ push_to_top_level ()
s->class_type = current_class_type;
s->class_decl = current_class_decl;
s->function_decl = current_function_decl;
s->base_init_list = current_base_init_list;
s->member_init_list = current_member_init_list;
s->class_bindings = class_binding_level;
s->previous_class_type = previous_class_type;
s->lang_stack = current_lang_stack;
@ -1571,6 +1574,8 @@ pop_from_top_level ()
C_C_D = CLASSTYPE_INST_VAR (current_class_type);
else
C_C_D = NULL_TREE;
current_base_init_list = s->base_init_list;
current_member_init_list = s->member_init_list;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
previous_class_type = s->previous_class_type;
@ -2230,7 +2235,7 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration `%#D' here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2))
TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 3))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@ -3061,6 +3066,7 @@ pushdecl (x)
/* Keep count of variables in this level with incomplete type. */
/* RTTI TD entries are created while defining the type_info. */
if (TREE_CODE (x) == VAR_DECL
&& TREE_TYPE (x) != error_mark_node
&& TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (TREE_TYPE (x)))
{
@ -3606,6 +3612,7 @@ define_label (filename, line, name)
else
{
tree uses, prev;
int identified = 0;
/* Mark label as having been defined. */
DECL_INITIAL (decl) = error_mark_node;
@ -3636,10 +3643,11 @@ define_label (filename, line, name)
&& DECL_INITIAL (new_decls) != error_mark_node)
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
{
if (IDENTIFIER_ERROR_LOCUS (decl) == NULL_TREE)
cp_error ("invalid jump to label `%D'", decl);
SET_IDENTIFIER_ERROR_LOCUS (decl, current_function_decl);
cp_error ("crosses initialization of `%D'", new_decls);
if (! identified)
cp_error ("jump to label `%D'", decl);
identified = 1;
cp_error_at (" crosses initialization of `%#D'",
new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
@ -5259,7 +5267,10 @@ shadow_tag (declspecs)
else if (value == ridpointers[(int) RID_STATIC]
|| value == ridpointers[(int) RID_EXTERN]
|| value == ridpointers[(int) RID_AUTO]
|| value == ridpointers[(int) RID_REGISTER])
|| value == ridpointers[(int) RID_REGISTER]
|| value == ridpointers[(int) RID_INLINE]
|| value == ridpointers[(int) RID_VIRTUAL]
|| value == ridpointers[(int) RID_EXPLICIT])
ob_modifier = value;
}
@ -5290,9 +5301,19 @@ shadow_tag (declspecs)
{
/* Anonymous unions are objects, that's why we only check for
inappropriate specifiers in this branch. */
if (ob_modifier)
cp_error ("`%D' can only be specified for objects and functions",
ob_modifier);
{
if (ob_modifier == ridpointers[(int) RID_INLINE]
|| ob_modifier == ridpointers[(int) RID_VIRTUAL])
cp_error ("`%D' can only be specified for functions", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
cp_error ("`%D' can only be specified for constructors",
ob_modifier);
else
cp_error ("`%D' can only be specified for objects and functions",
ob_modifier);
}
if (found_tag == 0)
pedwarn ("abstract declarator used as declaration");
@ -5837,16 +5858,24 @@ grok_reference_init (decl, type, init, cleanupp)
it in with a dummy CONSTRUCTOR to force the variable into .data;
otherwise we can use error_mark_node. */
static void
obscure_complex_init (decl)
tree decl;
static tree
obscure_complex_init (decl, init)
tree decl, init;
{
if (! flag_no_inline && TREE_STATIC (decl))
{
if (extract_init (decl, init))
return NULL_TREE;
}
if (current_binding_level == global_binding_level
&& ! DECL_COMMON (decl))
DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
NULL_TREE);
else
DECL_INITIAL (decl) = error_mark_node;
return init;
}
/* Finish processing of a declaration;
@ -6078,22 +6107,18 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags)
}
}
#endif
/* We must hide the initializer so that expand_decl
won't try to do something it does not understand. */
obscure_complex_init (decl);
}
else
{
dont_use_constructor:
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
/* Don't let anyone try to initialize this variable
until we are ready to do so. */
if (init)
obscure_complex_init (decl);
}
if (init)
/* We must hide the initializer so that expand_decl
won't try to do something it does not understand. */
init = obscure_complex_init (decl, init);
}
else if (DECL_EXTERNAL (decl))
;
@ -6120,7 +6145,7 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (TYPE_SIZE (type) != NULL_TREE
&& TYPE_NEEDS_CONSTRUCTING (type))
obscure_complex_init (decl);
init = obscure_complex_init (decl, NULL_TREE);
}
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
@ -6589,7 +6614,8 @@ expand_static_init (decl, init)
integer_zero_node, 1), 0);
old_cleanups = cleanups_this_call;
expand_assignment (temp, integer_one_node, 0, 0);
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| TREE_CODE (init) == TREE_LIST)
{
expand_aggr_init (decl, init, 0, 0);
do_pending_stack_adjust ();
@ -8372,11 +8398,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
RIDBIT_RESET (RID_FRIEND, specbits);
friendp = 0;
}
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
cp_error ("can't define friend function `%s' in a local class definition",
name);
}
if (decl_context == NORMAL && friendp)
error ("friend declaration not in class definition");
/* Traditionally, declaring return type float means double. */
if (flag_traditional
@ -8598,8 +8626,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
basetype :: member . */
if (ctype == current_class_type)
cp_pedwarn ("extra qualification `%T::' on member `%s' ignored",
ctype, name);
{
/* class A {
void A::f ();
};
Is this ill-formed? */
if (pedantic)
cp_pedwarn ("extra qualification `%T::' on member `%s' ignored",
ctype, name);
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (current_class_type == NULL_TREE
@ -11307,7 +11344,7 @@ finish_function (lineno, call_poplevel, nested)
int ok_to_optimize_dtor = 0;
if (current_function_assigns_this)
cond = build (NE_EXPR, integer_type_node,
cond = build (NE_EXPR, boolean_type_node,
current_class_decl, integer_zero_node);
else
{
@ -11756,8 +11793,14 @@ finish_function (lineno, call_poplevel, nested)
if (DECL_STATIC_DESTRUCTOR (fndecl))
static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
/* Let the error reporting routines know that we're outside a function. */
current_function_decl = NULL_TREE;
if (! nested)
{
/* Let the error reporting routines know that we're outside a
function. For a nested function, this value is used in
pop_cp_function_context and then reset via pop_function_context. */
current_function_decl = NULL_TREE;
}
named_label_uses = NULL_TREE;
}
@ -12190,13 +12233,13 @@ struct cp_function *cp_function_chain;
used during compilation of a C++ function. */
void
push_cp_function_context (toplev)
int toplev;
push_cp_function_context (context)
tree context;
{
struct cp_function *p
= (struct cp_function *) xmalloc (sizeof (struct cp_function));
push_function_context_to (toplev);
push_function_context_to (context);
p->next = cp_function_chain;
cp_function_chain = p;
@ -12221,8 +12264,8 @@ push_cp_function_context (toplev)
/* Restore the variables used during compilation of a C++ function. */
void
pop_cp_function_context (toplev)
int toplev;
pop_cp_function_context (context)
tree context;
{
struct cp_function *p = cp_function_chain;
tree link;
@ -12244,7 +12287,7 @@ pop_cp_function_context (toplev)
}
#endif
pop_function_context_from (toplev);
pop_function_context_from (context);
cp_function_chain = p->next;

View File

@ -1932,7 +1932,8 @@ build_push_scope (cname, name)
return rval;
}
void cplus_decl_attributes (decl, attributes, prefix_attributes)
void
cplus_decl_attributes (decl, attributes, prefix_attributes)
tree decl, attributes, prefix_attributes;
{
if (decl && decl != void_type_node)
@ -2463,7 +2464,14 @@ mark_vtable_entries (decl)
extern tree abort_fndecl;
if (flag_vtable_thunks)
fnaddr = TREE_VALUE (entries);
TREE_OPERAND (fnaddr, 0) = abort_fndecl;
TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
}
if (TREE_PUBLIC (fn) && ! TREE_ASM_WRITTEN (fn))
{
int save_extern = DECL_EXTERNAL (fn);
DECL_EXTERNAL (fn) = 1;
assemble_external (fn);
DECL_EXTERNAL (fn) = save_extern;
}
}
}
@ -2561,7 +2569,8 @@ finish_prevtable_vardecl (prev, vars)
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
method = DECL_NEXT_METHOD (method))
{
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method)
if (DECL_VINDEX (method) != NULL_TREE
&& !DECL_DECLARED_STATIC (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method))
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
@ -2574,10 +2583,17 @@ finish_prevtable_vardecl (prev, vars)
import_export_vtable (vars, ctype, 1);
/* We cannot use TREE_USED here, as it may be set by the expanding of a
ctor that is used to build a global object. The long term plan is to
make the TD entries statically initialized and move this to
finish_vtable_vardecl time. */
if (flag_rtti && write_virtuals >= 0
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || 1 || TREE_USED (vars)))
{
/* Kick out the type descriptor before writing out the vtable. */
/* Kick out the type descriptor before we dump out global
initializers, as they are initialized at run time and
we have to find them when we scan for things that need initialized
at the top level. */
build_t_desc (ctype, 1);
}
}
@ -2589,6 +2605,15 @@ finish_vtable_vardecl (prev, vars)
if (write_virtuals >= 0
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
{
#if 0
/* The long term plan it to make the TD entries statically initialized,
have the entries built and emitted here. When that happens, this
can be enabled, and the other call to build_t_desc removed. */
/* Kick out the type descriptor before writing out the vtable. */
if (flag_rtti)
build_t_desc (DECL_CONTEXT (vars), 1);
#endif
/* Write it out. */
mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
@ -2651,19 +2676,22 @@ walk_vtables (typedecl_fn, vardecl_fn)
{
register tree type = TREE_TYPE (vars);
if (TREE_CODE (vars) == TYPE_DECL
&& type != error_mark_node
&& TYPE_LANG_SPECIFIC (type)
&& CLASSTYPE_VSIZE (type))
if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars))
{
if (vardecl_fn) (*vardecl_fn) (prev, vars);
if (prev && TREE_CHAIN (prev) != vars)
continue;
}
else if (TREE_CODE (vars) == TYPE_DECL
&& type != error_mark_node
&& TYPE_LANG_SPECIFIC (type)
&& CLASSTYPE_VSIZE (type))
{
if (typedecl_fn) (*typedecl_fn) (prev, vars);
}
else if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars))
{
if (vardecl_fn) (*vardecl_fn) (prev, vars);
}
else
prev = vars;
prev = vars;
}
}
@ -2805,6 +2833,31 @@ finish_file ()
interface_unknown = 1;
interface_only = 0;
#if 1
/* The reason for pushing garbage onto the global_binding_level is to
ensure that we can slice out _DECLs which pertain to virtual function
tables. If the last thing pushed onto the global_binding_level was a
virtual function table, then slicing it out would slice away all the
decls (i.e., we lose the head of the chain).
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
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. */
/* Make last thing in global scope not be a virtual function table. */
#if 0 /* not yet, should get fixed properly later */
vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node);
#else
vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
#endif
DECL_IGNORED_P (vars) = 1;
SET_DECL_ARTIFICIAL (vars);
pushdecl (vars);
#endif
/* Walk to mark the inline functions we need, then output them so
that we can pick up any other tdecls that those routines need. */
walk_vtables ((void (*)())0, finish_prevtable_vardecl);
@ -3023,37 +3076,12 @@ finish_file ()
start_time = get_run_time ();
/* Now delete from the chain of variables all virtual function tables.
We output them all ourselves, because each will be treated specially. */
#if 1
/* The reason for pushing garbage onto the global_binding_level is to
ensure that we can slice out _DECLs which pertain to virtual function
tables. If the last thing pushed onto the global_binding_level was a
virtual function table, then slicing it out would slice away all the
decls (i.e., we lose the head of the chain).
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
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. */
/* Make last thing in global scope not be a virtual function table. */
#if 0 /* not yet, should get fixed properly later */
vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node);
#else
vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
#endif
DECL_IGNORED_P (vars) = 1;
SET_DECL_ARTIFICIAL (vars);
pushdecl (vars);
#endif
if (flag_handle_signatures)
walk_sigtables ((void (*)())0, finish_sigtable_vardecl);
for (fnname = saved_inlines; fnname; fnname = TREE_CHAIN (fnname))
import_export_inline (TREE_VALUE (fnname));
/* Now write out inline functions which had their addresses taken and
which were not declared virtual and which were not declared `extern
inline'. */
@ -3089,7 +3117,7 @@ finish_file ()
TREE_CHAIN (last) = TREE_CHAIN (place);
continue;
}
import_export_inline (decl);
if (TREE_PUBLIC (decl)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
|| flag_keep_inline_functions)
@ -3112,6 +3140,9 @@ finish_file ()
}
}
/* Now delete from the chain of variables all virtual function tables.
We output them all ourselves, because each will be treated specially. */
walk_vtables ((void (*)())0, prune_vtable_vardecl);
for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))

View File

@ -1142,6 +1142,13 @@ dump_expr (t, nop)
}
break;
case ARRAY_REF:
dump_expr (TREE_OPERAND (t, 0), 0);
OB_PUTC ('[');
dump_expr (TREE_OPERAND (t, 1), 0);
OB_PUTC (']');
break;
case CONVERT_EXPR:
dump_unary_op ("+", t, nop);
break;

View File

@ -264,7 +264,7 @@ fixup_result_decl (decl, result)
REG_FUNCTION_VALUE_P (real_decl_result) = 1;
result = real_decl_result;
}
emit_move_insn (result, DECL_RTL (decl));
store_expr (decl, result, 0);
emit_insn (gen_rtx (USE, VOIDmode, result));
}
}
@ -274,9 +274,90 @@ fixup_result_decl (decl, result)
in some cases. We cannot use `memory_operand' as a test
here because on most RISC machines, a variable's address
is not, by itself, a legitimate address. */
int
decl_in_memory_p (decl)
tree decl;
{
return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
}
/* Expand this initialization inline and see if it's simple enough that
it can be done at compile-time. */
static tree
extract_aggr_init (decl, init)
tree decl, init;
{
return 0;
}
static tree
extract_scalar_init (decl, init)
tree decl, init;
{
rtx value, insns, insn;
extern struct obstack temporary_obstack;
tree t = NULL_TREE;
push_obstacks (&temporary_obstack, &temporary_obstack);
start_sequence ();
value = expand_expr (init, NULL_RTX, VOIDmode, 0);
insns = get_insns ();
end_sequence ();
reg_scan (insns, max_reg_num (), 0);
jump_optimize (insns, 0, 0, 1);
pop_obstacks ();
for (insn = insns; insn; insn = NEXT_INSN (insn))
{
rtx r, to;
if (GET_CODE (insn) == NOTE)
continue;
else if (GET_CODE (insn) != INSN)
return 0;
r = PATTERN (insn);
if (GET_CODE (r) != SET)
return 0;
to = XEXP (r, 0);
if (! (to == value ||
(GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
return 0;
r = XEXP (r, 1);
switch (GET_CODE (r))
{
case CONST_INT:
t = build_int_2 (XEXP (r, 0), 0);
break;
default:
return 0;
}
}
return t;
}
int
extract_init (decl, init)
tree decl, init;
{
return 0;
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
init = extract_aggr_init (decl, init);
else
init = extract_scalar_init (decl, init);
if (init == NULL_TREE)
return 0;
DECL_INITIAL (decl) = init;
return 1;
}

View File

@ -571,7 +571,7 @@ emit_base_init (t, immediately)
if (init != void_list_node)
{
member = convert_pointer_to (base_binfo, current_class_decl);
member = convert_pointer_to_real (base_binfo, current_class_decl);
expand_aggr_init_1 (base_binfo, 0,
build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
@ -1980,6 +1980,10 @@ build_offset_ref (cname, name)
&& ((flag_save_memoized_contexts && global_bindings_p ())
|| ! allocation_temporary_p ()))
fnfields = copy_list (fnfields);
for (t = TREE_VALUE (fnfields); t; t = DECL_CHAIN (t))
assemble_external (t);
t = build_tree_list (error_mark_node, fnfields);
TREE_TYPE (t) = build_offset_type (type, unknown_type_node);
return t;

View File

@ -1796,8 +1796,10 @@ cons_up_default_function (type, full_name, kind)
/* When on-the-fly synthesis works properly, remove the second and third
conditions here. */
if (flag_keep_inline_functions
#if 0
|| ! flag_no_inline
|| complex
#endif
|| ! DECL_EXTERNAL (fn))
{
struct pending_inline *t;
@ -2812,7 +2814,13 @@ linenum:
extract_interface_info ();
c = get_last_nonwhite_on_line ();
if (c != EOF)
if (c == EOF)
{
/* Update the name in the top element of input_file_stack. */
if (input_file_stack)
input_file_stack->name = input_filename;
}
else
{
put_back (c);

View File

@ -2209,12 +2209,12 @@ synthesize_method (fndecl)
tree fndecl;
{
int nested = (current_function_decl != NULL_TREE);
int toplev = (decl_function_context (fndecl) == NULL_TREE);
tree context = decl_function_context (fndecl);
char *f = input_filename;
tree base = DECL_CLASS_CONTEXT (fndecl);
if (nested)
push_cp_function_context (toplev);
push_cp_function_context (context);
input_filename = DECL_SOURCE_FILE (fndecl);
interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base);
@ -2238,8 +2238,19 @@ synthesize_method (fndecl)
}
finish_function (lineno, 0, nested);
/* Do we really *want* to inline this function? */
if (DECL_INLINE (fndecl))
{
/* Turn off DECL_INLINE for the moment so function_cannot_inline_p
will check our size. */
DECL_INLINE (fndecl) = 0;
if (function_cannot_inline_p (fndecl) == 0)
DECL_INLINE (fndecl) = 1;
}
input_filename = f;
extract_interface_info ();
if (nested)
pop_cp_function_context (toplev);
pop_cp_function_context (context);
}

View File

@ -402,8 +402,12 @@ any_id:
;
extern_lang_string:
EXTERN_LANG_STRING
EXTERN_LANG_STRING
{ push_lang_context ($1); }
| extern_lang_string EXTERN_LANG_STRING
{ if (current_lang_name != $2)
cp_error ("use of linkage spec `%D' is different from previous spec `%D'", $2, current_lang_name);
pop_lang_context (); push_lang_context ($2); }
;
template_header:
@ -1725,7 +1729,7 @@ object: primary '.'
;
setattrs: /* empty */
{ prefix_attributes = $<ttype>0; }
{ prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
;
decl:

View File

@ -1712,6 +1712,8 @@ instantiate_template (tmpl, targ_ptr)
if (fndecl == error_mark_node)
goto exit;
assemble_external (fndecl);
/* If it's a static member fn in the template, we need to change it
into a FUNCTION_TYPE and chop off its this pointer. */
if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
@ -2059,6 +2061,23 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
{
my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
if (TREE_CODE (arg) == TREE_LIST
&& TREE_TYPE (arg) == unknown_type_node
&& TREE_CODE (TREE_VALUE (arg)) == TEMPLATE_DECL)
{
int nsubsts, ntparms;
tree *targs;
/* Have to back unify here */
arg = TREE_VALUE (arg);
nsubsts = 0;
ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg));
targs = (tree *) alloca (sizeof (tree) * ntparms);
parm = tree_cons (NULL_TREE, parm, NULL_TREE);
return type_unification (DECL_TEMPLATE_PARMS (arg), targs,
TYPE_ARG_TYPES (TREE_TYPE (arg)),
parm, &nsubsts, 0);
}
arg = TREE_TYPE (arg);
}
#endif
@ -2200,6 +2219,8 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
nsubsts);
case REFERENCE_TYPE:
if (TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts);
case ARRAY_TYPE:
@ -2242,8 +2263,6 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
tree t1, t2;
t1 = TREE_OPERAND (parm, 0);
t2 = TREE_OPERAND (parm, 1);
if (TREE_CODE (t1) != TEMPLATE_CONST_PARM)
return 1;
return unify (tparms, targs, ntparms, t1,
fold (build (PLUS_EXPR, integer_type_node, arg, t2)),
nsubsts);
@ -2299,6 +2318,9 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
if (TREE_CODE (arg) != FUNCTION_TYPE)
return 1;
check_args:
if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
TREE_TYPE (arg), nsubsts))
return 1;
return type_unification (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), nsubsts, 1);

View File

@ -24,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "rtl.h"
#define CEIL(x,y) (((x) + (y) - 1) / (y))
@ -826,6 +827,7 @@ layout_basetypes (rec, binfos)
DECL_FIELD_CONTEXT (decl) = rec;
DECL_CLASS_CONTEXT (decl) = rec;
DECL_FCONTEXT (decl) = basetype;
DECL_SAVED_INSNS (decl) = NULL_RTX;
DECL_FIELD_SIZE (decl) = 0;
DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node);
TREE_CHAIN (decl) = vbase_decls;

View File

@ -369,12 +369,24 @@ common_type (t1, t2)
But ANSI C++ specifies doing this with the qualifiers.
So I turned it on again. */
{
tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)),
TYPE_MAIN_VARIANT (TREE_TYPE (t2)));
tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (t1));
tree tt2 = TYPE_MAIN_VARIANT (TREE_TYPE (t2));
int constp
= TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
int volatilep
= TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
tree target;
if (tt1 == tt2)
target = tt1;
else if ((IS_AGGR_TYPE_CODE (TREE_CODE (tt1))
|| TREE_CODE (tt1) == OFFSET_TYPE
|| TREE_CODE (tt1) == METHOD_TYPE)
&& TREE_CODE (tt2) == TREE_CODE (tt1))
target = common_type (tt1, tt2);
else
target = void_type_node;
target = cp_build_type_variant (target, constp, volatilep);
if (code1 == POINTER_TYPE)
t1 = build_pointer_type (target);
@ -480,17 +492,18 @@ common_type (t1, t2)
return build_type_attribute_variant (t1, attributes);
case OFFSET_TYPE:
if (TYPE_OFFSET_BASETYPE (t1) == TYPE_OFFSET_BASETYPE (t2)
&& TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
{
tree basetype = TYPE_OFFSET_BASETYPE (t1);
t1 = build_offset_type (basetype,
common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
}
else
compiler_error ("common_type called with uncommon member types");
tree b1 = TYPE_OFFSET_BASETYPE (t1);
tree b2 = TYPE_OFFSET_BASETYPE (t2);
tree base;
/* ... falls through ... */
if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))
return build_type_attribute_variant (t1, attributes);
else if (binfo_or_else (b2, b1))
return build_type_attribute_variant (t2, attributes);
}
compiler_error ("common_type called with uncommon member types");
default:
return build_type_attribute_variant (t1, attributes);
@ -762,6 +775,17 @@ comp_target_types (ttl, ttr, nptrs)
if (ttl == ttr)
return 1;
if (TREE_CODE (ttl) == VOID_TYPE
&& TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttr) != METHOD_TYPE
&& TREE_CODE (ttr) != OFFSET_TYPE)
return 1;
if (TREE_CODE (ttr) == VOID_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE
&& TREE_CODE (ttl) != METHOD_TYPE
&& TREE_CODE (ttl) != OFFSET_TYPE)
return -1;
if (TREE_CODE (ttr) != TREE_CODE (ttl))
return 0;
@ -1680,6 +1704,7 @@ build_component_ref (datum, component, basetype_path, protect)
my_friendly_assert (datum != error_mark_node, 310);
fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
}
assemble_external (fndecl);
return fndecl;
}
if (access == access_protected)
@ -1692,7 +1717,12 @@ build_component_ref (datum, component, basetype_path, protect)
{
/* Just act like build_offset_ref, since the object does
not matter unless we're actually calling the function. */
tree t = build_tree_list (error_mark_node, fndecls);
tree t;
for (t = TREE_VALUE (fndecls); t; t = DECL_CHAIN (t))
assemble_external (t);
t = build_tree_list (error_mark_node, fndecls);
TREE_TYPE (t) = build_offset_type (basetype,
unknown_type_node);
return t;
@ -1779,6 +1809,13 @@ build_indirect_ref (ptr, errorstring)
if (ptr == current_class_decl)
return C_C_D;
ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1);
if (ptr)
{
pointer = ptr;
type = TREE_TYPE (pointer);
}
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
@ -2821,6 +2858,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
Zero means they need to be converted to RESULT_TYPE. */
int converted = 0;
/* Nonzero means create the expression with this type, rather than
RESULT_TYPE. */
tree build_type = 0;
/* Nonzero means after finally constructing the expression
give it this type. Otherwise, give it type RESULT_TYPE. */
tree final_type = 0;
@ -3064,8 +3105,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case EQ_EXPR:
case NE_EXPR:
result_type = boolean_type_node;
converted = 1;
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
@ -3073,33 +3113,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
{
register tree tt0 = TYPE_MAIN_VARIANT (TREE_TYPE (type0));
register tree tt1 = TYPE_MAIN_VARIANT (TREE_TYPE (type1));
/* Anything compares with void *. void * compares with anything.
Otherwise, the targets must be the same. */
if (tt0 != tt1 && TREE_CODE (tt0) == RECORD_TYPE
&& TREE_CODE (tt1) == RECORD_TYPE)
{
tree base = common_base_type (tt0, tt1);
if (base == NULL_TREE)
cp_pedwarn ("comparison of distinct object pointer types `%T' and `%T'", type0, type1);
else if (base == error_mark_node)
{
cp_error ("comparison of pointer types `%T' and `%T' requires conversion to ambiguous supertype", type0, type1);
return error_mark_node;
}
else
{
if (integer_zerop (op0))
op0 = null_pointer_node;
else
op0 = convert_pointer_to (base, op0);
if (integer_zerop (op1))
op1 = null_pointer_node;
else
op1 = convert_pointer_to (base, op1);
}
}
else if (comp_target_types (type0, type1, 1))
;
if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else if (tt0 == void_type_node)
{
if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE
@ -3225,10 +3241,11 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
{
return build_binary_op (code, op1, op0, 1);
}
else
/* If args are not valid, clear out RESULT_TYPE
to cause an error message later. */
result_type = 0;
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
if (result_type == NULL_TREE)
result_type = type0;
break;
case MAX_EXPR:
@ -3239,8 +3256,12 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (! comp_target_types (type0, type1, 1))
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
{
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
result_type = ptr_type_node;
}
#if 0
else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
!= (TYPE_SIZE (TREE_TYPE (type1)) != 0))
cp_pedwarn ("comparison of %scomplete and %scomplete pointers",
@ -3250,15 +3271,20 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
result_type = common_type (type0, type1);
#endif
else
result_type = common_type (type0, type1);
}
if (result_type == NULL_TREE)
result_type = type0;
break;
case LE_EXPR:
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
result_type = boolean_type_node;
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
@ -3267,6 +3293,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (! comp_target_types (type0, type1, 1))
cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
type0, type1);
#if 0
else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
!= (TYPE_SIZE (TREE_TYPE (type1)) != 0))
cp_pedwarn ("comparison of %scomplete and %scomplete pointers",
@ -3276,6 +3303,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
#endif
else
result_type = common_type (type0, type1);
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
@ -3299,9 +3329,11 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
warning ("comparison between pointer and integer");
op0 = convert (TREE_TYPE (op1), op0);
}
else
result_type = 0;
converted = 1;
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
if (result_type == NULL_TREE)
result_type = type0;
break;
}
@ -3437,7 +3469,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
return convert (boolean_type_node, val);
op0 = xop0, op1 = xop1, result_type = boolean_type_node;
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
}
@ -3544,8 +3577,11 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
op1 = convert (result_type, op1);
}
if (build_type == NULL_TREE)
build_type = result_type;
{
register tree result = build (resultcode, result_type, op0, op1);
register tree result = build (resultcode, build_type, op0, op1);
register tree folded;
folded = fold (result);
@ -6731,11 +6767,22 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
&& TREE_CODE (rhstype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (rhstype)) == METHOD_TYPE)
|| integer_zerop (rhs)
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
|| TYPE_PTRMEMFUNC_P (rhstype))
&& TYPE_PTRMEMFUNC_P (type))
{
tree ttl = TYPE_PTRMEMFUNC_FN_TYPE (type);
tree ttr = (TREE_CODE (rhstype) == POINTER_TYPE ? rhstype
: TYPE_PTRMEMFUNC_FN_TYPE (type));
int ctt = comp_target_types (ttl, ttr, 1);
if (ctt < 0)
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
ttr, ttl);
else if (ctt == 0)
cp_error ("%s to `%T' from `%T'", errtype, ttl, ttr);
/* compatible pointer to member functions. */
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), rhs, 0);
return build_ptrmemfunc (ttl, rhs, 0);
}
else if (codel == ERROR_MARK || coder == ERROR_MARK)
return error_mark_node;