+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,
compiler: ../cc1plus
../cc1plus: $(P) $(CXX_OBJS) $(OBJDEPS) $(LIBDEPS)
+ rm -f $@
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o ../cc1plus \
$(CXX_OBJS) $(OBJS) $(LIBS)
/* 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
#include <stdio.h>
#include "cp-tree.h"
#include "flags.h"
+#include "rtl.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
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
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. */
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))
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);
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) */
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)
#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;
}
/* 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.
&& 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);
}
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;
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;
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;
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);
/* 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)))
{
else
{
tree uses, prev;
+ int identified = 0;
/* Mark label as having been defined. */
DECL_INITIAL (decl) = error_mark_node;
&& 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);
}
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;
}
{
/* 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");
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;
}
}
#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))
;
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
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 ();
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
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
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
{
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;
}
\f
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;
/* 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;
}
#endif
- pop_function_context_from (toplev);
+ pop_function_context_from (context);
cp_function_chain = p->next;
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)
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;
}
}
}
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);
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);
}
}
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)
{
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 (typedecl_fn) (*typedecl_fn) (prev, vars);
+ if (vardecl_fn) (*vardecl_fn) (prev, vars);
+
+ if (prev && TREE_CHAIN (prev) != vars)
+ continue;
}
- else if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars))
+ else if (TREE_CODE (vars) == TYPE_DECL
+ && type != error_mark_node
+ && TYPE_LANG_SPECIFIC (type)
+ && CLASSTYPE_VSIZE (type))
{
- if (vardecl_fn) (*vardecl_fn) (prev, vars);
+ if (typedecl_fn) (*typedecl_fn) (prev, vars);
}
- else
- prev = vars;
+
+ prev = vars;
}
}
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);
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'. */
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)
}
}
+ /* 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))
}
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;
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));
}
}
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;
+}
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);
&& ((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;
/* 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;
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);
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);
}
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);
}
;
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:
;
setattrs: /* empty */
- { prefix_attributes = $<ttype>0; }
+ { prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
;
decl:
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
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
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:
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);
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);
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
+#include "rtl.h"
#define CEIL(x,y) (((x) + (y) - 1) / (y))
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;
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);
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);
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;
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)
{
/* 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;
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
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;
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;
{
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
{
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:
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",
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;
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",
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))
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;
}
= 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;
}
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);
&& 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;