Commit b7484fbe by Mike Stump

58th Cygnus<->FSF merge

From-SVN: r9186
parent a0dabda5
Mon Mar 13 21:00:28 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold,
and convert the size and integer_one_node to the index type.
Mon Mar 13 08:01:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (get_member_function_from_ptrfunc): Save the instance
argument, and tack it onto the front of the COND_EXPR to make the
semantics come out right. Grab the instance argument from
'*instance_ptrptr', rather than having it passed in separately.
* various: Change various consed-up comparison operations to have
boolean type. Remove the instance argument in calls to
get_member_function_from_ptrfunc.
* error.c (dump_expr): Dump true and false as "true" and "false".
* decl2.c (finish_file): Also set DECL_STATIC_FUNCTION_P on the
global init function.
* decl.c (finish_function): Only set DECL_EXTERNAL here if the
inline function is public.
Sat Mar 11 00:58:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* init.c (is_friend): Be more careful about checking
DECL_CLASS_CONTEXT on non-member functions.
* decl2.c (finish_vtable_vardecl): Don't bother calling
assemble_external here.
(prune_vtable_vardecl): New function that just splices out the
vtable decl from the top-level decls.
(import_export_inline): Unset DECL_EXTERNAL at first.
(finish_file): Don't bother calling assemble_external here. Do
splice out all of the vtables.
Fri Mar 10 14:42:29 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (finish_function): If we're not emitting the function yet,
call assemble_external for it.
* decl2.c (finish_prevtable_vardecl): Don't call mark_vtable_entries
here.
(finish_vtable_vardecl): Don't do the linkage deduction thing here.
Also don't splice out the current vtable if it is unused.
(finish_file): Move the second walk_vtables and the synthesis check
inside the 'reconsider' loop. Move thunk emission after the
'reconsider' loop.
Thu Mar 9 16:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* pt.c (tsubst): Don't bother calling cp_build_type_variant, since it
was passing bogus values for readonly and volatile from the original
template decl, not the resultant type of the tsubst call.
* class.c (duplicate_tag_error): Use cp_error_at to point out the
previous definition of the tag.
Thu Mar 9 10:46:17 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (start_function): Clear base_init_insns and protect_list.
(struct cp_function): Add base_init_insns field.
(push_cp_function_context): Also save base_init_insns.
(pop_cp_function_context): Also restore base_init_insns.
Wed Mar 8 13:31:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* init.c (member_init_ok_or_else): Check for initializing a static
member here.
(emit_base_init): Instead of here.
Tue Mar 7 16:03:26 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* call.c (build_method_call): Disable synthesis as needed.
* lex.c (cons_up_default_function): Ditto.
Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com) Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* parse.y: New rules to allow attributes in a prefix position. * parse.y: New rules to allow attributes in a prefix position.
...@@ -10,6 +87,234 @@ Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com) ...@@ -10,6 +87,234 @@ Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
(grokdeclarator): Added code to support machine attributes. (grokdeclarator): Added code to support machine attributes.
* Makefile.in (stamp-parse): Expect 5 shift/reduce failures. * Makefile.in (stamp-parse): Expect 5 shift/reduce failures.
Mon Mar 6 15:07:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* call.c (build_method_call): Don't synthesize methods outside of a
function.
Make base initialization more re-entrant so that synthesis on the
fly will work (and, eventually, template instantation on the fly).
* init.c (sort_member_init): Don't bother with members that can't be
initialized. Reorganize a bit. Don't initialize base members here.
(sort_base_init): New function, like sort_member_init, but for base
classes. Steals some code from emit_base_init.
(emit_base_init): Simplify. Call sort_{member,base}_init before
doing any initialization, so we don't have to save
current_{member,base}_init_list in push_cp_function_context.
(expand_aggr_vbase_init_1): Adjust for sort_base_init.
(expand_aggr_vbase_init): Simplify.
* decl.c (struct cp_function): Add protect_list field.
(push_cp_function_context): Also save protect_list.
(pop_cp_function_context): Also restore protect_list.
* call.c (build_method_call): Enable synthesis at point of call.
* lex.c (cons_up_default_function): Ditto.
* parse.y: Turn -ansi checks back into -pedantic checks.
* init.c (build_new): Fix -fcheck-new for array new.
Sat Mar 4 15:55:42 1995 Fergus Henderson <fjh@cs.mu.oz.au>
* typeck.c (build_compound_expr): warn if left-hand operand of
comma expression has no side-effects.
Fri Mar 3 15:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* parse.y (primary): Change 'object qualified_id *' rules to 'object
overqualified_id *'.
Fri Mar 3 12:48:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* parse.y (unary_expr): Catch doing sizeof an overloaded function.
Make the error look the same as the one we issue in c_sizeof.
* typeck.c (build_binary_op_nodefault): Give an error for trying
to compare a pointer-to-member to `void *'.
Fri Mar 3 11:28:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_unary_op): Handle bool increment with smoke and
mirrors here, rather than in expand_increment where it belongs,
because Kenner doesn't agree with me.
Fri Mar 3 00:08:10 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokparms): Catch a PARM_DECL being used for a default
argument as well.
Thu Mar 2 20:05:54 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* init.c (build_new): Don't allow new on a function type.
* parse.y (primary): Avoid a crash when seeing if the arg is of
the same type as that given for the typespec in an explicit dtor call.
Thu Mar 2 00:49:38 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (finish_function): Change test for calling
mark_inline_for_output.
Wed Mar 1 11:23:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_modify_expr): Complain if
build_default_binary_type_conversion fails.
* init.c (expand_default_init): Handle arguments of unknown type
properly.
* cvt.c (build_expr_type_conversion): Only complain about ambiguity
if 'complain'.
* various: Pass 'complain'.
* typeck.c (comptypes): Be more picky about comparing UPTs.
Wed Mar 1 11:03:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator): If declarator is null, say that the
type used has an incomplete type.
Wed Mar 1 10:06:20 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* pt.c (instantiate_template): Copy the template arguments to the
permanent_obstack. Also use simple_cst_equal to compare them when
looking for a previous instantiation.
* tree.c (make_deep_copy): Support copying INTEGER_TYPEs (assuming
they are array domain types).
Tue Feb 28 23:24:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cp-tree.h: Define WANT_* constants for passing to
build_expr_type_conversion.
* cvt.c (build_expr_type_conversion): New function to build
conversion to one of a group of suitable types.
(build_default_binary_type_conversion): Use it.
* decl2.c (grok_array_decl): Ditto.
* typeck.c (build_unary_op): Ditto.
(build_array_ref): Tidy up a bit.
(build_binary_op): Ditto.
Tue Feb 28 19:57:31 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator): Don't allow decl of an argument as `void'.
Tue Feb 28 17:23:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* parse.y (typed_declspecs1): Add 'typespec reserved_typespecquals
reserved_declspecs' rule.
* parse.y (expr_or_declarator): Remove notype_qualified_id rule.
(direct_notype_declarator): Ditto.
(complex_direct_notype_declarator): Add notype_qualified_id rule.
* lex.c (real_yylex): Handle :> digraph properly.
Tue Feb 28 12:26:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator): Check if it's a friend, not if it's
non-virtual, that's being initialized. Move the check up to
before FRIENDP would get cleared. Catch an unnamed var/field
being declared void. Say just `field' instead of `structure field'
in the error message. Only go for the operator name if DECLARATOR
is non-null.
Tue Feb 28 00:08:01 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (start_function): Complain about abstract return type.
(grokdeclarator): Complain about declaring constructors and
destructors to be const or volatile. Complain about declaring
destructors to be static.
* pt.c (uses_template_parms): Handle pmfs.
* decl.c (grokdeclarator): Don't call variable_size for array bounds
that only depend on template constant parameters.
Mon Feb 27 15:38:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* error.c (dump_decl): Only look to see if it's a vtable if we
actually have a name to check out.
Mon Feb 27 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cvt.c (convert_to_aggr): Lose misleading shortcut.
Sun Feb 26 17:27:32 1995 Doug Evans <dje@canuck.cygnus.com>
* decl.c (set_nested_typename): Always set DECL_IGNORED_P,
not just for dwarf.
Sun Feb 26 00:10:18 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator): Don't allow a static member to be
declared `register'.
* init.c (make_friend_class): Move up to a pedwarn for the warning
about a class declaring friends with itself.
* decl.c (grokdeclarator): You can't do `volatile friend class foo'
or `inline friend class foo'. Only try to make a friend out of
TYPE if we didn't already reset it to integer_type_node.
Sat Feb 25 22:32:03 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator): Don't allow initialization of a
non-virtual function.
* decl.c (start_function): Do a pedwarn if we're changing `main'
to have an int return type.
Sat Feb 25 00:02:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_modify_expr): Handle simple assignment from
TARGET_EXPRs by building up an RTL_EXPR to force expansion. Whew.
Fri Feb 24 18:27:14 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* decl.c (grokdeclarator): Also don't allow virtual outside of a
class decl for a scope method definition performed at global binding.
* init.c (build_offset_ref): Don't allow creation of an OFFSET_REF
of a bitfield.
* decl.c (grokdeclarator): Don't allow a const to be declared mutable.
* typeck.c (build_binary_op): Return an error_mark_node if either
one of the args turned into an error_mark_node when we tried to
use default_conversion.
* typeck.c (build_unary_op): Forbid using postfix -- on a bool.
* decl.c (grokdeclarator): Allow `signed' and `unsigned' to be
used on `__wchar_t'.
Fri Feb 24 13:59:53 1995 Mike Stump <mrs@cygnus.com>
* except.c (end_protect_partials): Do it the right way.
Wed Feb 22 15:42:56 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_binary_op_nodefault): Upgrade warning about
comparing distinct pointer types to pedwarn.
* typeck2.c (digest_init): Cope with extra braces.
* typeck.c (build_binary_op_nodefault): Use tree_int_cst_sgn instead
of INT_CST_LT (..., interger_zero_node).
Wed Feb 22 14:45:52 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* except.c [!TRY_NEW_EH] (end_protect_partials): Define dummy
function for systems that don't have EH.
Tue Feb 21 19:18:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* call.c (can_convert_arg): Like can_convert, but takes an arg as
well.
* pt.c (type_unification): Allow implicit conversions for parameters
that do not depend on template parameters.
Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu) Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu)
* Make-lang.in, config-lang.in: ($exeext): New macro. * Make-lang.in, config-lang.in: ($exeext): New macro.
...@@ -19,17 +324,46 @@ Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu) ...@@ -19,17 +324,46 @@ Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu)
* cp/g++.c: Added #ifdefs for sys/file.h and process.h for NT. * cp/g++.c: Added #ifdefs for sys/file.h and process.h for NT.
Modified spawnvp to have to correct number of arguments for OS/2, NT. Modified spawnvp to have to correct number of arguments for OS/2, NT.
Thu Feb 2 15:07:58 1995 Jason Merrill <jason@phydeaux.cygnus.com> Tue Feb 21 18:36:55 1995 Mike Stump <mrs@cygnus.com>
* decl.c (finish_function): Add calls to end_protect_partials to end
the exception region that protects constructors so that partially
constructed objects can be partially destructed when the constructor
throws an exception.
* init.c (perform_member_init, sort_member_init, emit_base_init):
Added support for partially constructed objects.
* init.c (build_partial_cleanup_for): New routine to do partial
cleanups of a base class.
* decl2.c (finish_file): Move the emitting of the exception table
down, after we emit all code that might have exception regions in
them.
* except.c (end_protect_partials, might_have_exceptions_p): New
routines.
(emit_exception_table): Always output table if called.
* cp-tree.h (protect_list, end_protect_partials,
might_have_exceptions_p, emit_exception_table): Added.
Tue Feb 21 16:05:59 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* gc.c (build_typeid): Pass a NULL_TREE, not the bogus, unused
address of a local variable.
* class.c (build_vfn_ref): Only try to build the PLUS_EXPR if we
were given a non-null PTR_TO_INSTPTR.
Tue Feb 21 01:53:18 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (duplicate_decls): Always lay out the merged decl.
* decl2.c (finish_vtable_vardecl): Don't do vtable hack on templates.
(finish_prevtable_vardecl): Ditto.
* class.c (build_vbase_path): Bash types to make the backend happy. * method.c (synthesize_method): Set interface_{unknown,only}
* cvt.c (build_up_reference): Bash the types bashed by according to the settings for our class, not the file where it comes
build_vbase_path to be reference types instead of pointer types. from.
(convert_to_reference): Ditto.
Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu) Sat Feb 18 12:26:48 1995 Mike Stump <mrs@cygnus.com>
* class.c (instantiate_type): Change error message text. * except.c: Handle systems that define __i386__ but not __i386.
* typeck2.c (store_init_value): Likewise.
Fri Feb 17 15:31:31 1995 Jason Merrill <jason@phydeaux.cygnus.com> Fri Feb 17 15:31:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
...@@ -518,6 +852,11 @@ Tue Jan 24 16:36:31 1995 Jason Merrill <jason@phydeaux.cygnus.com> ...@@ -518,6 +852,11 @@ Tue Jan 24 16:36:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR * typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR
will suffice to convert from integer_zero_node. will suffice to convert from integer_zero_node.
Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu)
* class.c (instantiate_type): Change error message text.
* typeck2.c (store_init_value): Likewise.
Mon Jan 23 21:57:14 1995 Mike Stump <mrs@cygnus.com> Mon Jan 23 21:57:14 1995 Mike Stump <mrs@cygnus.com>
* pt.c (tsubst): When we copy a node, don't forget to copy * pt.c (tsubst): When we copy a node, don't forget to copy
...@@ -4034,11 +4373,6 @@ Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com) ...@@ -4034,11 +4373,6 @@ Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com)
* Language directory reorganization. * Language directory reorganization.
See parent makefile. See parent makefile.
Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com)
* Language directory reorganization.
See parent makefile.
Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com) Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com)
* cp-tree.h (THUNK_DELTA): It is normally negative, so * cp-tree.h (THUNK_DELTA): It is normally negative, so
......
...@@ -194,14 +194,15 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h ...@@ -194,14 +194,15 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'` `echo $(PARSE_C) | sed 's,^\./,,'`
CONFLICTS = expect 5 shift/reduce confict and 38 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C) $(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y $(PARSE_C) : $(srcdir)/parse.y
@echo expect 5 shift/reduce confict and 39 reduce/reduce conflicts. @echo $(CONFLICTS)
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
#$(PARSE_C) $(PARSE_H) : stamp-parse ; @true #$(PARSE_C) $(PARSE_H) : stamp-parse ; @true
#stamp-parse: $(srcdir)/parse.y #stamp-parse: $(srcdir)/parse.y
# @echo expect 1 shift/reduce confict and 39 reduce/reduce conflicts. # @echo $(CONFLICTS)
# $(BISON) $(BISONFLAGS) -d $(srcdir)/parse.y # $(BISON) $(BISONFLAGS) -d $(srcdir)/parse.y
# grep '^#define[ ]*YYEMPTY' y.tab.c >>y.tab.h # grep '^#define[ ]*YYEMPTY' y.tab.c >>y.tab.h
# $(srcdir)/../move-if-change y.tab.c $(PARSE_C) # $(srcdir)/../move-if-change y.tab.c $(PARSE_C)
......
...@@ -593,6 +593,15 @@ can_convert (to, from) ...@@ -593,6 +593,15 @@ can_convert (to, from)
return h.code < USER_CODE; return h.code < USER_CODE;
} }
int
can_convert_arg (to, from, arg)
tree to, from, arg;
{
struct harshness_code h;
h = convert_harshness (to, from, arg);
return h.code < USER_CODE;
}
#ifdef DEBUG_MATCHING #ifdef DEBUG_MATCHING
static char * static char *
print_harshness (h) print_harshness (h)
...@@ -2371,9 +2380,12 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2371,9 +2380,12 @@ build_method_call (instance, name, parms, basetype_path, flags)
assemble_external (function); assemble_external (function);
#if 0 #if 0
/* Is it a synthesized method that needs to be synthesized? */
if (DECL_ARTIFICIAL (function) && ! flag_no_inline if (DECL_ARTIFICIAL (function) && ! flag_no_inline
&& DECL_SAVED_INSNS (function) == 0 && DECL_SAVED_INSNS (function) == 0
&& ! TREE_ASM_WRITTEN (function)) && ! TREE_ASM_WRITTEN (function)
/* Kludge: don't synthesize for default args. */
&& current_function_decl)
synthesize_method (function); synthesize_method (function);
#endif #endif
......
...@@ -240,7 +240,7 @@ build_vbase_path (code, type, expr, path, alias_this) ...@@ -240,7 +240,7 @@ build_vbase_path (code, type, expr, path, alias_this)
{ {
null_expr = build1 (NOP_EXPR, TYPE_POINTER_TO (last_virtual), integer_zero_node); null_expr = build1 (NOP_EXPR, TYPE_POINTER_TO (last_virtual), integer_zero_node);
expr = build (COND_EXPR, TYPE_POINTER_TO (last_virtual), expr = build (COND_EXPR, TYPE_POINTER_TO (last_virtual),
build (EQ_EXPR, integer_type_node, expr, build (EQ_EXPR, boolean_type_node, expr,
integer_zero_node), integer_zero_node),
null_expr, nonnull_expr); null_expr, nonnull_expr);
} }
...@@ -323,7 +323,7 @@ build_vbase_path (code, type, expr, path, alias_this) ...@@ -323,7 +323,7 @@ build_vbase_path (code, type, expr, path, alias_this)
expr = save_expr (expr); expr = save_expr (expr);
return build (COND_EXPR, type, return build (COND_EXPR, type,
build (EQ_EXPR, integer_type_node, expr, integer_zero_node), build (EQ_EXPR, boolean_type_node, expr, integer_zero_node),
null_expr, null_expr,
build (code, type, expr, offset)); build (code, type, expr, offset));
} }
...@@ -490,11 +490,12 @@ build_vfn_ref (ptr_to_instptr, instance, idx) ...@@ -490,11 +490,12 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
return aref; return aref;
else else
{ {
*ptr_to_instptr if (ptr_to_instptr)
= build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), *ptr_to_instptr
*ptr_to_instptr, = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
convert (ptrdiff_type_node, *ptr_to_instptr,
build_component_ref (aref, delta_identifier, 0, 0))); convert (ptrdiff_type_node,
build_component_ref (aref, delta_identifier, 0, 0)));
return build_component_ref (aref, pfn_identifier, 0, 0); return build_component_ref (aref, pfn_identifier, 0, 0);
} }
} }
...@@ -2020,6 +2021,7 @@ duplicate_tag_error (t) ...@@ -2020,6 +2021,7 @@ duplicate_tag_error (t)
tree t; tree t;
{ {
cp_error ("redefinition of `%#T'", t); cp_error ("redefinition of `%#T'", t);
cp_error_at ("previous definition here", t);
/* Pretend we haven't defined this type. */ /* Pretend we haven't defined this type. */
......
...@@ -1836,6 +1836,17 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ ...@@ -1836,6 +1836,17 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \ #define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP) | CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
/* Used by build_expr_type_conversion to indicate which types are
acceptable as arguments to the expression under consideration. */
#define WANT_INT 1 /* integer types, including bool */
#define WANT_FLOAT 2 /* floating point types */
#define WANT_ENUM 4 /* enumerated types */
#define WANT_POINTER 8 /* pointer types */
#define WANT_NULL 16 /* null pointer constant */
#define WANT_ARITH (WANT_INT | WANT_FLOAT)
/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST): /* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
purpose = friend name (IDENTIFIER_NODE); purpose = friend name (IDENTIFIER_NODE);
value = TREE_LIST of FUNCTION_DECLS; value = TREE_LIST of FUNCTION_DECLS;
...@@ -1913,8 +1924,8 @@ extern tree convert PROTO((tree, tree)); ...@@ -1913,8 +1924,8 @@ extern tree convert PROTO((tree, tree));
extern tree cp_convert PROTO((tree, tree, int, int)); extern tree cp_convert PROTO((tree, tree, int, int));
extern tree convert_force PROTO((tree, tree, int)); extern tree convert_force PROTO((tree, tree, int));
extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int)); extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
extern tree build_expr_type_conversion PROTO((int, tree, int));
extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *)); extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *));
extern tree type_promotes_to PROTO((tree)); extern tree type_promotes_to PROTO((tree));
/* decl.c */ /* decl.c */
...@@ -2042,9 +2053,10 @@ extern tree get_namespace_id PROTO((void)); ...@@ -2042,9 +2053,10 @@ extern tree get_namespace_id PROTO((void));
/* in edsel.c */ /* in edsel.c */
/* in except.c */ /* in except.c */
extern tree protect_list;
extern void start_protect PROTO((void)); extern void start_protect PROTO((void));
extern void end_protect PROTO((tree)); extern void end_protect PROTO((tree));
extern void end_protect_partials ();
extern void expand_exception_blocks PROTO((void)); extern void expand_exception_blocks PROTO((void));
extern void expand_start_try_stmts PROTO((void)); extern void expand_start_try_stmts PROTO((void));
extern void expand_end_try_stmts PROTO((void)); extern void expand_end_try_stmts PROTO((void));
...@@ -2053,7 +2065,8 @@ extern void expand_end_all_catch PROTO((void)); ...@@ -2053,7 +2065,8 @@ extern void expand_end_all_catch PROTO((void));
extern void start_catch_block PROTO((tree, tree)); extern void start_catch_block PROTO((tree, tree));
extern void end_catch_block PROTO((void)); extern void end_catch_block PROTO((void));
extern void expand_throw PROTO((tree)); extern void expand_throw PROTO((tree));
extern int build_exception_table PROTO((void)); extern int might_have_exceptions_p PROTO((void));
extern void emit_exception_table PROTO((void));
extern tree build_throw PROTO((tree)); extern tree build_throw PROTO((tree));
extern void init_exception_processing PROTO((void)); extern void init_exception_processing PROTO((void));
...@@ -2093,7 +2106,7 @@ extern tree get_type_value PROTO((tree)); ...@@ -2093,7 +2106,7 @@ extern tree get_type_value PROTO((tree));
extern tree build_member_call PROTO((tree, tree, tree)); extern tree build_member_call PROTO((tree, tree, tree));
extern tree build_offset_ref PROTO((tree, tree)); extern tree build_offset_ref PROTO((tree, tree));
extern tree get_member_function PROTO((tree *, tree, tree)); extern tree get_member_function PROTO((tree *, tree, tree));
extern tree get_member_function_from_ptrfunc PROTO((tree *, tree, tree)); extern tree get_member_function_from_ptrfunc PROTO((tree *, tree));
extern tree resolve_offset_ref PROTO((tree)); extern tree resolve_offset_ref PROTO((tree));
extern tree decl_constant_value PROTO((tree)); extern tree decl_constant_value PROTO((tree));
extern int is_friend_type PROTO((tree, tree)); extern int is_friend_type PROTO((tree, tree));
......
...@@ -903,6 +903,7 @@ convert_to_aggr (type, expr, msgp, protect) ...@@ -903,6 +903,7 @@ convert_to_aggr (type, expr, msgp, protect)
parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist); parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes); parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
#if 0
method_name = build_decl_overload (name, parmtypes, 1); method_name = build_decl_overload (name, parmtypes, 1);
/* constructors are up front. */ /* constructors are up front. */
...@@ -936,6 +937,7 @@ convert_to_aggr (type, expr, msgp, protect) ...@@ -936,6 +937,7 @@ convert_to_aggr (type, expr, msgp, protect)
} }
fndecl = DECL_CHAIN (fndecl); fndecl = DECL_CHAIN (fndecl);
} }
#endif
/* No exact conversion was found. See if an approximate /* No exact conversion was found. See if an approximate
one will do. */ one will do. */
...@@ -1548,7 +1550,7 @@ build_type_conversion (code, xtype, expr, for_sure) ...@@ -1548,7 +1550,7 @@ build_type_conversion (code, xtype, expr, for_sure)
{ {
cp_error ("ambiguous conversion from `%T' to `%T'", basetype, cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
xtype); xtype);
cp_error (" candidate conversion functions include `%T' and `%T'", cp_error (" candidate conversions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv)); TREE_VALUE (winner), TREE_VALUE (conv));
return NULL_TREE; return NULL_TREE;
} }
...@@ -1564,154 +1566,228 @@ build_type_conversion (code, xtype, expr, for_sure) ...@@ -1564,154 +1566,228 @@ build_type_conversion (code, xtype, expr, for_sure)
return NULL_TREE; return NULL_TREE;
} }
/* Must convert two aggregate types to non-aggregate type. /* Convert the given EXPR to one of a group of types suitable for use in an
Attempts to find a non-ambiguous, "best" type conversion. expression. DESIRES is a combination of various WANT_* flags (q.v.)
which indicates which types are suitable. If COMPLAIN is 1, complain
Return 1 on success, 0 on failure. about ambiguity; otherwise, the caller will deal with it. */
@@ What are the real semantics of this supposed to be??? */ tree
int build_expr_type_conversion (desires, expr, complain)
build_default_binary_type_conversion (code, arg1, arg2) int desires;
enum tree_code code; tree expr;
tree *arg1, *arg2; int complain;
{ {
tree type1 = TREE_TYPE (*arg1); tree basetype = TREE_TYPE (expr);
tree type2 = TREE_TYPE (*arg2); tree conv;
tree winner = NULL_TREE;
if (TREE_CODE (type1) == REFERENCE_TYPE
|| TREE_CODE (type1) == POINTER_TYPE)
type1 = TREE_TYPE (type1);
if (TREE_CODE (type2) == REFERENCE_TYPE
|| TREE_CODE (type2) == POINTER_TYPE)
type2 = TREE_TYPE (type2);
if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL) if (TREE_CODE (basetype) == OFFSET_TYPE)
{ {
tree decl = typedecl_for_tag (type1); expr = resolve_offset_ref (expr);
if (decl) basetype = TREE_TYPE (expr);
error ("type conversion nonexistent for type `%s'",
IDENTIFIER_POINTER (DECL_NAME (decl)));
else
error ("type conversion nonexistent for non-C++ type");
return 0;
}
if (TREE_CODE (TYPE_NAME (type2)) != TYPE_DECL)
{
tree decl = typedecl_for_tag (type2);
if (decl)
error ("type conversion nonexistent for type `%s'",
IDENTIFIER_POINTER (decl));
else
error ("type conversion nonexistent for non-C++ type");
return 0;
} }
if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1)) if (! IS_AGGR_TYPE (basetype))
{ switch (TREE_CODE (basetype))
if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2)) {
cp_error ("no conversion from `%T' and `%T' to types with default `%O' ", case INTEGER_TYPE:
type1, type2, code); if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
else && integer_zerop (expr))
cp_error ("no conversion from `%T' to type with default `%O'", return expr;
type1, code); /* else fall through... */
return 0;
} case BOOLEAN_TYPE:
else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2)) return (desires & WANT_INT) ? expr : NULL_TREE;
{ case ENUMERAL_TYPE:
cp_error ("no conversion from `%T' to type with default `%O'", return (desires & WANT_ENUM) ? expr : NULL_TREE;
type2, code); case REAL_TYPE:
return 0; return (desires & WANT_FLOAT) ? expr : NULL_TREE;
} case POINTER_TYPE:
return (desires & WANT_POINTER) ? expr : NULL_TREE;
case FUNCTION_TYPE:
case ARRAY_TYPE:
return (desires & WANT_POINTER) ? default_conversion (expr)
: NULL_TREE;
default:
return NULL_TREE;
}
if (code == TRUTH_ANDIF_EXPR if (! TYPE_HAS_CONVERSION (basetype))
|| code == TRUTH_ORIF_EXPR) return NULL_TREE;
{
*arg1 = convert (boolean_type_node, *arg1); for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
*arg2 = convert (boolean_type_node, *arg2);
}
else if (TYPE_HAS_INT_CONVERSION (type1))
{
if (TYPE_HAS_REAL_CONVERSION (type1))
cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int",
type1);
*arg1 = build_type_conversion (code, integer_type_node, *arg1, 1);
*arg2 = build_type_conversion (code, integer_type_node, *arg2, 1);
}
else if (TYPE_HAS_REAL_CONVERSION (type1))
{
*arg1 = build_type_conversion (code, double_type_node, *arg1, 1);
*arg2 = build_type_conversion (code, double_type_node, *arg2, 1);
}
else
{
*arg1 = build_type_conversion (code, ptr_type_node, *arg1, 1);
if (*arg1 == error_mark_node)
error ("ambiguous pointer conversion");
*arg2 = build_type_conversion (code, ptr_type_node, *arg2, 1);
if (*arg1 != error_mark_node && *arg2 == error_mark_node)
error ("ambiguous pointer conversion");
}
if (*arg1 == 0)
{
if (*arg2 == 0 && type1 != type2)
cp_error ("default type conversion for types `%T' and `%T' failed",
type1, type2);
else
cp_error ("default type conversion for type `%T' failed", type1);
return 0;
}
else if (*arg2 == 0)
{ {
cp_error ("default type conversion for type `%T' failed", type2); int win = 0;
return 0;
if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
continue;
switch (TREE_CODE (TREE_VALUE (conv)))
{
case BOOLEAN_TYPE:
case INTEGER_TYPE:
win = (desires & WANT_INT); break;
case ENUMERAL_TYPE:
win = (desires & WANT_ENUM); break;
case REAL_TYPE:
win = (desires & WANT_FLOAT); break;
case POINTER_TYPE:
win = (desires & WANT_POINTER); break;
}
if (win)
{
if (winner)
{
if (complain)
{
cp_error ("ambiguous default type conversion from `%T'",
basetype);
cp_error (" candidate conversions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv));
}
return error_mark_node;
}
else
winner = conv;
}
} }
return 1;
if (winner)
return build_type_conversion_1 (TREE_VALUE (winner), basetype, expr,
TREE_PURPOSE (winner), 1);
return NULL_TREE;
} }
/* Must convert an aggregate type to non-aggregate type. /* Must convert two aggregate types to non-aggregate type.
Attempts to find a non-ambiguous, "best" type conversion. Attempts to find a non-ambiguous, "best" type conversion.
Return 1 on success, 0 on failure. Return 1 on success, 0 on failure.
The type of the argument is expected to be of aggregate type here.
@@ What are the real semantics of this supposed to be??? */ @@ What are the real semantics of this supposed to be??? */
int int
build_default_unary_type_conversion (code, arg) build_default_binary_type_conversion (code, arg1, arg2)
enum tree_code code; enum tree_code code;
tree *arg; tree *arg1, *arg2;
{ {
tree type = TREE_TYPE (*arg); switch (code)
if (! TYPE_HAS_CONVERSION (type))
{ {
cp_error ("type conversion required for type `%T'", type); case MULT_EXPR:
return 0; case TRUNC_DIV_EXPR:
} case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
*arg1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
*arg2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
break;
if (code == TRUTH_NOT_EXPR) case TRUNC_MOD_EXPR:
*arg = convert (boolean_type_node, *arg); case FLOOR_MOD_EXPR:
else if (TYPE_HAS_INT_CONVERSION (type)) case LSHIFT_EXPR:
{ case RSHIFT_EXPR:
if (TYPE_HAS_REAL_CONVERSION (type)) case BIT_AND_EXPR:
cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int", case BIT_XOR_EXPR:
type); case BIT_IOR_EXPR:
*arg = build_type_conversion (code, integer_type_node, *arg, 1); *arg1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg1, 0);
} *arg2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg2, 0);
else if (TYPE_HAS_REAL_CONVERSION (type)) break;
*arg = build_type_conversion (code, double_type_node, *arg, 1);
else case PLUS_EXPR:
{ {
*arg = build_type_conversion (code, ptr_type_node, *arg, 1); tree a1, a2, p1, p2;
if (*arg == error_mark_node) int wins;
error ("ambiguous pointer conversion");
} a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
if (*arg == NULL_TREE) a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
{ p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
cp_error ("default type conversion for type `%T' failed", type); p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
return 0;
wins = (a1 && a2) + (a1 && p2) + (p1 && a2);
if (wins > 1)
error ("ambiguous default type conversion for `operator +'");
if (a1 && a2)
*arg1 = a1, *arg2 = a2;
else if (a1 && p2)
*arg1 = a1, *arg2 = p2;
else
*arg1 = p1, *arg2 = a2;
break;
}
case MINUS_EXPR:
{
tree a1, a2, p1, p2;
int wins;
a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
wins = (a1 && a2) + (p1 && p2) + (p1 && a2);
if (wins > 1)
error ("ambiguous default type conversion for `operator -'");
if (a1 && a2)
*arg1 = a1, *arg2 = a2;
else if (p1 && p2)
*arg1 = p1, *arg2 = p2;
else
*arg1 = p1, *arg2 = a2;
break;
}
case GT_EXPR:
case LT_EXPR:
case GE_EXPR:
case LE_EXPR:
case EQ_EXPR:
case NE_EXPR:
{
tree a1, a2, p1, p2;
int wins;
a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
p1 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg1, 0);
p2 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg2, 0);
wins = (a1 && a2) + (p1 && p2);
if (wins > 1)
cp_error ("ambiguous default type conversion for `%O'", code);
if (a1 && a2)
*arg1 = a1, *arg2 = a2;
else
*arg1 = p1, *arg2 = p2;
break;
}
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
*arg1 = convert (boolean_type_node, *arg1);
*arg2 = convert (boolean_type_node, *arg2);
break;
default:
*arg1 = NULL_TREE;
*arg2 = NULL_TREE;
} }
return 1;
if (*arg1 == error_mark_node || *arg2 == error_mark_node)
cp_error ("ambiguous default type conversion for `%O'", code);
if (*arg1 && *arg2)
return 1;
return 0;
} }
/* Implements integral promotion (4.1) and float->double promotion. */ /* Implements integral promotion (4.1) and float->double promotion. */
......
...@@ -1664,13 +1664,10 @@ set_nested_typename (decl, classname, name, type) ...@@ -1664,13 +1664,10 @@ set_nested_typename (decl, classname, name, type)
type_decl = build_decl (TYPE_DECL, nested, type); type_decl = build_decl (TYPE_DECL, nested, type);
DECL_NESTED_TYPENAME (type_decl) = nested; DECL_NESTED_TYPENAME (type_decl) = nested;
SET_DECL_ARTIFICIAL (type_decl); SET_DECL_ARTIFICIAL (type_decl);
#ifdef DWARF_DEBUGGING_INFO /* Mark the TYPE_DECL node created just above as a gratuitous one so that
/* Mark the TYPE_DECL node created just above as a dwarfout.c will know not to generate a TAG_typedef DIE for it, and
gratuitous one so that dwarfout.c will know not to sdbout.c won't try to output a .def for "::foo". */
generate a TAG_typedef DIE for it. */ DECL_IGNORED_P (type_decl) = 1;
if (write_symbols == DWARF_DEBUG)
DECL_IGNORED_P (type_decl) = 1;
#endif /* DWARF_DEBUGGING_INFO */
/* Remove this when local classes are fixed. */ /* Remove this when local classes are fixed. */
SET_IDENTIFIER_TYPE_VALUE (nested, type); SET_IDENTIFIER_TYPE_VALUE (nested, type);
...@@ -2447,21 +2444,16 @@ duplicate_decls (newdecl, olddecl) ...@@ -2447,21 +2444,16 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype; TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */ /* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl)) if (oldtype != TREE_TYPE (newdecl)
{ && TREE_TYPE (newdecl) != error_mark_node)
if (TREE_TYPE (newdecl) != error_mark_node) layout_type (TREE_TYPE (newdecl));
layout_type (TREE_TYPE (newdecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL if (TREE_CODE (newdecl) == VAR_DECL
&& TREE_CODE (newdecl) != TYPE_DECL || TREE_CODE (newdecl) == PARM_DECL
&& TREE_CODE (newdecl) != CONST_DECL || TREE_CODE (newdecl) == RESULT_DECL
&& TREE_CODE (newdecl) != TEMPLATE_DECL) || TREE_CODE (newdecl) == FIELD_DECL
layout_decl (newdecl, 0); || TREE_CODE (newdecl) == TYPE_DECL)
} layout_decl (newdecl, 0);
else
{
/* Since the type is OLDDECL's, make OLDDECL's size go with. */
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
}
/* Merge the type qualifiers. */ /* Merge the type qualifiers. */
if (TREE_READONLY (newdecl)) if (TREE_READONLY (newdecl))
...@@ -7660,7 +7652,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7660,7 +7652,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (TREE_CODE (type) == REAL_TYPE) if (TREE_CODE (type) == REAL_TYPE)
error ("short, signed or unsigned invalid for `%s'", name); error ("short, signed or unsigned invalid for `%s'", name);
else if (TREE_CODE (type) != INTEGER_TYPE || type == wchar_type_node) else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name); error ("long, short, signed or unsigned invalid for `%s'", name);
else if (RIDBIT_SETP (RID_LONG, specbits) else if (RIDBIT_SETP (RID_LONG, specbits)
&& RIDBIT_SETP (RID_SHORT, specbits)) && RIDBIT_SETP (RID_SHORT, specbits))
...@@ -7780,6 +7772,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7780,6 +7772,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
error ("non-object member `%s' cannot be declared `mutable'", name); error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits); RIDBIT_RESET (RID_MUTABLE, specbits);
} }
else if (constp)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (staticp) else if (staticp)
{ {
error ("static `%s' cannot be declared `mutable'", name); error ("static `%s' cannot be declared `mutable'", name);
...@@ -7820,7 +7817,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7820,7 +7817,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
} }
/* Give error if `virtual' is used outside of class declaration. */ /* Give error if `virtual' is used outside of class declaration. */
if (virtualp && current_class_name == NULL_TREE) if (virtualp
&& (current_class_name == NULL_TREE || decl_context != FIELD))
{ {
error ("virtual outside class declaration"); error ("virtual outside class declaration");
virtualp = 0; virtualp = 0;
...@@ -7972,14 +7970,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -7972,14 +7970,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{ {
if (decl_context == FIELD) if (decl_context == FIELD)
{ {
tree tmp = TREE_OPERAND (declarator, 0); tree tmp = NULL_TREE;
register int op = IDENTIFIER_OPNAME_P (tmp); register int op = 0;
if (declarator)
{
tmp = TREE_OPERAND (declarator, 0);
op = IDENTIFIER_OPNAME_P (tmp);
}
error ("storage class specified for %s `%s'", error ("storage class specified for %s `%s'",
IS_SIGNATURE (current_class_type) IS_SIGNATURE (current_class_type)
? (op ? (op
? "signature member operator" ? "signature member operator"
: "signature member function") : "signature member function")
: (op ? "member operator" : "structure field"), : (op ? "member operator" : "field"),
op ? operator_name_string (tmp) : name); op ? operator_name_string (tmp) : name);
} }
else else
...@@ -8092,6 +8096,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8092,6 +8096,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{ {
register tree itype = NULL_TREE; register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1); register tree size = TREE_OPERAND (declarator, 1);
/* The index is a signed object `sizetype' bits wide. */
tree index_type = signed_type (sizetype);
declarator = TREE_OPERAND (declarator, 0); declarator = TREE_OPERAND (declarator, 0);
...@@ -8181,8 +8187,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8181,8 +8187,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
cp_error ("size of array `%D' is negative", dname); cp_error ("size of array `%D' is negative", dname);
size = integer_one_node; size = integer_one_node;
} }
itype = build_index_type (size_binop (MINUS_EXPR, size,
integer_one_node));
} }
else else
{ {
...@@ -8194,15 +8198,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8194,15 +8198,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
else else
cp_pedwarn ("ANSI C++ forbids variable-size array"); cp_pedwarn ("ANSI C++ forbids variable-size array");
} }
dont_grok_size:
itype =
build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
/* Make sure the array size remains visibly nonconstant /* Make sure the array size remains visibly nonconstant
even if it is (eg) a const variable with known value. */ even if it is (eg) a const variable with known value. */
size_varies = 1; size_varies = 1;
itype = variable_size (itype);
itype = build_index_type (itype);
} }
dont_grok_size:
itype =
fold (build_binary_op (MINUS_EXPR,
convert (index_type, size),
convert (index_type,
integer_one_node), 1));
if (! TREE_CONSTANT (itype))
itype = variable_size (itype);
itype = build_index_type (itype);
resume_momentary (yes); resume_momentary (yes);
} }
...@@ -8262,10 +8271,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8262,10 +8271,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
inner_decl = TREE_OPERAND (inner_decl, 1); inner_decl = TREE_OPERAND (inner_decl, 1);
/* Pick up type qualifiers which should be applied to `this'. */
quals = TREE_OPERAND (declarator, 2);
/* Say it's a definition only for the CALL_EXPR /* Say it's a definition only for the CALL_EXPR
closest to the identifier. */ closest to the identifier. */
funcdecl_p = funcdecl_p =
inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE; inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
|| TREE_CODE (inner_decl) == BIT_NOT_EXPR);
if (ctype == NULL_TREE if (ctype == NULL_TREE
&& decl_context == FIELD && decl_context == FIELD
...@@ -8289,14 +8302,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8289,14 +8302,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
may not be static. */ may not be static. */
if (staticp == 2) if (staticp == 2)
error ("destructor cannot be static member function"); error ("destructor cannot be static member function");
if (TYPE_READONLY (type)) if (quals)
{
error ("destructors cannot be declared `const'");
return void_type_node;
}
if (TYPE_VOLATILE (type))
{ {
error ("destructors cannot be declared `volatile'"); error ("destructors cannot be declared `const' or `volatile'");
return void_type_node; return void_type_node;
} }
if (decl_context == FIELD) if (decl_context == FIELD)
...@@ -8320,16 +8328,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8320,16 +8328,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
pedwarn ("constructors cannot be declared virtual"); pedwarn ("constructors cannot be declared virtual");
virtualp = 0; virtualp = 0;
} }
if (TYPE_READONLY (type)) if (quals)
{ {
error ("constructors cannot be declared `const'"); error ("constructors cannot be declared `const' or `volatile'");
return void_type_node; return void_type_node;
} }
if (TYPE_VOLATILE (type))
{
error ("constructors cannot be declared `volatile'");
return void_type_node;
}
{ {
RID_BIT_TYPE tmp_bits; RID_BIT_TYPE tmp_bits;
bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE)); bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE));
...@@ -8358,20 +8361,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8358,20 +8361,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (decl_context == FIELD) if (decl_context == FIELD)
staticp = 0; staticp = 0;
} }
else if (friendp && virtualp) else if (friendp)
{ {
/* Cannot be both friend and virtual. */ if (initialized)
error ("virtual functions cannot be friends"); error ("can't initialize friend function `%s'", name);
RIDBIT_RESET (RID_FRIEND, specbits); if (virtualp)
friendp = 0; {
/* Cannot be both friend and virtual. */
error ("virtual functions cannot be friends");
RIDBIT_RESET (RID_FRIEND, specbits);
friendp = 0;
}
} }
if (decl_context == NORMAL && friendp) if (decl_context == NORMAL && friendp)
error ("friend declaration not in class definition"); error ("friend declaration not in class definition");
/* Pick up type qualifiers which should be applied to `this'. */
quals = TREE_OPERAND (declarator, 2);
/* Traditionally, declaring return type float means double. */ /* Traditionally, declaring return type float means double. */
if (flag_traditional if (flag_traditional
...@@ -8836,13 +8841,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8836,13 +8841,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* Special case: "friend class foo" looks like a TYPENAME context. */ /* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp) if (friendp)
{ {
/* A friendly class? */ if (volatilep)
if (current_class_type) {
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); cp_error ("`volatile' specified for friend class declaration");
else volatilep = 0;
error("trying to make class `%s' a friend of global scope", }
TYPE_NAME_STRING (type)); if (inlinep)
type = void_type_node; {
cp_error ("`inline' specified for friend class declaration");
inlinep = 0;
}
/* Only try to do this stuff if we didn't already give up. */
if (type != integer_type_node)
{
/* A friendly class? */
if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
else
error ("trying to make class `%s' a friend of global scope",
TYPE_NAME_STRING (type));
type = void_type_node;
}
} }
else if (quals) else if (quals)
{ {
...@@ -8878,7 +8898,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8878,7 +8898,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM) if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM)
{ {
if (TREE_CODE (declarator) == IDENTIFIER_NODE) if (! declarator)
error ("unnamed variable or field declared void");
else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
{ {
if (IDENTIFIER_OPNAME_P (declarator)) if (IDENTIFIER_OPNAME_P (declarator))
#if 0 /* How could this happen? */ #if 0 /* How could this happen? */
...@@ -8921,6 +8943,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -8921,6 +8943,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = build_pointer_type (type); type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE) else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type); type = build_pointer_type (type);
else if (type == void_type_node && declarator)
{
error ("declaration of `%s' as void", name);
return NULL_TREE;
}
decl = build_decl (PARM_DECL, declarator, type); decl = build_decl (PARM_DECL, declarator, type);
...@@ -9030,7 +9057,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -9030,7 +9057,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
else if (TYPE_SIZE (type) == NULL_TREE && !staticp else if (TYPE_SIZE (type) == NULL_TREE && !staticp
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{ {
cp_error ("field `%D' has incomplete type", declarator); if (declarator)
cp_error ("field `%D' has incomplete type", declarator);
else
cp_error ("name `%T' has incomplete type", type);
/* If we're instantiating a template, tell them which /* If we're instantiating a template, tell them which
instantiation made the field's type be incomplete. */ instantiation made the field's type be incomplete. */
...@@ -9302,6 +9332,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) ...@@ -9302,6 +9332,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
staticp = 0; staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits); RIDBIT_RESET (RID_STATIC, specbits);
} }
if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
{
cp_error ("static member `%D' declared `register'", decl);
RIDBIT_RESET (RID_REGISTER, specbits);
}
if (RIDBIT_SETP (RID_EXTERN, specbits)) if (RIDBIT_SETP (RID_EXTERN, specbits))
{ {
cp_error ("cannot explicitly declare member `%#D' to have extern linkage", cp_error ("cannot explicitly declare member `%#D' to have extern linkage",
...@@ -9583,7 +9618,8 @@ grokparms (first_parm, funcdef_flag) ...@@ -9583,7 +9618,8 @@ grokparms (first_parm, funcdef_flag)
any_init++; any_init++;
if (TREE_CODE (init) == SAVE_EXPR) if (TREE_CODE (init) == SAVE_EXPR)
PARM_DECL_EXPR (init) = 1; PARM_DECL_EXPR (init) = 1;
else if (TREE_CODE (init) == VAR_DECL) else if (TREE_CODE (init) == VAR_DECL
|| TREE_CODE (init) == PARM_DECL)
{ {
if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init))) if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
{ {
...@@ -10656,6 +10692,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10656,6 +10692,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
original_result_rtx = NULL_RTX; original_result_rtx = NULL_RTX;
current_function_obstack_index = 0; current_function_obstack_index = 0;
current_function_obstack_usage = 0; current_function_obstack_usage = 0;
base_init_insns = NULL_RTX;
protect_list = NULL_TREE;
clear_temp_name (); clear_temp_name ();
...@@ -10751,7 +10789,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10751,7 +10789,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{ {
if (pedantic || warn_return_type) if (pedantic || warn_return_type)
warning ("return type for `main' changed to integer type"); pedwarn ("return type for `main' changed to integer type");
TREE_TYPE (decl1) = fntype = default_function_type; TREE_TYPE (decl1) = fntype = default_function_type;
} }
warn_about_return_type = 0; warn_about_return_type = 0;
...@@ -10795,6 +10833,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10795,6 +10833,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype)); DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype));
} }
if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
if (warn_about_return_type) if (warn_about_return_type)
warning ("return-type defaults to `int'"); warning ("return-type defaults to `int'");
...@@ -10824,14 +10866,19 @@ start_function (declspecs, declarator, raises, pre_parsed_p) ...@@ -10824,14 +10866,19 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
DECL_EXTERNAL (decl1) = current_extern_inline; DECL_EXTERNAL (decl1) = current_extern_inline;
DECL_INTERFACE_KNOWN (decl1) = 1; DECL_INTERFACE_KNOWN (decl1) = 1;
} }
else if (current_extern_inline)
{
/* `extern inline' acts like a declaration except for
defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = 1;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
else else
{ {
/* This is a definition, not a reference. /* This is a definition, not a reference.
So normally clear DECL_EXTERNAL. So clear DECL_EXTERNAL. */
However, `extern inline' acts like a declaration except for DECL_EXTERNAL (decl1) = 0;
defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1) if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))) || DECL_TEMPLATE_INSTANTIATION (decl1)))
/* We know nothing yet */; /* We know nothing yet */;
...@@ -11423,6 +11470,7 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11423,6 +11470,7 @@ finish_function (lineno, call_poplevel, nested)
if (DECL_CONSTRUCTOR_P (current_function_decl)) if (DECL_CONSTRUCTOR_P (current_function_decl))
{ {
end_protect_partials ();
expand_label (ctor_label); expand_label (ctor_label);
ctor_label = NULL_TREE; ctor_label = NULL_TREE;
...@@ -11503,6 +11551,8 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11503,6 +11551,8 @@ finish_function (lineno, call_poplevel, nested)
if (mark != get_last_insn ()) if (mark != get_last_insn ())
reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
end_protect_partials ();
/* This is where the body of the constructor ends. */ /* This is where the body of the constructor ends. */
expand_label (ctor_label); expand_label (ctor_label);
ctor_label = NULL_TREE; ctor_label = NULL_TREE;
...@@ -11643,8 +11693,14 @@ finish_function (lineno, call_poplevel, nested) ...@@ -11643,8 +11693,14 @@ finish_function (lineno, call_poplevel, nested)
/* Run the optimizers and output the assembler code for this function. */ /* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl); rest_of_compilation (fndecl);
if (DECL_DEFER_OUTPUT (fndecl)) if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
mark_inline_for_output (fndecl); {
/* Set DECL_EXTERNAL so that assemble_external will be called as
necessary. We'll clear it again in import_export_inline. */
if (TREE_PUBLIC (fndecl))
DECL_EXTERNAL (fndecl) = 1;
mark_inline_for_output (fndecl);
}
if (ctype && TREE_ASM_WRITTEN (fndecl)) if (ctype && TREE_ASM_WRITTEN (fndecl))
note_debug_info_needed (ctype); note_debug_info_needed (ctype);
...@@ -12121,7 +12177,9 @@ struct cp_function ...@@ -12121,7 +12177,9 @@ struct cp_function
tree shadowed_labels; tree shadowed_labels;
tree ctor_label; tree ctor_label;
tree dtor_label; tree dtor_label;
tree protect_list;
rtx result_rtx; rtx result_rtx;
rtx base_init_insns;
struct cp_function *next; struct cp_function *next;
struct binding_level *binding_level; struct binding_level *binding_level;
}; };
...@@ -12156,6 +12214,8 @@ push_cp_function_context (toplev) ...@@ -12156,6 +12214,8 @@ push_cp_function_context (toplev)
p->just_assigned_this = current_function_just_assigned_this; p->just_assigned_this = current_function_just_assigned_this;
p->parms_stored = current_function_parms_stored; p->parms_stored = current_function_parms_stored;
p->result_rtx = original_result_rtx; p->result_rtx = original_result_rtx;
p->base_init_insns = base_init_insns;
p->protect_list = protect_list;
} }
/* Restore the variables used during compilation of a C++ function. */ /* Restore the variables used during compilation of a C++ function. */
...@@ -12197,10 +12257,12 @@ pop_cp_function_context (toplev) ...@@ -12197,10 +12257,12 @@ pop_cp_function_context (toplev)
current_binding_level = p->binding_level; current_binding_level = p->binding_level;
ctor_label = p->ctor_label; ctor_label = p->ctor_label;
dtor_label = p->dtor_label; dtor_label = p->dtor_label;
protect_list = p->protect_list;
current_function_assigns_this = p->assigns_this; current_function_assigns_this = p->assigns_this;
current_function_just_assigned_this = p->just_assigned_this; current_function_just_assigned_this = p->just_assigned_this;
current_function_parms_stored = p->parms_stored; current_function_parms_stored = p->parms_stored;
original_result_rtx = p->result_rtx; original_result_rtx = p->result_rtx;
base_init_insns = p->base_init_insns;
free (p); free (p);
} }
...@@ -1027,6 +1027,7 @@ grok_array_decl (array_expr, index_exp) ...@@ -1027,6 +1027,7 @@ grok_array_decl (array_expr, index_exp)
tree array_expr, index_exp; tree array_expr, index_exp;
{ {
tree type = TREE_TYPE (array_expr); tree type = TREE_TYPE (array_expr);
tree p1, p2, i1, i2;
if (type == error_mark_node || index_exp == error_mark_node) if (type == error_mark_node || index_exp == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -1049,28 +1050,38 @@ grok_array_decl (array_expr, index_exp) ...@@ -1049,28 +1050,38 @@ grok_array_decl (array_expr, index_exp)
array_expr, index_exp, NULL_TREE); array_expr, index_exp, NULL_TREE);
/* Otherwise, create an ARRAY_REF for a pointer or array type. */ /* Otherwise, create an ARRAY_REF for a pointer or array type. */
if (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == ARRAY_TYPE)
return build_array_ref (array_expr, index_exp);
/* Woops, looks like they did something like `5[a]' instead of `a[5]'. if (TREE_CODE (type) == ARRAY_TYPE)
We don't emit a warning or error for this, since it's allowed p1 = array_expr;
by ARM $8.2.4. */ else
p1 = build_expr_type_conversion (WANT_POINTER, array_expr, 0);
type = TREE_TYPE (index_exp); if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)
p2 = index_exp;
else
p2 = build_expr_type_conversion (WANT_POINTER, index_exp, 0);
if (TREE_CODE (type) == OFFSET_TYPE i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0);
|| TREE_CODE (type) == REFERENCE_TYPE) i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0);
type = TREE_TYPE (type);
if (TREE_CODE (type) == POINTER_TYPE if ((p1 && i2) && (i1 && p2))
|| TREE_CODE (type) == ARRAY_TYPE) error ("ambiguous conversion for array subscript");
return build_array_ref (index_exp, array_expr);
/* The expression E1[E2] is identical (by definition) to *((E1)+(E2)). */ if (p1 && i2)
return build_indirect_ref (build_binary_op (PLUS_EXPR, array_expr, array_expr = p1, index_exp = i2;
index_exp, 1), else if (i1 && p2)
"array indexing"); array_expr = p2, index_exp = i1;
else
{
cp_error ("invalid types `%T[%T]' for array subscript",
type, TREE_TYPE (index_exp));
return error_mark_node;
}
if (array_expr == error_mark_node || index_exp == error_mark_node)
error ("ambiguous conversion for array subscript");
return build_array_ref (array_expr, index_exp);
} }
/* Given the cast expression EXP, checking out its validity. Either return /* Given the cast expression EXP, checking out its validity. Either return
...@@ -2487,8 +2498,8 @@ import_export_vtable (decl, type, final) ...@@ -2487,8 +2498,8 @@ import_export_vtable (decl, type, final)
} }
else else
{ {
/* We can only do this optimization if we have real non-inline /* We can only wait to decide if we have real non-inline virtual
virtual functions in our class, or if we come from a template. */ functions in our class, or if we come from a template. */
int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type); int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
...@@ -2543,7 +2554,8 @@ finish_prevtable_vardecl (prev, vars) ...@@ -2543,7 +2554,8 @@ finish_prevtable_vardecl (prev, vars)
tree ctype = DECL_CONTEXT (vars); tree ctype = DECL_CONTEXT (vars);
import_export_template (ctype); import_export_template (ctype);
if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype)) if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype)
&& ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
{ {
tree method; tree method;
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE; for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
...@@ -2562,19 +2574,11 @@ finish_prevtable_vardecl (prev, vars) ...@@ -2562,19 +2574,11 @@ finish_prevtable_vardecl (prev, vars)
import_export_vtable (vars, ctype, 1); import_export_vtable (vars, ctype, 1);
if (write_virtuals >= 0 if (flag_rtti && write_virtuals >= 0
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
{ {
extern tree the_null_vtable_entry;
/* Kick out the type descriptor before writing out the vtable. */ /* Kick out the type descriptor before writing out the vtable. */
if (flag_rtti) build_t_desc (ctype, 1);
{
build_t_desc (ctype, 1);
}
/* Write it out. */
mark_vtable_entries (vars);
} }
} }
...@@ -2582,39 +2586,13 @@ static void ...@@ -2582,39 +2586,13 @@ static void
finish_vtable_vardecl (prev, vars) finish_vtable_vardecl (prev, vars)
tree prev, vars; tree prev, vars;
{ {
tree ctype = DECL_CONTEXT (vars);
import_export_template (ctype);
if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype))
{
tree method;
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
method = DECL_NEXT_METHOD (method))
{
if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method))
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = ! DECL_EXTERNAL (method);
CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
if (flag_rtti)
cp_warning ("compiler error: rtti entry for `%T' decided too late", ctype);
break;
}
}
}
import_export_vtable (vars, ctype, 1);
if (write_virtuals >= 0 if (write_virtuals >= 0
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
{ {
extern tree the_null_vtable_entry;
/* Write it out. */ /* Write it out. */
mark_vtable_entries (vars); mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0) if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
store_init_value (vars, DECL_INITIAL (vars)); store_init_value (vars, DECL_INITIAL (vars));
#ifdef DWARF_DEBUGGING_INFO #ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG) if (write_symbols == DWARF_DEBUG)
...@@ -2646,8 +2624,18 @@ finish_vtable_vardecl (prev, vars) ...@@ -2646,8 +2624,18 @@ finish_vtable_vardecl (prev, vars)
rest_of_decl_compilation (vars, NULL_PTR, 1, 1); rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
} }
else if (TREE_USED (vars)) else if (! TREE_USED (vars))
assemble_external (vars); /* We don't know what to do with this one yet. */
return;
/* We know that PREV must be non-zero here. */
TREE_CHAIN (prev) = TREE_CHAIN (vars);
}
static void
prune_vtable_vardecl (prev, vars)
tree prev, vars;
{
/* We know that PREV must be non-zero here. */ /* We know that PREV must be non-zero here. */
TREE_CHAIN (prev) = TREE_CHAIN (vars); TREE_CHAIN (prev) = TREE_CHAIN (vars);
} }
...@@ -2731,6 +2719,8 @@ import_export_inline (decl) ...@@ -2731,6 +2719,8 @@ import_export_inline (decl)
if (DECL_INTERFACE_KNOWN (decl)) if (DECL_INTERFACE_KNOWN (decl))
return; return;
DECL_EXTERNAL (decl) = 0;
if (DECL_TEMPLATE_INSTANTIATION (decl)) if (DECL_TEMPLATE_INSTANTIATION (decl))
{ {
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates) if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
...@@ -2773,7 +2763,6 @@ finish_file () ...@@ -2773,7 +2763,6 @@ finish_file ()
tree fnname; tree fnname;
tree vars = static_aggregates; tree vars = static_aggregates;
int needs_cleaning = 0, needs_messing_up = 0; int needs_cleaning = 0, needs_messing_up = 0;
int have_exception_handlers = build_exception_table ();
if (flag_detailed_statistics) if (flag_detailed_statistics)
dump_tree_statistics (); dump_tree_statistics ();
...@@ -2788,7 +2777,7 @@ finish_file () ...@@ -2788,7 +2777,7 @@ finish_file ()
we'll need here. */ we'll need here. */
push_lang_context (lang_name_c); push_lang_context (lang_name_c);
if (static_ctors || vars || have_exception_handlers) if (static_ctors || vars || might_have_exceptions_p ())
needs_messing_up = 1; needs_messing_up = 1;
if (static_dtors) if (static_dtors)
needs_cleaning = 1; needs_cleaning = 1;
...@@ -2900,7 +2889,7 @@ finish_file () ...@@ -2900,7 +2889,7 @@ finish_file ()
push_momentary (); push_momentary ();
expand_start_bindings (0); expand_start_bindings (0);
if (have_exception_handlers) if (might_have_exceptions_p ())
register_exception_table (); register_exception_table ();
while (vars) while (vars)
...@@ -2931,6 +2920,7 @@ finish_file () ...@@ -2931,6 +2920,7 @@ finish_file ()
/* 9.5p5: The initializer of a static member of a class has /* 9.5p5: The initializer of a static member of a class has
the same acess rights as a member function. */ the same acess rights as a member function. */
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl); DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
#if 0 #if 0
if (init) if (init)
...@@ -3061,30 +3051,9 @@ finish_file () ...@@ -3061,30 +3051,9 @@ finish_file ()
pushdecl (vars); pushdecl (vars);
#endif #endif
walk_vtables ((void (*)())0, finish_vtable_vardecl);
if (flag_handle_signatures) if (flag_handle_signatures)
walk_sigtables ((void (*)())0, finish_sigtable_vardecl); walk_sigtables ((void (*)())0, finish_sigtable_vardecl);
for (vars = saved_inlines; vars; vars = TREE_CHAIN (vars))
{
tree decl = TREE_VALUE (vars);
if (DECL_ARTIFICIAL (decl)
&& ! DECL_INITIAL (decl)
&& TREE_USED (decl))
synthesize_method (decl);
}
for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
{
if (TREE_CODE (vars) == THUNK_DECL)
emit_thunk (vars);
else if (TREE_CODE (vars) == FUNCTION_DECL
&& ! DECL_INTERFACE_KNOWN (vars)
&& DECL_DECLARED_STATIC (vars))
TREE_PUBLIC (vars) = 0;
}
/* Now write out inline functions which had their addresses taken and /* Now write out inline functions which had their addresses taken and
which were not declared virtual and which were not declared `extern which were not declared virtual and which were not declared `extern
inline'. */ inline'. */
...@@ -3098,10 +3067,23 @@ finish_file () ...@@ -3098,10 +3067,23 @@ finish_file ()
tree place = TREE_CHAIN (saved_inlines); tree place = TREE_CHAIN (saved_inlines);
reconsider = 0; reconsider = 0;
walk_vtables ((void (*)())0, finish_vtable_vardecl);
for (; place; place = TREE_CHAIN (place)) for (; place; place = TREE_CHAIN (place))
{ {
tree decl = TREE_VALUE (place); tree decl = TREE_VALUE (place);
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl))
{
if (TREE_USED (decl))
synthesize_method (decl);
else
{
last = place;
continue;
}
}
if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0) if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0)
{ {
TREE_CHAIN (last) = TREE_CHAIN (place); TREE_CHAIN (last) = TREE_CHAIN (place);
...@@ -3114,9 +3096,7 @@ finish_file () ...@@ -3114,9 +3096,7 @@ finish_file ()
{ {
TREE_CHAIN (last) = TREE_CHAIN (place); TREE_CHAIN (last) = TREE_CHAIN (place);
if (DECL_EXTERNAL (decl)) if (! DECL_EXTERNAL (decl))
assemble_external (decl);
else
{ {
reconsider = 1; reconsider = 1;
temporary_allocation (); temporary_allocation ();
...@@ -3132,6 +3112,21 @@ finish_file () ...@@ -3132,6 +3112,21 @@ finish_file ()
} }
} }
walk_vtables ((void (*)())0, prune_vtable_vardecl);
for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
{
if (TREE_CODE (vars) == THUNK_DECL)
emit_thunk (vars);
else if (TREE_CODE (vars) == FUNCTION_DECL
&& ! DECL_INTERFACE_KNOWN (vars)
&& DECL_DECLARED_STATIC (vars))
TREE_PUBLIC (vars) = 0;
}
if (might_have_exceptions_p ())
emit_exception_table ();
if (write_virtuals == 2) if (write_virtuals == 2)
{ {
/* Now complain about an virtual function tables promised /* Now complain about an virtual function tables promised
......
...@@ -585,7 +585,7 @@ dump_decl (t, v) ...@@ -585,7 +585,7 @@ dump_decl (t, v)
break; break;
case VAR_DECL: case VAR_DECL:
if (VTABLE_NAME_P (DECL_NAME (t))) if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
{ {
OB_PUTS ("vtable for "); OB_PUTS ("vtable for ");
dump_type (DECL_CONTEXT (t), v); dump_type (DECL_CONTEXT (t), v);
...@@ -933,9 +933,16 @@ dump_expr (t, nop) ...@@ -933,9 +933,16 @@ dump_expr (t, nop)
char *p = enum_name_string (t, type); char *p = enum_name_string (t, type);
OB_PUTCP (p); OB_PUTCP (p);
} }
else if (type == char_type_node else if (type == boolean_type_node)
|| type == signed_char_type_node {
|| type == unsigned_char_type_node) if (t == boolean_false_node)
OB_PUTS ("false");
else if (t == boolean_true_node)
OB_PUTS ("true");
else
my_friendly_abort (366);
}
else if (type == char_type_node)
{ {
OB_PUTC ('\''); OB_PUTC ('\'');
dump_char (TREE_INT_CST_LOW (t)); dump_char (TREE_INT_CST_LOW (t));
......
...@@ -31,6 +31,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -31,6 +31,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "obstack.h" #include "obstack.h"
#include "expr.h" #include "expr.h"
tree protect_list;
extern void (*interim_eh_hook) PROTO((tree)); extern void (*interim_eh_hook) PROTO((tree));
/* holds the fndecl for __builtin_return_address () */ /* holds the fndecl for __builtin_return_address () */
...@@ -53,6 +55,11 @@ tree builtin_return_address_fndecl; ...@@ -53,6 +55,11 @@ tree builtin_return_address_fndecl;
#define __mips #define __mips
#endif #endif
#endif #endif
#ifdef __i386__
#ifndef __i386
#define __i386
#endif
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) || defined (__alpha) #if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) || defined (__alpha)
#define TRY_NEW_EH #define TRY_NEW_EH
#endif #endif
...@@ -872,11 +879,13 @@ void ...@@ -872,11 +879,13 @@ void
end_protect (finalization) end_protect (finalization)
tree finalization; tree finalization;
{ {
struct ehEntry *entry = pop_eh_entry (&ehstack); struct ehEntry *entry;
if (! doing_eh (0)) if (! doing_eh (0))
return; return;
entry = pop_eh_entry (&ehstack);
emit_label (entry->end_label); emit_label (entry->end_label);
entry->finalization = finalization; entry->finalization = finalization;
...@@ -1574,11 +1583,29 @@ expand_throw (exp) ...@@ -1574,11 +1583,29 @@ expand_throw (exp)
/* end of: my-cp-except.c */ /* end of: my-cp-except.c */
#endif #endif
void
end_protect_partials () {
while (protect_list)
{
end_protect (TREE_VALUE (protect_list));
protect_list = TREE_CHAIN (protect_list);
}
}
int
might_have_exceptions_p ()
{
#ifdef TRY_NEW_EH
if (eh_table_output_queue.head)
return 1;
#endif
return 0;
}
/* Output the exception table. /* Output the exception table.
Return the number of handlers. */ Return the number of handlers. */
int void
build_exception_table () emit_exception_table ()
{ {
int count = 0; int count = 0;
#ifdef TRY_NEW_EH #ifdef TRY_NEW_EH
...@@ -1587,7 +1614,15 @@ build_exception_table () ...@@ -1587,7 +1614,15 @@ build_exception_table ()
tree eh_node_decl; tree eh_node_decl;
if (! doing_eh (0)) if (! doing_eh (0))
return 0; return;
exception_section ();
/* Beginning marker for table. */
ASM_OUTPUT_ALIGN (asm_out_file, 2);
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
output_exception_table_entry (asm_out_file,
const0_rtx, const0_rtx, const0_rtx);
while (entry = dequeue_eh_entry (&eh_table_output_queue)) while (entry = dequeue_eh_entry (&eh_table_output_queue))
{ {
...@@ -1596,32 +1631,18 @@ build_exception_table () ...@@ -1596,32 +1631,18 @@ build_exception_table ()
if (context && ! TREE_ASM_WRITTEN (context)) if (context && ! TREE_ASM_WRITTEN (context))
continue; continue;
if (count == 0)
{
exception_section ();
/* Beginning marker for table. */
ASM_OUTPUT_ALIGN (asm_out_file, 2);
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
output_exception_table_entry (asm_out_file,
const0_rtx, const0_rtx, const0_rtx);
}
count++; count++;
output_exception_table_entry (asm_out_file, output_exception_table_entry (asm_out_file,
entry->start_label, entry->end_label, entry->start_label, entry->end_label,
entry->exception_handler_label); entry->exception_handler_label);
} }
if (count) /* Ending marker for table. */
{ ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
/* Ending marker for table. */ output_exception_table_entry (asm_out_file,
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__"); constm1_rtx, constm1_rtx, constm1_rtx);
output_exception_table_entry (asm_out_file,
constm1_rtx, constm1_rtx, constm1_rtx);
}
#endif /* TRY_NEW_EH */ #endif /* TRY_NEW_EH */
return count;
} }
void void
......
...@@ -157,8 +157,8 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) ...@@ -157,8 +157,8 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
/* 348 - 351 */ /* 348 - 351 */
/* Subroutine of emit_base_init. */ /* Subroutine of emit_base_init. */
static void static void
perform_member_init (member, name, init, explicit) perform_member_init (member, name, init, explicit, protect_list)
tree member, name, init; tree member, name, init, *protect_list;
int explicit; int explicit;
{ {
tree decl; tree decl;
...@@ -223,27 +223,44 @@ perform_member_init (member, name, init, explicit) ...@@ -223,27 +223,44 @@ perform_member_init (member, name, init, explicit)
} }
} }
expand_cleanups_to (NULL_TREE); expand_cleanups_to (NULL_TREE);
if (flag_handle_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
cp_warning ("caution, member `%D' may not be destroyed in the presense of an exception during construction", member); if (TYPE_NEEDS_DESTRUCTOR (type))
{
tree expr = build_component_ref (C_C_D, name, 0, explicit);
expr = build_delete (type, expr, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
if (expr != error_mark_node)
{
start_protect ();
*protect_list = tree_cons (NULL_TREE, expr, *protect_list);
}
}
} }
extern int warn_reorder;
/* Subroutine of emit_member_init. */ /* Subroutine of emit_member_init. */
static tree static tree
sort_member_init (t) sort_member_init (t)
tree t; tree t;
{ {
extern int warn_reorder;
tree x, member, name, field, init; tree x, member, name, field, init;
tree init_list = NULL_TREE; tree init_list = NULL_TREE;
tree fields_to_unmark = NULL_TREE; tree fields_to_unmark = NULL_TREE;
int found;
int last_pos = 0; int last_pos = 0;
tree last_field; tree last_field;
for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member)) for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))
{ {
int pos; int pos;
found = 0;
/* member could be, for example, a CONST_DECL for an enumerated
tag; we don't want to try to initialize that, since it already
has a value. */
if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
continue;
for (x = current_member_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos) for (x = current_member_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
{ {
/* If we cleared this out, then pay no attention to it. */ /* If we cleared this out, then pay no attention to it. */
...@@ -266,17 +283,9 @@ sort_member_init (t) ...@@ -266,17 +283,9 @@ sort_member_init (t)
if (field == member) if (field == member)
{ {
/* See if we already found an initializer for this field. */ if (warn_reorder)
if (found)
{
if (DECL_NAME (field))
cp_error ("multiple initializations given for member `%D'",
field);
continue;
}
else
{ {
if (pos < last_pos && warn_reorder) if (pos < last_pos)
{ {
cp_warning_at ("member initializers for `%#D'", last_field); cp_warning_at ("member initializers for `%#D'", last_field);
cp_warning_at (" and `%#D'", field); cp_warning_at (" and `%#D'", field);
...@@ -286,78 +295,193 @@ sort_member_init (t) ...@@ -286,78 +295,193 @@ sort_member_init (t)
last_field = field; last_field = field;
} }
init_list = chainon (init_list,
build_tree_list (name, TREE_VALUE (x)));
/* Make sure we won't try to work on this init again. */ /* Make sure we won't try to work on this init again. */
TREE_PURPOSE (x) = NULL_TREE; TREE_PURPOSE (x) = NULL_TREE;
found = 1; x = build_tree_list (name, TREE_VALUE (x));
break; goto got_it;
} }
} }
/* If we didn't find MEMBER in the list, create a dummy entry /* If we didn't find MEMBER in the list, create a dummy entry
so the two lists (INIT_LIST and the list of members) will be so the two lists (INIT_LIST and the list of members) will be
symmetrical. */ symmetrical. */
if (! found) x = build_tree_list (NULL_TREE, NULL_TREE);
init_list = chainon (init_list, build_tree_list (NULL_TREE, NULL_TREE)); got_it:
init_list = chainon (init_list, x);
} }
/* Initializers for base members go at the end. */
for (x = current_member_init_list ; x ; x = TREE_CHAIN (x)) for (x = current_member_init_list ; x ; x = TREE_CHAIN (x))
{ {
if (TREE_PURPOSE (x)) name = TREE_PURPOSE (x);
if (name)
{ {
name = TREE_PURPOSE (x); if (purpose_member (name, init_list))
init = TREE_VALUE (x);
/* XXX: this may need the COMPONENT_REF operand 0 check if
it turns out we actually get them. */
field = IDENTIFIER_CLASS_VALUE (name);
/* If one member shadows another, get the outermost one. */
if (TREE_CODE (field) == TREE_LIST)
{ {
field = TREE_VALUE (field); cp_error ("multiple initializations given for member `%D'",
if (decl_type_context (field) != current_class_type) IDENTIFIER_CLASS_VALUE (name));
cp_error ("field `%D' not in immediate context", field); continue;
} }
init_list = chainon (init_list,
build_tree_list (name, TREE_VALUE (x)));
TREE_PURPOSE (x) = NULL_TREE;
}
}
#if 0 return init_list;
/* It turns out if you have an anonymous union in the }
class, a member from it can end up not being on the
list of fields (rather, the type is), and therefore
won't be seen by the for loop above. */
/* The code in this for loop is derived from a general loop static void
which had this check in it. Theoretically, we've hit sort_base_init (t, rbase_ptr, vbase_ptr)
every initialization for the list of members in T, so tree t, *rbase_ptr, *vbase_ptr;
we shouldn't have anything but these left in this list. */ {
my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351); tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
#endif int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int i;
tree x;
tree last;
/* For warn_reorder. */
int last_pos = 0;
tree last_base = NULL_TREE;
tree rbases = NULL_TREE;
tree vbases = NULL_TREE;
if (TREE_HAS_CONSTRUCTOR (field)) /* First walk through and splice out vbase and invalid initializers.
Also replace names with binfos. */
last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list);
for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
{
tree basename = TREE_PURPOSE (x);
tree binfo;
if (basename == NULL_TREE)
{
/* Initializer for single base class. Must not
use multiple inheritance or this is ambiguous. */
switch (n_baseclasses)
{ {
if (DECL_NAME (field)) case 0:
error ("multiple initializations given for member `%s'", cp_error ("`%T' does not have a base class to initialize",
IDENTIFIER_POINTER (DECL_NAME (field))); current_class_type);
continue; return;
case 1:
break;
default:
cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
current_class_type);
return;
} }
binfo = TREE_VEC_ELT (binfos, 0);
}
else if (is_aggr_typedef (basename, 1))
{
binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
if (binfo == NULL_TREE)
continue;
TREE_HAS_CONSTRUCTOR (field) = 1; /* Virtual base classes are special cases. Their initializers
fields_to_unmark = tree_cons (NULL_TREE, field, fields_to_unmark); are recorded with this constructor, and they are used when
this constructor is the top-level constructor called. */
if (TREE_VIA_VIRTUAL (binfo))
{
tree v = CLASSTYPE_VBASECLASSES (t);
while (BINFO_TYPE (v) != BINFO_TYPE (binfo))
v = TREE_CHAIN (v);
perform_member_init (field, name, init, 1); vbases = tree_cons (v, TREE_VALUE (x), vbases);
TREE_PURPOSE (x) = NULL_TREE; continue;
}
else
{
/* Otherwise, if it is not an immediate base class, complain. */
for (i = n_baseclasses-1; i >= 0; i--)
if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
break;
if (i < 0)
{
cp_error ("`%T' is not an immediate base class of `%T'",
IDENTIFIER_TYPE_VALUE (basename),
current_class_type);
continue;
}
}
} }
else
my_friendly_abort (365);
TREE_PURPOSE (x) = binfo;
TREE_CHAIN (last) = x;
last = x;
} }
TREE_CHAIN (last) = NULL_TREE;
/* Unmark fields which are initialized for the base class. */ /* Now walk through our regular bases and make sure they're initialized. */
while (fields_to_unmark)
for (i = 0; i < n_baseclasses; ++i)
{ {
TREE_HAS_CONSTRUCTOR (TREE_VALUE (fields_to_unmark)) = 0; tree base_binfo = TREE_VEC_ELT (binfos, i);
/* XXX is this a memory leak? */ int pos;
fields_to_unmark = TREE_CHAIN (fields_to_unmark);
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
for (x = current_base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
{
tree binfo = TREE_PURPOSE (x);
if (binfo == NULL_TREE)
continue;
if (binfo == base_binfo)
{
if (warn_reorder)
{
if (pos < last_pos)
{
cp_warning_at ("base initializers for `%#T'", last_base);
cp_warning_at (" and `%#T'", BINFO_TYPE (binfo));
warning (" will be re-ordered to match inheritance order");
}
last_pos = pos;
last_base = BINFO_TYPE (binfo);
}
/* Make sure we won't try to work on this init again. */
TREE_PURPOSE (x) = NULL_TREE;
x = build_tree_list (binfo, TREE_VALUE (x));
goto got_it;
}
}
/* If we didn't find BASE_BINFO in the list, create a dummy entry
so the two lists (RBASES and the list of bases) will be
symmetrical. */
x = build_tree_list (NULL_TREE, NULL_TREE);
got_it:
rbases = chainon (rbases, x);
} }
return init_list; *rbase_ptr = rbases;
*vbase_ptr = vbases;
}
/* Perform partial cleanups for a base for exception handling. */
static tree
build_partial_cleanup_for (binfo)
tree binfo;
{
tree expr = convert_pointer_to_real (binfo,
build_unary_op (ADDR_EXPR, C_C_D, 0));
return build_delete (TREE_TYPE (expr),
expr,
integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
} }
/* Perform whatever initializations have yet to be done on the base /* Perform whatever initializations have yet to be done on the base
...@@ -385,13 +509,14 @@ emit_base_init (t, immediately) ...@@ -385,13 +509,14 @@ emit_base_init (t, immediately)
{ {
extern tree in_charge_identifier; extern tree in_charge_identifier;
tree member, vbases; tree member, x;
tree init_list; tree mem_init_list;
int pass, start; tree rbase_init_list, vbase_init_list;
tree t_binfo = TYPE_BINFO (t); tree t_binfo = TYPE_BINFO (t);
tree binfos = BINFO_BASETYPES (t_binfo); tree binfos = BINFO_BASETYPES (t_binfo);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
int have_init_list = 0, from_init_list;
my_friendly_assert (protect_list == NULL_TREE, 999);
if (! immediately) if (! immediately)
{ {
...@@ -407,172 +532,31 @@ emit_base_init (t, immediately) ...@@ -407,172 +532,31 @@ emit_base_init (t, immediately)
emit_line_note_force (DECL_SOURCE_FILE (current_function_decl), emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),
DECL_SOURCE_LINE (current_function_decl)); DECL_SOURCE_LINE (current_function_decl));
start = ! TYPE_USES_VIRTUAL_BASECLASSES (t); mem_init_list = sort_member_init (t);
for (pass = start; pass < 2; pass++) current_member_init_list = NULL_TREE;
{
tree vbase_init_list = NULL_TREE;
for (init_list = current_base_init_list; init_list;
init_list = TREE_CHAIN (init_list))
{
tree basename = TREE_PURPOSE (init_list);
tree binfo;
tree init = TREE_VALUE (init_list);
if (basename == NULL_TREE)
{
/* Initializer for single base class. Must not
use multiple inheritance or this is ambiguous. */
switch (n_baseclasses)
{
case 0:
cp_error ("`%T' does not have a base class to initialize",
current_class_type);
return;
case 1:
break;
default:
cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
current_class_type);
return;
}
binfo = TREE_VEC_ELT (binfos, 0);
}
else if (is_aggr_typedef (basename, 1))
{
binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
if (binfo == NULL_TREE)
continue;
/* Virtual base classes are special cases. Their initializers
are recorded with this constructor, and they are used when
this constructor is the top-level constructor called. */
if (! TREE_VIA_VIRTUAL (binfo))
{
/* Otherwise, if it is not an immediate base class, complain. */
for (i = n_baseclasses-1; i >= 0; i--)
if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
break;
if (i < 0)
{
cp_error ("`%T' is not an immediate base class of `%T'",
IDENTIFIER_TYPE_VALUE (basename),
current_class_type);
continue;
}
}
}
else
continue;
/* The base initialization list goes up to the first
base class which can actually use it. */
if (pass == start)
{
char *msgp = (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
? "cannot pass initialization up to class `%s'" : 0;
while (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo))
&& BINFO_BASETYPES (binfo) != NULL_TREE
&& TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 1)
{
/* ?? This should be fixed in RENO by forcing
default constructors to exist. */
SET_BINFO_BASEINIT_MARKED (binfo);
binfo = BINFO_BASETYPE (binfo, 0);
}
/* We used to give an error if this wasn't true, saying that
there's no constructor for the initialization of basename.
This turned out to be incorrect---it should use the
default constructor, since a user could try to initialize
the class in a derived class's base initializer list. */
if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
{
if (msgp)
{
if (pedantic)
error_with_aggr_type (binfo, msgp);
else
msgp = NULL;
}
}
if (BINFO_BASEINIT_MARKED (binfo))
{
msgp = "class `%s' initializer already specified";
error (msgp, IDENTIFIER_POINTER (basename));
}
if (msgp)
continue;
SET_BINFO_BASEINIT_MARKED (binfo);
if (TREE_VIA_VIRTUAL (binfo))
{
vbase_init_list = tree_cons (init, BINFO_TYPE (binfo),
vbase_init_list);
continue;
}
if (pass == 0)
continue;
}
else if (TREE_VIA_VIRTUAL (binfo))
continue;
member = convert_pointer_to (binfo, current_class_decl); sort_base_init (t, &rbase_init_list, &vbase_init_list);
expand_aggr_init_1 (binfo, 0, current_base_init_list = NULL_TREE;
build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (binfo), LOOKUP_NORMAL);
expand_cleanups_to (NULL_TREE);
}
if (pass == 0) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{ {
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)); tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
tree vbases;
if (DECL_NAME (current_function_decl) == NULL_TREE expand_start_cond (first_arg, 0);
&& TREE_CHAIN (first_arg) != NULL_TREE) expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
{ vbase_init_list);
/* If there are virtual baseclasses without initialization expand_end_cond ();
specified, and this is a default X(X&) constructor,
build the initialization list so that each virtual baseclass
of the new object is initialized from the virtual baseclass
of the incoming arg. */
tree init_arg = build_unary_op (ADDR_EXPR, TREE_CHAIN (first_arg), 0);
for (vbases = CLASSTYPE_VBASECLASSES (t);
vbases; vbases = TREE_CHAIN (vbases))
{
if (BINFO_BASEINIT_MARKED (vbases) == 0)
{
member = convert_pointer_to (vbases, init_arg);
if (member == init_arg)
member = TREE_CHAIN (first_arg);
else
TREE_TYPE (member) = build_reference_type (BINFO_TYPE (vbases));
vbase_init_list = tree_cons (convert_from_reference (member),
vbases, vbase_init_list);
SET_BINFO_BASEINIT_MARKED (vbases);
}
}
}
expand_start_cond (first_arg, 0);
expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
vbase_init_list);
expand_end_cond ();
}
} }
current_base_init_list = NULL_TREE;
/* Now, perform default initialization of all base classes which /* Now, perform initialization of non-virtual base classes. */
have not yet been initialized, and unmark baseclasses which
have been initialized. */
for (i = 0; i < n_baseclasses; i++) for (i = 0; i < n_baseclasses; i++)
{ {
tree base = current_class_decl; tree base = current_class_decl;
tree base_binfo = TREE_VEC_ELT (binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i);
tree init = void_list_node;
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
#if 0 /* Once unsharing happens soon enough. */ #if 0 /* Once unsharing happens soon enough. */
my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo); my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo);
...@@ -580,109 +564,113 @@ emit_base_init (t, immediately) ...@@ -580,109 +564,113 @@ emit_base_init (t, immediately)
BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo; BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
#endif #endif
if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo))) if (TREE_PURPOSE (rbase_init_list))
{ init = TREE_VALUE (rbase_init_list);
if (! TREE_VIA_VIRTUAL (base_binfo) else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
&& ! BINFO_BASEINIT_MARKED (base_binfo)) init = NULL_TREE;
{
tree ref;
if (BINFO_OFFSET_ZEROP (base_binfo)) if (init != void_list_node)
base = build1 (NOP_EXPR, {
TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), member = convert_pointer_to (base_binfo, current_class_decl);
current_class_decl); expand_aggr_init_1 (base_binfo, 0,
else build_indirect_ref (member, NULL_PTR), init,
base = build (PLUS_EXPR, BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), expand_cleanups_to (NULL_TREE);
current_class_decl, BINFO_OFFSET (base_binfo));
ref = build_indirect_ref (base, NULL_PTR);
expand_aggr_init_1 (base_binfo, 0, ref, NULL_TREE,
BINFO_OFFSET_ZEROP (base_binfo),
LOOKUP_NORMAL);
expand_cleanups_to (NULL_TREE);
}
} }
CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
if (! TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{ {
while (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo)) start_protect ();
&& BINFO_BASETYPES (base_binfo) != NULL_TREE protect_list = tree_cons (NULL_TREE,
&& TREE_VEC_LENGTH (BINFO_BASETYPES (base_binfo)) == 1) build_partial_cleanup_for (base_binfo),
{ protect_list);
/* ?? This should be fixed in RENO by forcing
default constructors to exist. It is needed for symmetry
with code above. */
base_binfo = BINFO_BASETYPE (base_binfo, 0);
CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
}
} }
rbase_init_list = TREE_CHAIN (rbase_init_list);
} }
/* Initialize all the virtual function table fields that /* Initialize all the virtual function table fields that
do come from virtual base classes. */ do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0); expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0);
for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
CLEAR_BINFO_BASEINIT_MARKED (vbases);
/* Initialize all the virtual function table fields that /* Initialize all the virtual function table fields that
do not come from virtual base classes. */ do not come from virtual base classes. */
expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl); expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
if (current_member_init_list)
{
init_list = sort_member_init (t);
have_init_list = 1;
}
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
{ {
tree init, name; tree init, name;
from_init_list = 0; int from_init_list;
/* member could be, for example, a CONST_DECL for an enumerated
tag; we don't want to try to initialize that, since it already
has a value. */
if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
continue;
/* See if we had a user-specified member initialization. */ /* See if we had a user-specified member initialization. */
if (have_init_list) if (TREE_PURPOSE (mem_init_list))
{ {
if (TREE_PURPOSE (init_list)) name = TREE_PURPOSE (mem_init_list);
{ init = TREE_VALUE (mem_init_list);
name = TREE_PURPOSE (init_list); from_init_list = 1;
init = TREE_VALUE (init_list);
from_init_list = 1;
if (TREE_STATIC (member)) /* Also see if it's ever a COMPONENT_REF here. If it is, we
{ need to do `expand_assignment (name, init, 0, 0);' and
cp_error ("field `%#D' is static; only point of initialization is its declaration", a continue. */
member); my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349);
continue;
}
/* Also see if it's ever a COMPONENT_REF here. If it is, we
need to do `expand_assignment (name, init, 0, 0);' and
a continue. */
my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349);
}
init_list = TREE_CHAIN (init_list);
} }
else
if (! from_init_list)
{ {
/* member could be, for example, a CONST_DECL for an enumerated
tag; we don't want to try to initialize that, since it already
has a value. */
if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
continue;
name = DECL_NAME (member); name = DECL_NAME (member);
init = DECL_INITIAL (member); init = DECL_INITIAL (member);
from_init_list = 0;
} }
perform_member_init (member, name, init, from_init_list); perform_member_init (member, name, init, from_init_list, &protect_list);
mem_init_list = TREE_CHAIN (mem_init_list);
} }
current_member_init_list = NULL_TREE; /* Now initialize any members from our bases. */
while (mem_init_list)
{
tree name, init, field;
if (TREE_PURPOSE (mem_init_list))
{
name = TREE_PURPOSE (mem_init_list);
init = TREE_VALUE (mem_init_list);
/* XXX: this may need the COMPONENT_REF operand 0 check if
it turns out we actually get them. */
field = IDENTIFIER_CLASS_VALUE (name);
/* If one member shadows another, get the outermost one. */
if (TREE_CODE (field) == TREE_LIST)
{
field = TREE_VALUE (field);
if (decl_type_context (field) != current_class_type)
cp_error ("field `%D' not in immediate context", field);
}
#if 0
/* It turns out if you have an anonymous union in the
class, a member from it can end up not being on the
list of fields (rather, the type is), and therefore
won't be seen by the for loop above. */
/* The code in this for loop is derived from a general loop
which had this check in it. Theoretically, we've hit
every initialization for the list of members in T, so
we shouldn't have anything but these left in this list. */
my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351);
#endif
perform_member_init (field, name, init, 1, &protect_list);
}
mem_init_list = TREE_CHAIN (mem_init_list);
}
if (! immediately) if (! immediately)
{ {
...@@ -750,14 +738,13 @@ static void ...@@ -750,14 +738,13 @@ static void
expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
tree binfo, exp, addr, init_list; tree binfo, exp, addr, init_list;
{ {
tree init = value_member (BINFO_TYPE (binfo), init_list); tree init = purpose_member (binfo, init_list);
tree ref = build_indirect_ref (addr, NULL_PTR); tree ref = build_indirect_ref (addr, NULL_PTR);
if (init) if (init)
init = TREE_PURPOSE (init); init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */ /* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN); expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
expand_cleanups_to (NULL_TREE); expand_cleanups_to (NULL_TREE);
CLEAR_BINFO_VBASE_INIT_MARKED (binfo);
} }
/* Initialize this object's virtual base class pointers. This must be /* Initialize this object's virtual base class pointers. This must be
...@@ -781,38 +768,14 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list) ...@@ -781,38 +768,14 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list)
if (result) if (result)
expand_expr_stmt (build_compound_expr (result)); expand_expr_stmt (build_compound_expr (result));
/* Mark everything as having an initializer for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
(either explicit or default). */ vbases = TREE_CHAIN (vbases))
for (vbases = CLASSTYPE_VBASECLASSES (type); {
vbases; vbases = TREE_CHAIN (vbases)) tree tmp = purpose_member (vbases, result);
SET_BINFO_VBASE_INIT_MARKED (vbases); expand_aggr_vbase_init_1 (vbases, exp,
TREE_OPERAND (TREE_VALUE (tmp), 0),
/* First, initialize baseclasses which could be baseclasses init_list);
for other virtual baseclasses. */ }
for (vbases = CLASSTYPE_VBASECLASSES (type);
vbases; vbases = TREE_CHAIN (vbases))
/* Don't initialize twice. */
if (BINFO_VBASE_INIT_MARKED (vbases))
{
tree tmp = result;
while (BINFO_TYPE (vbases) != BINFO_TYPE (TREE_PURPOSE (tmp)))
tmp = TREE_CHAIN (tmp);
expand_aggr_vbase_init_1 (vbases, exp,
TREE_OPERAND (TREE_VALUE (tmp), 0),
init_list);
}
/* Now initialize the baseclasses which don't have virtual baseclasses. */
for (; result; result = TREE_CHAIN (result))
/* Don't initialize twice. */
if (BINFO_VBASE_INIT_MARKED (TREE_PURPOSE (result)))
{
my_friendly_abort (47);
expand_aggr_vbase_init_1 (TREE_PURPOSE (result), exp,
TREE_OPERAND (TREE_VALUE (result), 0),
init_list);
}
} }
} }
...@@ -862,7 +825,7 @@ member_init_ok_or_else (field, type, member_name) ...@@ -862,7 +825,7 @@ member_init_ok_or_else (field, type, member_name)
if (field == NULL_TREE) if (field == NULL_TREE)
{ {
cp_error ("class `%T' does not have any field named `%s'", type, cp_error ("class `%T' does not have any field named `%s'", type,
member_name); member_name);
return 0; return 0;
} }
if (DECL_CONTEXT (field) != type if (DECL_CONTEXT (field) != type
...@@ -872,6 +835,13 @@ member_init_ok_or_else (field, type, member_name) ...@@ -872,6 +835,13 @@ member_init_ok_or_else (field, type, member_name)
field); field);
return 0; return 0;
} }
if (TREE_STATIC (field))
{
cp_error ("field `%#D' is static; only point of initialization is its declaration",
field);
return 0;
}
return 1; return 1;
} }
...@@ -1209,7 +1179,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -1209,7 +1179,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
tree rval; tree rval;
tree parms; tree parms;
if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) if (init == NULL_TREE
|| (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))
{ {
parms = init; parms = init;
if (parms) if (parms)
...@@ -2044,6 +2015,12 @@ build_offset_ref (cname, name) ...@@ -2044,6 +2015,12 @@ build_offset_ref (cname, name)
return t; return t;
} }
if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t))
{
cp_error ("illegal pointer to bit field `%D'", t);
return error_mark_node;
}
/* static class functions too. */ /* static class functions too. */
if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
my_friendly_abort (53); my_friendly_abort (53);
...@@ -2085,7 +2062,7 @@ get_member_function (exp_addr_ptr, exp, member) ...@@ -2085,7 +2062,7 @@ get_member_function (exp_addr_ptr, exp, member)
if (UNITS_PER_WORD <= 1) if (UNITS_PER_WORD <= 1)
my_friendly_abort (54); my_friendly_abort (54);
e1 = build (GT_EXPR, integer_type_node, e0, integer_zero_node); e1 = build (GT_EXPR, boolean_type_node, e0, integer_zero_node);
e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr, e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
build_tree_list (NULL_TREE, e1))); build_tree_list (NULL_TREE, e1)));
e1 = save_expr (e1); e1 = save_expr (e1);
...@@ -2240,7 +2217,7 @@ resolve_offset_ref (exp) ...@@ -2240,7 +2217,7 @@ resolve_offset_ref (exp)
} }
else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member))) else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
{ {
return get_member_function_from_ptrfunc (&addr, base, member); return get_member_function_from_ptrfunc (&addr, member);
} }
my_friendly_abort (56); my_friendly_abort (56);
/* NOTREACHED */ /* NOTREACHED */
...@@ -2322,7 +2299,13 @@ is_friend (type, supplicant) ...@@ -2322,7 +2299,13 @@ is_friend (type, supplicant)
{ {
tree list = DECL_FRIENDLIST (TYPE_NAME (type)); tree list = DECL_FRIENDLIST (TYPE_NAME (type));
tree name = DECL_NAME (supplicant); tree name = DECL_NAME (supplicant);
tree ctype = DECL_CLASS_CONTEXT (supplicant); tree ctype;
if (DECL_FUNCTION_MEMBER_P (supplicant))
ctype = DECL_CLASS_CONTEXT (supplicant);
else
ctype = NULL_TREE;
for (; list ; list = TREE_CHAIN (list)) for (; list ; list = TREE_CHAIN (list))
{ {
if (name == TREE_PURPOSE (list)) if (name == TREE_PURPOSE (list))
...@@ -2353,8 +2336,14 @@ is_friend (type, supplicant) ...@@ -2353,8 +2336,14 @@ is_friend (type, supplicant)
} }
{ {
tree context = declp ? DECL_CLASS_CONTEXT (supplicant) tree context;
: DECL_CONTEXT (TYPE_NAME (supplicant));
if (! declp)
context = DECL_CONTEXT (TYPE_NAME (supplicant));
else if (DECL_FUNCTION_MEMBER_P (supplicant))
context = DECL_CLASS_CONTEXT (supplicant);
else
context = NULL_TREE;
if (context) if (context)
return is_friend (type, context); return is_friend (type, context);
...@@ -2508,7 +2497,7 @@ make_friend_class (type, friend_type) ...@@ -2508,7 +2497,7 @@ make_friend_class (type, friend_type)
} }
if (type == friend_type) if (type == friend_type)
{ {
warning ("class `%s' is implicitly friends with itself", pedwarn ("class `%s' is implicitly friends with itself",
TYPE_NAME_STRING (type)); TYPE_NAME_STRING (type));
return; return;
} }
...@@ -2803,7 +2792,7 @@ build_new (placement, decl, init, use_global_new) ...@@ -2803,7 +2792,7 @@ build_new (placement, decl, init, use_global_new)
{ {
tree type, true_type, size, rval; tree type, true_type, size, rval;
tree nelts; tree nelts;
tree alloc_expr; tree alloc_expr, alloc_temp;
int has_array = 0; int has_array = 0;
enum tree_code code = NEW_EXPR; enum tree_code code = NEW_EXPR;
...@@ -2927,6 +2916,12 @@ build_new (placement, decl, init, use_global_new) ...@@ -2927,6 +2916,12 @@ build_new (placement, decl, init, use_global_new)
type = true_type = TREE_TYPE (type); type = true_type = TREE_TYPE (type);
} }
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("new cannot be applied to a function type");
return error_mark_node;
}
/* When the object being created is an array, the new-expression yields a /* When the object being created is an array, the new-expression yields a
pointer to the initial element (if any) of the array. For example, pointer to the initial element (if any) of the array. For example,
both new int and new int[10] return an int*. 5.3.4. */ both new int and new int[10] return an int*. 5.3.4. */
...@@ -2956,7 +2951,7 @@ build_new (placement, decl, init, use_global_new) ...@@ -2956,7 +2951,7 @@ build_new (placement, decl, init, use_global_new)
if (true_type == void_type_node) if (true_type == void_type_node)
{ {
error ("invalid type for new: `void'"); error ("invalid type `void' for new");
return error_mark_node; return error_mark_node;
} }
...@@ -3032,12 +3027,19 @@ build_new (placement, decl, init, use_global_new) ...@@ -3032,12 +3027,19 @@ build_new (placement, decl, init, use_global_new)
TREE_CALLS_NEW (rval) = 1; TREE_CALLS_NEW (rval) = 1;
} }
if (flag_check_new) if (flag_check_new && rval)
{ {
if (rval) /* For array new, we need to make sure that the call to new is
rval = save_expr (rval); not expanded as part of the RTL_EXPR for the initialization,
alloc_expr = rval; so we can't just use save_expr here. */
alloc_temp = get_temp_name (TREE_TYPE (rval), 0);
alloc_expr = build (MODIFY_EXPR, TREE_TYPE (rval), alloc_temp, rval);
TREE_SIDE_EFFECTS (alloc_expr) = 1;
rval = alloc_temp;
} }
else
alloc_expr = NULL_TREE;
/* if rval is NULL_TREE I don't have to allocate it, but are we totally /* if rval is NULL_TREE I don't have to allocate it, but are we totally
sure we have some extra bytes in that case for the BI_header_size sure we have some extra bytes in that case for the BI_header_size
...@@ -3184,10 +3186,17 @@ build_new (placement, decl, init, use_global_new) ...@@ -3184,10 +3186,17 @@ build_new (placement, decl, init, use_global_new)
done: done:
if (flag_check_new && alloc_expr && rval != alloc_expr) if (alloc_expr)
{ {
tree ifexp = build_binary_op (NE_EXPR, alloc_expr, integer_zero_node, 1); /* Did we modify the storage? */
rval = build_conditional_expr (ifexp, rval, alloc_expr); if (rval != alloc_temp)
{
tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
integer_zero_node, 1);
rval = build_conditional_expr (ifexp, rval, alloc_temp);
}
else
rval = alloc_expr;
} }
if (rval && TREE_TYPE (rval) != build_pointer_type (type)) if (rval && TREE_TYPE (rval) != build_pointer_type (type))
...@@ -3354,7 +3363,7 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -3354,7 +3363,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
} }
} }
expand_start_cond (build (GE_EXPR, integer_type_node, expand_start_cond (build (GE_EXPR, boolean_type_node,
iterator, integer_zero_node), 0); iterator, integer_zero_node), 0);
expand_start_loop_continue_elsewhere (1); expand_start_loop_continue_elsewhere (1);
...@@ -3394,7 +3403,7 @@ expand_vec_init (decl, base, maxindex, init, from_array) ...@@ -3394,7 +3403,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
expand_assignment (base2, expand_assignment (base2,
build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0); build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0);
expand_loop_continue_here (); expand_loop_continue_here ();
expand_exit_loop_if_false (0, build (NE_EXPR, integer_type_node, expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node,
build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one)); build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one));
if (obey_regdecls) if (obey_regdecls)
...@@ -3975,7 +3984,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete, ...@@ -3975,7 +3984,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
body = tree_cons (NULL_TREE, body = tree_cons (NULL_TREE,
build (EXIT_EXPR, void_type_node, build (EXIT_EXPR, void_type_node,
build (EQ_EXPR, integer_type_node, base, tbase)), build (EQ_EXPR, boolean_type_node, base, tbase)),
body); body);
loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body)); loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
...@@ -4031,7 +4040,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete, ...@@ -4031,7 +4040,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
/* Outermost wrapper: If pointer is null, punt. */ /* Outermost wrapper: If pointer is null, punt. */
body = build (COND_EXPR, void_type_node, body = build (COND_EXPR, void_type_node,
build (NE_EXPR, integer_type_node, base, integer_zero_node), build (NE_EXPR, boolean_type_node, base, integer_zero_node),
body, integer_zero_node); body, integer_zero_node);
body = build1 (NOP_EXPR, void_type_node, body); body = build1 (NOP_EXPR, void_type_node, body);
......
...@@ -4541,8 +4541,6 @@ real_yylex () ...@@ -4541,8 +4541,6 @@ real_yylex ()
{ value = '}'; goto done; } { value = '}'; goto done; }
else if (c == '%' && c1 == ':') else if (c == '%' && c1 == ':')
{ value = '#'; goto done; } { value = '#'; goto done; }
else if (c == ':' && c1 == '>')
{ value = ']'; goto done; }
nextchar = c1; nextchar = c1;
token_buffer[1] = 0; token_buffer[1] = 0;
...@@ -4560,6 +4558,11 @@ real_yylex () ...@@ -4560,6 +4558,11 @@ real_yylex ()
value = SCOPE; value = SCOPE;
yylval.itype = 1; yylval.itype = 1;
} }
else if (c == '>')
{
value = ']';
goto done;
}
else else
{ {
nextchar = c; nextchar = c;
......
...@@ -2211,12 +2211,14 @@ synthesize_method (fndecl) ...@@ -2211,12 +2211,14 @@ synthesize_method (fndecl)
int nested = (current_function_decl != NULL_TREE); int nested = (current_function_decl != NULL_TREE);
int toplev = (decl_function_context (fndecl) == NULL_TREE); int toplev = (decl_function_context (fndecl) == NULL_TREE);
char *f = input_filename; char *f = input_filename;
tree base = DECL_CLASS_CONTEXT (fndecl);
if (nested) if (nested)
push_cp_function_context (toplev); push_cp_function_context (toplev);
input_filename = DECL_SOURCE_FILE (fndecl); input_filename = DECL_SOURCE_FILE (fndecl);
extract_interface_info (); interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base);
interface_only = CLASSTYPE_INTERFACE_ONLY (base);
start_function (NULL_TREE, fndecl, NULL_TREE, 1); start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls (); store_parm_decls ();
......
...@@ -1074,8 +1074,10 @@ unary_expr: ...@@ -1074,8 +1074,10 @@ unary_expr:
{ {
tree t = TREE_VALUE ($2); tree t = TREE_VALUE ($2);
if (t != NULL_TREE if (t != NULL_TREE
&& TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) && ((TREE_TYPE (t)
pedwarn ("ANSI C++ forbids using sizeof() on a function"); && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
|| is_overloaded_fn (t)))
pedwarn ("ANSI C++ forbids taking the sizeof a function type");
} }
$$ = c_sizeof (TREE_TYPE ($2)); } $$ = c_sizeof (TREE_TYPE ($2)); }
| SIZEOF '(' type_id ')' %prec HYPERUNARY | SIZEOF '(' type_id ')' %prec HYPERUNARY
...@@ -1142,7 +1144,7 @@ new_initializer: ...@@ -1142,7 +1144,7 @@ new_initializer:
syntactically valid but semantically invalid. */ syntactically valid but semantically invalid. */
| '=' init | '=' init
{ {
if (flag_ansi) if (pedantic)
pedwarn ("ANSI C++ forbids initialization of new expression with `='"); pedwarn ("ANSI C++ forbids initialization of new expression with `='");
$$ = $2; $$ = $2;
} }
...@@ -1169,7 +1171,7 @@ cast_expr: ...@@ -1169,7 +1171,7 @@ cast_expr:
{ {
tree init = build_nt (CONSTRUCTOR, NULL_TREE, tree init = build_nt (CONSTRUCTOR, NULL_TREE,
nreverse ($3)); nreverse ($3));
if (flag_ansi) if (pedantic)
pedwarn ("ANSI C++ forbids constructor-expressions"); pedwarn ("ANSI C++ forbids constructor-expressions");
/* Indicate that this was a GNU C constructor expression. */ /* Indicate that this was a GNU C constructor expression. */
TREE_HAS_CONSTRUCTOR (init) = 1; TREE_HAS_CONSTRUCTOR (init) = 1;
...@@ -1289,7 +1291,6 @@ unqualified_id: ...@@ -1289,7 +1291,6 @@ unqualified_id:
expr_or_declarator: expr_or_declarator:
notype_unqualified_id notype_unqualified_id
| notype_qualified_id
| '*' expr_or_declarator %prec UNARY | '*' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); } { $$ = build_parse_node (INDIRECT_REF, $2); }
| '&' expr_or_declarator %prec UNARY | '&' expr_or_declarator %prec UNARY
...@@ -1301,9 +1302,6 @@ expr_or_declarator: ...@@ -1301,9 +1302,6 @@ expr_or_declarator:
direct_notype_declarator: direct_notype_declarator:
complex_direct_notype_declarator complex_direct_notype_declarator
| notype_unqualified_id | notype_unqualified_id
| notype_qualified_id
{ push_nested_class (TREE_TYPE (OP0 ($$)), 3);
TREE_COMPLEXITY ($$) = current_class_depth; }
| '(' expr_or_declarator ')' | '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); } { $$ = finish_decl_parsing ($2); }
; ;
...@@ -1360,7 +1358,7 @@ primary: ...@@ -1360,7 +1358,7 @@ primary:
$<ttype>$ = expand_start_stmt_expr (); } $<ttype>$ = expand_start_stmt_expr (); }
compstmt ')' compstmt ')'
{ tree rtl_exp; { tree rtl_exp;
if (flag_ansi) if (pedantic)
pedwarn ("ANSI C++ forbids braced-groups within expressions"); pedwarn ("ANSI C++ forbids braced-groups within expressions");
rtl_exp = expand_end_stmt_expr ($<ttype>2); rtl_exp = expand_end_stmt_expr ($<ttype>2);
/* The statements have side effects, so the group does. */ /* The statements have side effects, so the group does. */
...@@ -1554,7 +1552,7 @@ primary: ...@@ -1554,7 +1552,7 @@ primary:
| object unqualified_id %prec UNARY | object unqualified_id %prec UNARY
{ got_object = NULL_TREE; { got_object = NULL_TREE;
$$ = build_component_ref ($$, $2, NULL_TREE, 1); } $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
| object qualified_id %prec UNARY | object overqualified_id %prec UNARY
{ got_object = NULL_TREE; { got_object = NULL_TREE;
$$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); } $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
| object unqualified_id '(' nonnull_exprlist ')' | object unqualified_id '(' nonnull_exprlist ')'
...@@ -1589,7 +1587,7 @@ primary: ...@@ -1589,7 +1587,7 @@ primary:
(LOOKUP_NORMAL|LOOKUP_AGGR)); (LOOKUP_NORMAL|LOOKUP_AGGR));
#endif #endif
} }
| object qualified_id '(' nonnull_exprlist ')' | object overqualified_id '(' nonnull_exprlist ')'
{ {
got_object = NULL_TREE; got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
...@@ -1601,7 +1599,7 @@ primary: ...@@ -1601,7 +1599,7 @@ primary:
else else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4); $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
} }
| object qualified_id LEFT_RIGHT | object overqualified_id LEFT_RIGHT
{ {
got_object = NULL_TREE; got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2)))) if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
...@@ -1617,8 +1615,9 @@ primary: ...@@ -1617,8 +1615,9 @@ primary:
| object '~' TYPESPEC LEFT_RIGHT | object '~' TYPESPEC LEFT_RIGHT
{ {
got_object = NULL_TREE; got_object = NULL_TREE;
if (TREE_CODE (TREE_TYPE ($1)) if (IDENTIFIER_GLOBAL_VALUE ($3)
!= TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3)))) && (TREE_CODE (TREE_TYPE ($1))
!= TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3)))))
cp_error ("`%E' is not of type `%T'", $1, $3); cp_error ("`%E' is not of type `%T'", $1, $3);
$$ = convert (void_type_node, $1); $$ = convert (void_type_node, $1);
} }
...@@ -1654,7 +1653,7 @@ primary_no_id: ...@@ -1654,7 +1653,7 @@ primary_no_id:
} }
$<ttype>$ = expand_start_stmt_expr (); } $<ttype>$ = expand_start_stmt_expr (); }
compstmt ')' compstmt ')'
{ if (flag_ansi) { if (pedantic)
pedwarn ("ANSI C++ forbids braced-groups within expressions"); pedwarn ("ANSI C++ forbids braced-groups within expressions");
$$ = expand_end_stmt_expr ($<ttype>2); } $$ = expand_end_stmt_expr ($<ttype>2); }
| primary_no_id '(' nonnull_exprlist ')' | primary_no_id '(' nonnull_exprlist ')'
...@@ -1816,6 +1815,8 @@ typed_declspecs1: ...@@ -1816,6 +1815,8 @@ typed_declspecs1:
{ $$ = decl_tree_cons (NULL_TREE, $2, $$); } { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
| typespec reserved_declspecs %prec HYPERUNARY | typespec reserved_declspecs %prec HYPERUNARY
{ $$ = decl_tree_cons (NULL_TREE, $$, $2); } { $$ = decl_tree_cons (NULL_TREE, $$, $2); }
| typespec reserved_typespecquals reserved_declspecs
{ $$ = decl_tree_cons (NULL_TREE, $$, chainon ($2, $3)); }
| declmods typespec reserved_declspecs | declmods typespec reserved_declspecs
{ $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); } { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
| declmods typespec reserved_typespecquals | declmods typespec reserved_typespecquals
...@@ -1902,11 +1903,11 @@ typespec: structsp ...@@ -1902,11 +1903,11 @@ typespec: structsp
| complete_type_name | complete_type_name
| TYPEOF '(' expr ')' | TYPEOF '(' expr ')'
{ $$ = TREE_TYPE ($3); { $$ = TREE_TYPE ($3);
if (flag_ansi) if (pedantic)
pedwarn ("ANSI C++ forbids `typeof'"); } pedwarn ("ANSI C++ forbids `typeof'"); }
| TYPEOF '(' type_id ')' | TYPEOF '(' type_id ')'
{ $$ = groktypename ($3); { $$ = groktypename ($3);
if (flag_ansi) if (pedantic)
pedwarn ("ANSI C++ forbids `typeof'"); } pedwarn ("ANSI C++ forbids `typeof'"); }
| SIGOF '(' expr ')' | SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3); { tree type = TREE_TYPE ($3);
...@@ -2763,7 +2764,7 @@ new_type_id: ...@@ -2763,7 +2764,7 @@ new_type_id:
non-constant dimension. */ non-constant dimension. */
| '(' type_id ')' '[' expr ']' | '(' type_id ')' '[' expr ']'
{ {
if (flag_ansi) if (pedantic)
pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new"); pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
$$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5); $$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5);
$$ = build_decl_list (TREE_PURPOSE ($2), $$); $$ = build_decl_list (TREE_PURPOSE ($2), $$);
...@@ -2905,6 +2906,9 @@ complex_direct_notype_declarator: ...@@ -2905,6 +2906,9 @@ complex_direct_notype_declarator:
{ $$ = build_parse_node (ARRAY_REF, $$, $3); } { $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_notype_declarator '[' ']' | direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| notype_qualified_id
{ push_nested_class (TREE_TYPE (OP0 ($$)), 3);
TREE_COMPLEXITY ($$) = current_class_depth; }
; ;
qualified_id: qualified_id:
...@@ -3107,7 +3111,7 @@ errstmt: error ';' ...@@ -3107,7 +3111,7 @@ errstmt: error ';'
maybe_label_decls: maybe_label_decls:
/* empty */ /* empty */
| label_decls | label_decls
{ if (flag_ansi) { if (pedantic)
pedwarn ("ANSI C++ forbids label declarations"); } pedwarn ("ANSI C++ forbids label declarations"); }
; ;
...@@ -3323,7 +3327,7 @@ simple_stmt: ...@@ -3323,7 +3327,7 @@ simple_stmt:
register tree label register tree label
= build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
if (flag_ansi) if (pedantic)
pedwarn ("ANSI C++ forbids range expressions in switch statement"); pedwarn ("ANSI C++ forbids range expressions in switch statement");
if (value1 != error_mark_node if (value1 != error_mark_node
&& value2 != error_mark_node) && value2 != error_mark_node)
......
...@@ -755,6 +755,8 @@ uses_template_parms (t) ...@@ -755,6 +755,8 @@ uses_template_parms (t)
case REFERENCE_TYPE: case REFERENCE_TYPE:
return uses_template_parms (TREE_TYPE (t)); return uses_template_parms (TREE_TYPE (t));
case RECORD_TYPE: case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (t))
return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t));
case UNION_TYPE: case UNION_TYPE:
if (!TYPE_NAME (t)) if (!TYPE_NAME (t))
return 0; return 0;
...@@ -1153,9 +1155,8 @@ tsubst (t, args, nargs, in_decl) ...@@ -1153,9 +1155,8 @@ tsubst (t, args, nargs, in_decl)
&& type != integer_type_node && type != integer_type_node
&& type != void_type_node && type != void_type_node
&& type != char_type_node) && type != char_type_node)
type = cp_build_type_variant (tsubst (type, args, nargs, in_decl), type = tsubst (type, args, nargs, in_decl);
TYPE_READONLY (type),
TYPE_VOLATILE (type));
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case RECORD_TYPE: case RECORD_TYPE:
...@@ -1679,12 +1680,16 @@ instantiate_template (tmpl, targ_ptr) ...@@ -1679,12 +1680,16 @@ instantiate_template (tmpl, targ_ptr)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283); my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl)); len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
i = len;
while (i--)
targ_ptr[i] = copy_to_permanent (targ_ptr[i]);
for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl); for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
fndecl; fndecl = TREE_CHAIN (fndecl)) fndecl; fndecl = TREE_CHAIN (fndecl))
{ {
tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0); tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);
for (i = len - 1; i >= 0; i--) for (i = len - 1; i >= 0; i--)
if (t1[i] != targ_ptr[i]) if (simple_cst_equal (t1[i], targ_ptr[i]) <= 0)
goto no_match; goto no_match;
/* Here, we have a match. */ /* Here, we have a match. */
...@@ -2036,6 +2041,15 @@ type_unification (tparms, targs, parms, args, nsubsts, subr) ...@@ -2036,6 +2041,15 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
return 1; return 1;
if (arg == unknown_type_node) if (arg == unknown_type_node)
return 1; return 1;
if (! uses_template_parms (parm)
&& TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
{
if (can_convert_arg (parm, TREE_TYPE (arg), arg))
continue;
return 1;
}
#if 0 #if 0
if (TREE_CODE (arg) == VAR_DECL) if (TREE_CODE (arg) == VAR_DECL)
arg = TREE_TYPE (arg); arg = TREE_TYPE (arg);
......
...@@ -1740,6 +1740,9 @@ make_deep_copy (t) ...@@ -1740,6 +1740,9 @@ make_deep_copy (t)
case ARRAY_TYPE: case ARRAY_TYPE:
return build_array_type (make_deep_copy (TREE_TYPE (t)), return build_array_type (make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TYPE_DOMAIN (t))); make_deep_copy (TYPE_DOMAIN (t)));
case INTEGER_TYPE:
return build_index_type (make_deep_copy (TYPE_MAX_VALUE (t)));
case OFFSET_TYPE: case OFFSET_TYPE:
return build_offset_type (make_deep_copy (TYPE_OFFSET_BASETYPE (t)), return build_offset_type (make_deep_copy (TYPE_OFFSET_BASETYPE (t)),
make_deep_copy (TREE_TYPE (t))); make_deep_copy (TREE_TYPE (t)));
...@@ -1749,6 +1752,7 @@ make_deep_copy (t) ...@@ -1749,6 +1752,7 @@ make_deep_copy (t)
build_function_type build_function_type
(make_deep_copy (TREE_TYPE (t)), (make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TREE_CHAIN (TYPE_ARG_TYPES (t))))); make_deep_copy (TREE_CHAIN (TYPE_ARG_TYPES (t)))));
case RECORD_TYPE: case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t)) if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type return build_ptrmemfunc_type
......
...@@ -719,7 +719,28 @@ comptypes (type1, type2, strict) ...@@ -719,7 +719,28 @@ comptypes (type1, type2, strict)
return 1; return 1;
case UNINSTANTIATED_P_TYPE: case UNINSTANTIATED_P_TYPE:
return UPT_TEMPLATE (t1) == UPT_TEMPLATE (t2); if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2))
return 0;
{
int i = TREE_VEC_LENGTH (UPT_PARMS (t1));
tree *p1 = &TREE_VEC_ELT (UPT_PARMS (t1), 0);
tree *p2 = &TREE_VEC_ELT (UPT_PARMS (t2), 0);
while (i--)
{
if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
{
if (! comptypes (p1[i], p2[i], 1))
return 0;
}
else
{
if (simple_cst_equal (p1[i], p2[i]) <= 0)
return 0;
}
}
}
return 1;
} }
return attrval == 2 && val == 1 ? 2 : val; return attrval == 2 && val == 1 ? 2 : val;
} }
...@@ -1834,26 +1855,6 @@ build_array_ref (array, idx) ...@@ -1834,26 +1855,6 @@ build_array_ref (array, idx)
return error_mark_node; return error_mark_node;
itype = TREE_TYPE (idx); itype = TREE_TYPE (idx);
/* We must check here for the reference, so we can do the possible
conversions immediately afterwards. */
if (TREE_CODE (itype) == REFERENCE_TYPE)
{
idx = convert_from_reference (idx);
itype = TREE_TYPE (idx);
}
if (IS_AGGR_TYPE (itype))
{
if (TYPE_HAS_INT_CONVERSION (itype))
idx = build_type_conversion (CONVERT_EXPR,
integer_type_node, idx, 1);
else
{
error_with_aggr_type (itype,
"type `%s' requires integer conversion for array indexing");
return error_mark_node;
}
}
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
&& TREE_CODE (array) != INDIRECT_REF) && TREE_CODE (array) != INDIRECT_REF)
...@@ -1902,19 +1903,19 @@ build_array_ref (array, idx) ...@@ -1902,19 +1903,19 @@ build_array_ref (array, idx)
return error_mark_node; return error_mark_node;
} }
/* Note in C++ we don't bother warning about subscripting a
`register' array, since it's valid in C++ to take the address
of something with that storage specification. */
if (pedantic && !lvalue_p (array)) if (pedantic && !lvalue_p (array))
pedwarn ("ANSI C++ forbids subscripting non-lvalue array"); pedwarn ("ANSI C++ forbids subscripting non-lvalue array");
if (pedantic) /* Note in C++ it is valid to subscript a `register' array, since
it is valid to take the address of something with that
storage specification. */
if (extra_warnings)
{ {
tree foo = array; tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF) while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0); foo = TREE_OPERAND (foo, 0);
if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
pedwarn ("ANSI C++ forbids subscripting non-lvalue array"); warning ("subscripting array declared `register'");
} }
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
...@@ -2122,7 +2123,7 @@ build_x_function_call (function, params, decl) ...@@ -2122,7 +2123,7 @@ build_x_function_call (function, params, decl)
decl = C_C_D; decl = C_C_D;
decl_addr = build_unary_op (ADDR_EXPR, decl, 0); decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
function = get_member_function_from_ptrfunc (&decl_addr, decl, function = get_member_function_from_ptrfunc (&decl_addr,
TREE_OPERAND (function, 1)); TREE_OPERAND (function, 1));
params = tree_cons (NULL_TREE, decl_addr, params); params = tree_cons (NULL_TREE, decl_addr, params);
return build_function_call (function, params); return build_function_call (function, params);
...@@ -2184,9 +2185,8 @@ build_x_function_call (function, params, decl) ...@@ -2184,9 +2185,8 @@ build_x_function_call (function, params, decl)
instance to use, if the member points to a virtual member. */ instance to use, if the member points to a virtual member. */
tree tree
get_member_function_from_ptrfunc (instance_ptrptr, instance, function) get_member_function_from_ptrfunc (instance_ptrptr, function)
tree *instance_ptrptr; tree *instance_ptrptr;
tree instance;
tree function; tree function;
{ {
if (TREE_CODE (function) == OFFSET_REF) if (TREE_CODE (function) == OFFSET_REF)
...@@ -2200,7 +2200,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function) ...@@ -2200,7 +2200,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
tree index = save_expr (build_component_ref (function, tree index = save_expr (build_component_ref (function,
index_identifier, index_identifier,
0, 0)); 0, 0));
tree e1 = build (GT_EXPR, delta_type_node, index, tree e1 = build (GT_EXPR, boolean_type_node, index,
convert (delta_type_node, integer_zero_node)); convert (delta_type_node, integer_zero_node));
tree delta = convert (ptrdiff_type_node, tree delta = convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier, 0, 0)); build_component_ref (function, delta_identifier, 0, 0));
...@@ -2209,9 +2209,16 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function) ...@@ -2209,9 +2209,16 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
tree e3; tree e3;
tree aref, vtbl; tree aref, vtbl;
tree instance;
tree instance_ptr = *instance_ptrptr;
if (TREE_SIDE_EFFECTS (instance_ptr))
instance_ptr = save_expr (instance_ptr);
/* convert down to the right base, before using the instance. */ /* convert down to the right base, before using the instance. */
instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)), instance
build_unary_op (ADDR_EXPR, instance, 0)); = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
instance_ptr);
if (instance == error_mark_node) if (instance == error_mark_node)
return instance; return instance;
...@@ -2238,9 +2245,8 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function) ...@@ -2238,9 +2245,8 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
delta, 1); delta, 1);
} }
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (*instance_ptrptr), *instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
*instance_ptrptr, instance_ptr, delta);
delta);
if (flag_vtable_thunks) if (flag_vtable_thunks)
e2 = aref; e2 = aref;
else else
...@@ -2249,6 +2255,12 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function) ...@@ -2249,6 +2255,12 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
e3 = PFN_FROM_PTRMEMFUNC (function); e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (e3); TREE_TYPE (e2) = TREE_TYPE (e3);
function = build_conditional_expr (e1, e2, e3); function = build_conditional_expr (e1, e2, e3);
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
if (TREE_CODE (instance_ptr) == SAVE_EXPR)
function = build (COMPOUND_EXPR, TREE_TYPE (function),
instance_ptr, function);
} }
return function; return function;
} }
...@@ -2325,7 +2337,7 @@ build_function_call_real (function, params, require_complete, flags) ...@@ -2325,7 +2337,7 @@ build_function_call_real (function, params, require_complete, flags)
{ {
tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0); tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype); fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype);
function = get_member_function_from_ptrfunc (&instance_ptr, C_C_D, function); function = get_member_function_from_ptrfunc (&instance_ptr, function);
} }
is_method = (TREE_CODE (fntype) == POINTER_TYPE is_method = (TREE_CODE (fntype) == POINTER_TYPE
...@@ -2715,7 +2727,6 @@ build_binary_op (code, arg1, arg2, convert_p) ...@@ -2715,7 +2727,6 @@ build_binary_op (code, arg1, arg2, convert_p)
tree arg1, arg2; tree arg1, arg2;
int convert_p; int convert_p;
{ {
tree type1, type2;
tree args[2]; tree args[2];
args[0] = arg1; args[0] = arg1;
...@@ -2724,64 +2735,39 @@ build_binary_op (code, arg1, arg2, convert_p) ...@@ -2724,64 +2735,39 @@ build_binary_op (code, arg1, arg2, convert_p)
if (convert_p) if (convert_p)
{ {
tree args_save [2]; tree args_save [2];
tree type0, type1;
args[0] = args_save [0] = default_conversion (args[0]); args[0] = args_save [0] = default_conversion (args[0]);
args[1] = args_save [1] = default_conversion (args[1]); args[1] = args_save [1] = default_conversion (args[1]);
if (args[0] == error_mark_node || args[1] == error_mark_node)
return error_mark_node;
type0 = TREE_TYPE (args[0]);
type1 = TREE_TYPE (args[1]);
if (type_unknown_p (args[0])) if (type_unknown_p (args[0]))
{ {
args[0] = instantiate_type (TREE_TYPE (args[1]), args[0], 1); args[0] = instantiate_type (type1, args[0], 1);
args[0] = default_conversion (args[0]); args[0] = default_conversion (args[0]);
} }
else if (type_unknown_p (args[1])) else if (type_unknown_p (args[1]))
{ {
args[1] = require_instantiated_type (TREE_TYPE (args[0]), args[1] = require_instantiated_type (type0, args[1],
args[1],
error_mark_node); error_mark_node);
args[1] = default_conversion (args[1]); args[1] = default_conversion (args[1]);
} }
type1 = TREE_TYPE (args[0]); if (IS_AGGR_TYPE (type0) || IS_AGGR_TYPE (type1))
type2 = TREE_TYPE (args[1]);
if (IS_AGGR_TYPE_2 (type1, type2))
{ {
/* Try to convert this to something reasonable. */ /* Try to convert this to something reasonable. */
if (! build_default_binary_type_conversion(code, &args[0], &args[1])) if (! build_default_binary_type_conversion(code, &args[0], &args[1]))
return error_mark_node;
}
else if (IS_AGGR_TYPE (type1) || IS_AGGR_TYPE (type2))
{
int convert_index = IS_AGGR_TYPE (type2);
/* Avoid being tripped up by things like (ARG1 != 0). */
tree types[2], try;
types[0] = type1; types[1] = type2;
if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
try = build_type_conversion (code, boolean_type_node,
args[convert_index], 1);
else
{
try = build_type_conversion (code, types[convert_index ^ 1],
args[convert_index], 1);
if (try == 0
&& args[1] == integer_zero_node
&& (code == NE_EXPR || code == EQ_EXPR))
try = build_type_conversion (code, ptr_type_node,
args[convert_index], 1);
}
if (try == 0)
{ {
cp_error ("no match for `%O(%#T, %#T)'", code, cp_error ("no match for `%O(%#T, %#T)'", code,
TREE_TYPE (arg1), TREE_TYPE (arg2)); TREE_TYPE (arg1), TREE_TYPE (arg2));
return error_mark_node; return error_mark_node;
} }
if (try == error_mark_node)
error ("ambiguous pointer conversion");
args[convert_index] = try;
} }
if (args[0] == args_save[0]) if (args[0] == args_save[0])
args[0] = arg1; args[0] = arg1;
if (args[1] == args_save[1]) if (args[1] == args_save[1])
...@@ -3094,7 +3080,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3094,7 +3080,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
{ {
tree base = common_base_type (tt0, tt1); tree base = common_base_type (tt0, tt1);
if (base == NULL_TREE) if (base == NULL_TREE)
cp_warning ("comparison of distinct object pointer types `%T' and `%T'", type0, type1); cp_pedwarn ("comparison of distinct object pointer types `%T' and `%T'", type0, type1);
else if (base == error_mark_node) else if (base == error_mark_node)
{ {
cp_error ("comparison of pointer types `%T' and `%T' requires conversion to ambiguous supertype", type0, type1); cp_error ("comparison of pointer types `%T' and `%T' requires conversion to ambiguous supertype", type0, type1);
...@@ -3119,6 +3105,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3119,6 +3105,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE
&& tree_int_cst_lt (TYPE_SIZE (type0), TYPE_SIZE (type1))) && tree_int_cst_lt (TYPE_SIZE (type0), TYPE_SIZE (type1)))
pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer"); pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer");
else if (TREE_CODE (tt1) == OFFSET_TYPE)
pedwarn ("ANSI C++ forbids conversion of a pointer to member to `void *'");
} }
else if (tt1 == void_type_node) else if (tt1 == void_type_node)
{ {
...@@ -3291,18 +3279,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3291,18 +3279,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
} }
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1)) && integer_zerop (op1))
{ op1 = null_pointer_node;
op1 = null_pointer_node;
if (pedantic)
pedwarn ("ordered comparison of pointer with integer zero");
}
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0)) && integer_zerop (op0))
{ op0 = null_pointer_node;
op0 = null_pointer_node;
if (pedantic)
pedwarn ("ANSI C++ forbids ordered comparison of pointer with integer zero");
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{ {
if (pedantic) if (pedantic)
...@@ -3482,14 +3462,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3482,14 +3462,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Do the checking based on the original operand trees, so that /* Do the checking based on the original operand trees, so that
casts will be considered, but default promotions won't be. */ casts will be considered, but default promotions won't be. */
if (TREE_UNSIGNED (comp_type) if (TREE_UNSIGNED (comp_type)
&& ((op0_signed && ((op0_signed && (TREE_CODE (orig_op0) != INTEGER_CST
&& (TREE_CODE (op0) != INTEGER_CST || tree_int_cst_sgn (orig_op0) == -1))
|| (TREE_CODE (op0) == INTEGER_CST || (op1_signed && (TREE_CODE (orig_op1) != INTEGER_CST
&& INT_CST_LT (op0, integer_zero_node)))) || tree_int_cst_sgn (orig_op1) == -1))))
|| (op1_signed
&& (TREE_CODE (op1) != INTEGER_CST
|| (TREE_CODE (op1) == INTEGER_CST
&& INT_CST_LT (op1, integer_zero_node))))))
warning ("comparison between signed and unsigned"); warning ("comparison between signed and unsigned");
/* Warn if two unsigned values are being compared in a size /* Warn if two unsigned values are being compared in a size
...@@ -3830,121 +3806,46 @@ build_unary_op (code, xarg, noconvert) ...@@ -3830,121 +3806,46 @@ build_unary_op (code, xarg, noconvert)
/* No default_conversion here. It causes trouble for ADDR_EXPR. */ /* No default_conversion here. It causes trouble for ADDR_EXPR. */
register tree arg = xarg; register tree arg = xarg;
register tree argtype = 0; register tree argtype = 0;
register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
char *errstring = NULL; char *errstring = NULL;
tree val; tree val;
int isaggrtype;
if (typecode == ERROR_MARK) if (arg == error_mark_node)
return error_mark_node; return error_mark_node;
if (typecode == REFERENCE_TYPE && code != ADDR_EXPR && ! noconvert)
{
arg = convert_from_reference (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
}
if (typecode == ENUMERAL_TYPE)
typecode = INTEGER_TYPE;
if (typecode == BOOLEAN_TYPE && ! noconvert)
typecode = INTEGER_TYPE;
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
switch (code) switch (code)
{ {
case CONVERT_EXPR: case CONVERT_EXPR:
/* This is used for unary plus, because a CONVERT_EXPR /* This is used for unary plus, because a CONVERT_EXPR
is enough to prevent anybody from looking inside for is enough to prevent anybody from looking inside for
associativity, but won't generate any code. */ associativity, but won't generate any code. */
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE)) if (!(arg = build_expr_type_conversion
errstring = "wrong type argument to unary plus"; (WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, 1)))
else if (!noconvert) errstring = "wrong type argument to unary plus";
arg = default_conversion (arg); else
arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
break;
case NEGATE_EXPR:
if (typecode == OFFSET_TYPE)
{
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{ {
if (!noconvert) if (!noconvert)
arg = default_conversion (arg); arg = default_conversion (arg);
else arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
{
cp_error ("type conversion for type `%T' not allowed",
TREE_TYPE (arg));
return error_mark_node;
}
typecode = TREE_CODE (TREE_TYPE (arg));
noconvert = 1;
} }
break;
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE)) case NEGATE_EXPR:
errstring = "wrong type argument to unary minus"; if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
errstring = "wrong type argument to unary minus";
else if (!noconvert) else if (!noconvert)
arg = default_conversion (arg); arg = default_conversion (arg);
break; break;
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
if (typecode == OFFSET_TYPE) if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, arg, 1)))
{ errstring = "wrong type argument to bit-complement";
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{
if (!noconvert)
arg = default_conversion (arg);
else
{
cp_error ("type conversion for type `%T' not allowed",
TREE_TYPE (arg));
return error_mark_node;
}
typecode = TREE_CODE (TREE_TYPE (arg));
noconvert = 1;
}
if (typecode != INTEGER_TYPE)
errstring = "wrong type argument to bit-complement";
else if (!noconvert) else if (!noconvert)
arg = default_conversion (arg); arg = default_conversion (arg);
break; break;
case ABS_EXPR: case ABS_EXPR:
if (typecode == OFFSET_TYPE) if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
{ errstring = "wrong type argument to abs";
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{
if (!noconvert)
arg = default_conversion (arg);
else
{
cp_error ("type conversion for type `%T' not allowed",
TREE_TYPE (arg));
return error_mark_node;
}
typecode = TREE_CODE (TREE_TYPE (arg));
noconvert = 1;
}
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
errstring = "wrong type argument to abs";
else if (!noconvert) else if (!noconvert)
arg = default_conversion (arg); arg = default_conversion (arg);
break; break;
...@@ -3973,21 +3874,8 @@ build_unary_op (code, xarg, noconvert) ...@@ -3973,21 +3874,8 @@ build_unary_op (code, xarg, noconvert)
/* Report invalid types. */ /* Report invalid types. */
if (typecode == OFFSET_TYPE) if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER,
{ arg, 1)))
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{
arg = default_conversion (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
}
if (typecode != POINTER_TYPE
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
{ {
if (code == PREINCREMENT_EXPR) if (code == PREINCREMENT_EXPR)
errstring ="no pre-increment operator for type"; errstring ="no pre-increment operator for type";
...@@ -4024,7 +3912,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -4024,7 +3912,7 @@ build_unary_op (code, xarg, noconvert)
/* Compute the increment. */ /* Compute the increment. */
if (typecode == POINTER_TYPE) if (TREE_CODE (argtype) == POINTER_TYPE)
{ {
enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype)); enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
if (TYPE_SIZE (TREE_TYPE (argtype)) == 0) if (TYPE_SIZE (TREE_TYPE (argtype)) == 0)
...@@ -4081,7 +3969,37 @@ build_unary_op (code, xarg, noconvert) ...@@ -4081,7 +3969,37 @@ build_unary_op (code, xarg, noconvert)
? "increment" : "decrement"))) ? "increment" : "decrement")))
return error_mark_node; return error_mark_node;
val = build (code, TREE_TYPE (arg), arg, inc); /* Forbid using -- on `bool'. */
if (TREE_TYPE (arg) == boolean_type_node)
{
if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
{
cp_error ("invalid use of `--' on bool variable `%D'", arg);
return error_mark_node;
}
#if 0
/* This will only work if someone can convince Kenner to accept
my patch to expand_increment. (jason) */
val = build (code, TREE_TYPE (arg), arg, inc);
#else
if (code == POSTINCREMENT_EXPR)
{
arg = stabilize_reference (arg);
val = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
boolean_true_node);
TREE_SIDE_EFFECTS (val) = 1;
arg = save_expr (arg);
val = build (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
val = build (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
}
else
val = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
boolean_true_node);
#endif
}
else
val = build (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1; TREE_SIDE_EFFECTS (val) = 1;
return convert (result_type, val); return convert (result_type, val);
} }
...@@ -4090,7 +4008,8 @@ build_unary_op (code, xarg, noconvert) ...@@ -4090,7 +4008,8 @@ build_unary_op (code, xarg, noconvert)
/* Note that this operation never does default_conversion /* Note that this operation never does default_conversion
regardless of NOCONVERT. */ regardless of NOCONVERT. */
if (typecode == REFERENCE_TYPE) argtype = TREE_TYPE (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{ {
arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_REFERENCE_EXPR (arg) = 1; TREE_REFERENCE_EXPR (arg) = 1;
...@@ -4194,13 +4113,12 @@ build_unary_op (code, xarg, noconvert) ...@@ -4194,13 +4113,12 @@ build_unary_op (code, xarg, noconvert)
; ;
/* Anything not already handled and not a true memory reference /* Anything not already handled and not a true memory reference
is an error. */ is an error. */
else if (typecode != FUNCTION_TYPE else if (TREE_CODE (argtype) != FUNCTION_TYPE
&& typecode != METHOD_TYPE && TREE_CODE (argtype) != METHOD_TYPE
&& !lvalue_or_else (arg, "unary `&'")) && !lvalue_or_else (arg, "unary `&'"))
return error_mark_node; return error_mark_node;
/* Ordinary case; arg is a COMPONENT_REF or a decl. */ /* Ordinary case; arg is a COMPONENT_REF or a decl. */
argtype = TREE_TYPE (arg);
/* If the lvalue is const or volatile, /* If the lvalue is const or volatile,
merge that into the type that the address will point to. */ merge that into the type that the address will point to. */
if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd' if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
...@@ -4900,10 +4818,25 @@ build_compound_expr (list) ...@@ -4900,10 +4818,25 @@ build_compound_expr (list)
rest = build_compound_expr (TREE_CHAIN (list)); rest = build_compound_expr (TREE_CHAIN (list));
/* When pedantic, a compound expression can be neither an lvalue if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
nor an integer constant expression. */ {
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic) /* the left-hand operand of a comma expression is like an expression
return rest; statement: we should warn if it doesn't have any side-effects,
unless it was explicitly cast to (void). */
if ((extra_warnings || warn_unused)
&& !(TREE_CODE (TREE_VALUE(list)) == CONVERT_EXPR
&& TREE_TYPE (TREE_VALUE(list)) == void_type_node))
warning("left-hand operand of comma expression has no effect");
/* When pedantic, a compound expression can be neither an lvalue
nor an integer constant expression. */
if (! pedantic)
return rest;
}
#if 0 /* this requires a gcc backend patch to export warn_if_unused_value */
else if (warn_unused)
warn_if_unused_value (TREE_VALUE(list));
#endif
return build (COMPOUND_EXPR, TREE_TYPE (rest), return build (COMPOUND_EXPR, TREE_TYPE (rest),
break_out_cleanups (TREE_VALUE (list)), rest); break_out_cleanups (TREE_VALUE (list)), rest);
...@@ -5629,8 +5562,6 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5629,8 +5562,6 @@ build_modify_expr (lhs, modifycode, rhs)
cp_error ("`%T' does not define operator=", lhstype); cp_error ("`%T' does not define operator=", lhstype);
else if (! TYPE_HAS_REAL_ASSIGNMENT (lhstype) else if (! TYPE_HAS_REAL_ASSIGNMENT (lhstype)
&& ! TYPE_HAS_COMPLEX_ASSIGN_REF (lhstype) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (lhstype)
/* FIXME find some way to deal with TARGET_EXPRs here. */
&& TREE_CODE (newrhs) != TARGET_EXPR
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))) && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */; /* Do the default thing */;
else else
...@@ -5697,7 +5628,11 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5697,7 +5628,11 @@ build_modify_expr (lhs, modifycode, rhs)
newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1); newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
} }
else else
return error_mark_node; {
cp_error ("no match for `%O(%#T, %#T)'", modifycode,
TREE_TYPE (lhs), TREE_TYPE (rhs));
return error_mark_node;
}
} }
else else
{ {
...@@ -6008,18 +5943,32 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -6008,18 +5943,32 @@ build_modify_expr (lhs, modifycode, rhs)
} }
else else
newrhs = convert_for_assignment (lhstype, newrhs, "assignment", newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
NULL_TREE, 0); NULL_TREE, 0);
if (flag_elide_constructors == 0 if (TREE_CODE (newrhs) == CALL_EXPR
&& TREE_CODE (newrhs) == CALL_EXPR && TYPE_NEEDS_CONSTRUCTING (lhstype))
&& TREE_ADDRESSABLE (lhstype)) newrhs = build_cplus_new (lhstype, newrhs, 0);
if (TREE_CODE (newrhs) == TARGET_EXPR)
{ {
/* Can't initialized directly from a CALL_EXPR, since /* Can't initialize directly from a TARGET_EXPR, since that would
we don't know about what doesn't alias what. */ cause the lhs to be constructed twice. So we force the
TARGET_EXPR to be expanded. expand_expr should really do this
by itself. */
tree xval = make_node (RTL_EXPR);
rtx rtxval;
tree temp = get_temp_name (lhstype, 0); do_pending_stack_adjust ();
newrhs = build (COMPOUND_EXPR, lhstype, start_sequence_for_rtl_expr (xval);
build_modify_expr (temp, INIT_EXPR, newrhs), emit_note (0, -1);
temp); rtxval = expand_expr (newrhs, NULL, VOIDmode, 0);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (xval) = 1;
RTL_EXPR_SEQUENCE (xval) = get_insns ();
end_sequence ();
RTL_EXPR_RTL (xval) = rtxval;
TREE_TYPE (xval) = lhstype;
newrhs = xval;
} }
} }
...@@ -6172,7 +6121,7 @@ get_delta_difference (from, to, force) ...@@ -6172,7 +6121,7 @@ get_delta_difference (from, to, force)
} }
if (TREE_VIA_VIRTUAL (binfo)) if (TREE_VIA_VIRTUAL (binfo))
{ {
warning ("pointer to member conversion to virtual base class will only work if your very careful"); warning ("pointer to member conversion to virtual base class will only work if you are very careful");
} }
return build_binary_op (MINUS_EXPR, return build_binary_op (MINUS_EXPR,
integer_zero_node, integer_zero_node,
...@@ -6180,7 +6129,7 @@ get_delta_difference (from, to, force) ...@@ -6180,7 +6129,7 @@ get_delta_difference (from, to, force)
} }
if (TREE_VIA_VIRTUAL (binfo)) if (TREE_VIA_VIRTUAL (binfo))
{ {
warning ("pointer to member conversion from virtual base class will only work if your very careful"); warning ("pointer to member conversion from virtual base class will only work if you are very careful");
} }
return BINFO_OFFSET (binfo); return BINFO_OFFSET (binfo);
} }
...@@ -6241,7 +6190,7 @@ build_ptrmemfunc (type, pfn, force) ...@@ -6241,7 +6190,7 @@ build_ptrmemfunc (type, pfn, force)
force); force);
delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1); delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1); delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1);
e1 = fold (build (GT_EXPR, integer_type_node, index, integer_zero_node)); e1 = fold (build (GT_EXPR, boolean_type_node, index, integer_zero_node));
u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE)); u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta, u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
......
...@@ -329,7 +329,7 @@ ack (s, v, v2) ...@@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */ same situation (call exit). */
/* First used: 0 (reserved), Last used: 364. Free: */ /* First used: 0 (reserved), Last used: 366. Free: */
static int abortcount = 0; static int abortcount = 0;
...@@ -855,6 +855,14 @@ digest_init (type, init, tail) ...@@ -855,6 +855,14 @@ digest_init (type, init, tail)
} }
init = element; init = element;
} }
while (TREE_CODE (init) == CONSTRUCTOR)
{
cp_pedwarn ("braces around scalar initializer for `%T'", type);
init = CONSTRUCTOR_ELTS (init);
if (TREE_CHAIN (init))
cp_pedwarn ("ignoring extra initializers for `%T'", type);
init = TREE_VALUE (init);
}
return convert_for_initialization (0, type, init, LOOKUP_NORMAL, return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0); "initialization", NULL_TREE, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment