parent
e96a50ccad
commit
28cbf42c14
185
gcc/cp/ChangeLog
185
gcc/cp/ChangeLog
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
12
gcc/cp/cvt.c
12
gcc/cp/cvt.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
105
gcc/cp/decl.c
105
gcc/cp/decl.c
|
@ -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)
|
||||
{
|
||||
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,10 +8398,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
|
|||
RIDBIT_RESET (RID_FRIEND, specbits);
|
||||
friendp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (decl_context == NORMAL && friendp)
|
||||
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);
|
||||
}
|
||||
|
||||
/* Traditionally, declaring return type float means double. */
|
||||
|
||||
|
@ -8598,8 +8626,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
|
|||
basetype :: member . */
|
||||
|
||||
if (ctype == current_class_type)
|
||||
{
|
||||
/* 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. */
|
||||
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;
|
||||
|
||||
|
|
111
gcc/cp/decl2.c
111
gcc/cp/decl2.c
|
@ -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,18 +2676,21 @@ walk_vtables (typedecl_fn, vardecl_fn)
|
|||
{
|
||||
register tree type = TREE_TYPE (vars);
|
||||
|
||||
if (TREE_CODE (vars) == TYPE_DECL
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
10
gcc/cp/lex.c
10
gcc/cp/lex.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -404,6 +404,10 @@ any_id:
|
|||
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:
|
||||
|
|
26
gcc/cp/pt.c
26
gcc/cp/pt.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
153
gcc/cp/typeck.c
153
gcc/cp/typeck.c
|
@ -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);
|
||||
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");
|
||||
#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;
|
||||
|
|
Loading…
Reference in New Issue