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)
* 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)
(grokdeclarator): Added code to support machine attributes.
* 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)
* 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)
* 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.
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.
* cvt.c (build_up_reference): Bash the types bashed by
build_vbase_path to be reference types instead of pointer types.
(convert_to_reference): Ditto.
* method.c (synthesize_method): Set interface_{unknown,only}
according to the settings for our class, not the file where it comes
from.
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.
* typeck2.c (store_init_value): Likewise.
* except.c: Handle systems that define __i386__ but not __i386.
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>
* typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR
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>
* 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)
* Language directory reorganization.
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)
* 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
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
CONFLICTS = expect 5 shift/reduce confict and 38 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(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); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
#$(PARSE_C) $(PARSE_H) : stamp-parse ; @true
#stamp-parse: $(srcdir)/parse.y
# @echo expect 1 shift/reduce confict and 39 reduce/reduce conflicts.
# @echo $(CONFLICTS)
# $(BISON) $(BISONFLAGS) -d $(srcdir)/parse.y
# grep '^#define[ ]*YYEMPTY' y.tab.c >>y.tab.h
# $(srcdir)/../move-if-change y.tab.c $(PARSE_C)
......
......@@ -593,6 +593,15 @@ can_convert (to, from)
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
static char *
print_harshness (h)
......@@ -2371,9 +2380,12 @@ build_method_call (instance, name, parms, basetype_path, flags)
assemble_external (function);
#if 0
/* Is it a synthesized method that needs to be synthesized? */
if (DECL_ARTIFICIAL (function) && ! flag_no_inline
&& 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);
#endif
......
......@@ -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);
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),
null_expr, nonnull_expr);
}
......@@ -323,7 +323,7 @@ build_vbase_path (code, type, expr, path, alias_this)
expr = save_expr (expr);
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,
build (code, type, expr, offset));
}
......@@ -490,11 +490,12 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
return aref;
else
{
*ptr_to_instptr
= build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
*ptr_to_instptr,
convert (ptrdiff_type_node,
build_component_ref (aref, delta_identifier, 0, 0)));
if (ptr_to_instptr)
*ptr_to_instptr
= build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
*ptr_to_instptr,
convert (ptrdiff_type_node,
build_component_ref (aref, delta_identifier, 0, 0)));
return build_component_ref (aref, pfn_identifier, 0, 0);
}
}
......@@ -2020,6 +2021,7 @@ duplicate_tag_error (t)
tree t;
{
cp_error ("redefinition of `%#T'", t);
cp_error_at ("previous definition here", t);
/* Pretend we haven't defined this type. */
......
......@@ -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 \
| 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):
purpose = friend name (IDENTIFIER_NODE);
value = TREE_LIST of FUNCTION_DECLS;
......@@ -1913,8 +1924,8 @@ extern tree convert PROTO((tree, tree));
extern tree cp_convert PROTO((tree, tree, int, int));
extern tree convert_force PROTO((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_unary_type_conversion PROTO((enum tree_code, tree *));
extern tree type_promotes_to PROTO((tree));
/* decl.c */
......@@ -2042,9 +2053,10 @@ extern tree get_namespace_id PROTO((void));
/* in edsel.c */
/* in except.c */
extern tree protect_list;
extern void start_protect PROTO((void));
extern void end_protect PROTO((tree));
extern void end_protect_partials ();
extern void expand_exception_blocks PROTO((void));
extern void expand_start_try_stmts PROTO((void));
extern void expand_end_try_stmts PROTO((void));
......@@ -2053,7 +2065,8 @@ extern void expand_end_all_catch PROTO((void));
extern void start_catch_block PROTO((tree, tree));
extern void end_catch_block PROTO((void));
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 void init_exception_processing PROTO((void));
......@@ -2093,7 +2106,7 @@ extern tree get_type_value PROTO((tree));
extern tree build_member_call PROTO((tree, tree, tree));
extern tree build_offset_ref PROTO((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 decl_constant_value PROTO((tree));
extern int is_friend_type PROTO((tree, tree));
......
......@@ -903,6 +903,7 @@ convert_to_aggr (type, expr, msgp, protect)
parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
#if 0
method_name = build_decl_overload (name, parmtypes, 1);
/* constructors are up front. */
......@@ -936,6 +937,7 @@ convert_to_aggr (type, expr, msgp, protect)
}
fndecl = DECL_CHAIN (fndecl);
}
#endif
/* No exact conversion was found. See if an approximate
one will do. */
......@@ -1548,7 +1550,7 @@ build_type_conversion (code, xtype, expr, for_sure)
{
cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
xtype);
cp_error (" candidate conversion functions include `%T' and `%T'",
cp_error (" candidate conversions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv));
return NULL_TREE;
}
......@@ -1564,154 +1566,228 @@ build_type_conversion (code, xtype, expr, for_sure)
return NULL_TREE;
}
/* Must convert two aggregate types to non-aggregate type.
Attempts to find a non-ambiguous, "best" type conversion.
Return 1 on success, 0 on failure.
/* Convert the given EXPR to one of a group of types suitable for use in an
expression. DESIRES is a combination of various WANT_* flags (q.v.)
which indicates which types are suitable. If COMPLAIN is 1, complain
about ambiguity; otherwise, the caller will deal with it. */
@@ What are the real semantics of this supposed to be??? */
int
build_default_binary_type_conversion (code, arg1, arg2)
enum tree_code code;
tree *arg1, *arg2;
tree
build_expr_type_conversion (desires, expr, complain)
int desires;
tree expr;
int complain;
{
tree type1 = TREE_TYPE (*arg1);
tree type2 = TREE_TYPE (*arg2);
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);
tree basetype = TREE_TYPE (expr);
tree conv;
tree winner = NULL_TREE;
if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL)
if (TREE_CODE (basetype) == OFFSET_TYPE)
{
tree decl = typedecl_for_tag (type1);
if (decl)
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;
expr = resolve_offset_ref (expr);
basetype = TREE_TYPE (expr);
}
if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1))
{
if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
cp_error ("no conversion from `%T' and `%T' to types with default `%O' ",
type1, type2, code);
else
cp_error ("no conversion from `%T' to type with default `%O'",
type1, code);
return 0;
}
else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
{
cp_error ("no conversion from `%T' to type with default `%O'",
type2, code);
return 0;
}
if (! IS_AGGR_TYPE (basetype))
switch (TREE_CODE (basetype))
{
case INTEGER_TYPE:
if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
&& integer_zerop (expr))
return expr;
/* else fall through... */
case BOOLEAN_TYPE:
return (desires & WANT_INT) ? expr : NULL_TREE;
case ENUMERAL_TYPE:
return (desires & WANT_ENUM) ? expr : NULL_TREE;
case REAL_TYPE:
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
|| code == TRUTH_ORIF_EXPR)
{
*arg1 = convert (boolean_type_node, *arg1);
*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)
if (! TYPE_HAS_CONVERSION (basetype))
return NULL_TREE;
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
cp_error ("default type conversion for type `%T' failed", type2);
return 0;
int win = 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.
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??? */
int
build_default_unary_type_conversion (code, arg)
build_default_binary_type_conversion (code, arg1, arg2)
enum tree_code code;
tree *arg;
tree *arg1, *arg2;
{
tree type = TREE_TYPE (*arg);
if (! TYPE_HAS_CONVERSION (type))
switch (code)
{
cp_error ("type conversion required for type `%T'", type);
return 0;
}
case MULT_EXPR:
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)
*arg = convert (boolean_type_node, *arg);
else if (TYPE_HAS_INT_CONVERSION (type))
{
if (TYPE_HAS_REAL_CONVERSION (type))
cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int",
type);
*arg = build_type_conversion (code, integer_type_node, *arg, 1);
}
else if (TYPE_HAS_REAL_CONVERSION (type))
*arg = build_type_conversion (code, double_type_node, *arg, 1);
else
{
*arg = build_type_conversion (code, ptr_type_node, *arg, 1);
if (*arg == error_mark_node)
error ("ambiguous pointer conversion");
}
if (*arg == NULL_TREE)
{
cp_error ("default type conversion for type `%T' failed", type);
return 0;
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case BIT_AND_EXPR:
case BIT_XOR_EXPR:
case BIT_IOR_EXPR:
*arg1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg1, 0);
*arg2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg2, 0);
break;
case PLUS_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) + (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. */
......
......@@ -1664,13 +1664,10 @@ set_nested_typename (decl, classname, name, type)
type_decl = build_decl (TYPE_DECL, nested, type);
DECL_NESTED_TYPENAME (type_decl) = nested;
SET_DECL_ARTIFICIAL (type_decl);
#ifdef DWARF_DEBUGGING_INFO
/* Mark the TYPE_DECL node created just above as a
gratuitous one so that dwarfout.c will know not to
generate a TAG_typedef DIE for it. */
if (write_symbols == DWARF_DEBUG)
DECL_IGNORED_P (type_decl) = 1;
#endif /* DWARF_DEBUGGING_INFO */
/* Mark the TYPE_DECL node created just above as a gratuitous one so that
dwarfout.c will know not to generate a TAG_typedef DIE for it, and
sdbout.c won't try to output a .def for "::foo". */
DECL_IGNORED_P (type_decl) = 1;
/* Remove this when local classes are fixed. */
SET_IDENTIFIER_TYPE_VALUE (nested, type);
......@@ -2447,21 +2444,16 @@ duplicate_decls (newdecl, olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl))
{
if (TREE_TYPE (newdecl) != error_mark_node)
layout_type (TREE_TYPE (newdecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL
&& TREE_CODE (newdecl) != TYPE_DECL
&& TREE_CODE (newdecl) != CONST_DECL
&& TREE_CODE (newdecl) != TEMPLATE_DECL)
layout_decl (newdecl, 0);
}
else
{
/* Since the type is OLDDECL's, make OLDDECL's size go with. */
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
}
if (oldtype != TREE_TYPE (newdecl)
&& TREE_TYPE (newdecl) != error_mark_node)
layout_type (TREE_TYPE (newdecl));
if (TREE_CODE (newdecl) == VAR_DECL
|| TREE_CODE (newdecl) == PARM_DECL
|| TREE_CODE (newdecl) == RESULT_DECL
|| TREE_CODE (newdecl) == FIELD_DECL
|| TREE_CODE (newdecl) == TYPE_DECL)
layout_decl (newdecl, 0);
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
......@@ -7660,7 +7652,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (TREE_CODE (type) == REAL_TYPE)
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);
else if (RIDBIT_SETP (RID_LONG, specbits)
&& RIDBIT_SETP (RID_SHORT, specbits))
......@@ -7780,6 +7772,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (constp)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
......@@ -7820,7 +7817,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
/* 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");
virtualp = 0;
......@@ -7972,14 +7970,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{
if (decl_context == FIELD)
{
tree tmp = TREE_OPERAND (declarator, 0);
register int op = IDENTIFIER_OPNAME_P (tmp);
tree tmp = NULL_TREE;
register int op = 0;
if (declarator)
{
tmp = TREE_OPERAND (declarator, 0);
op = IDENTIFIER_OPNAME_P (tmp);
}
error ("storage class specified for %s `%s'",
IS_SIGNATURE (current_class_type)
? (op
? "signature member operator"
: "signature member function")
: (op ? "member operator" : "structure field"),
: (op ? "member operator" : "field"),
op ? operator_name_string (tmp) : name);
}
else
......@@ -8092,6 +8096,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{
register tree itype = NULL_TREE;
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);
......@@ -8181,8 +8187,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
cp_error ("size of array `%D' is negative", dname);
size = integer_one_node;
}
itype = build_index_type (size_binop (MINUS_EXPR, size,
integer_one_node));
}
else
{
......@@ -8194,15 +8198,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
else
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
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;
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);
}
......@@ -8262,10 +8271,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
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
closest to the identifier. */
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
&& decl_context == FIELD
......@@ -8289,14 +8302,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
may not be static. */
if (staticp == 2)
error ("destructor cannot be static member function");
if (TYPE_READONLY (type))
{
error ("destructors cannot be declared `const'");
return void_type_node;
}
if (TYPE_VOLATILE (type))
if (quals)
{
error ("destructors cannot be declared `volatile'");
error ("destructors cannot be declared `const' or `volatile'");
return void_type_node;
}
if (decl_context == FIELD)
......@@ -8320,16 +8328,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
pedwarn ("constructors cannot be declared virtual");
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;
}
if (TYPE_VOLATILE (type))
{
error ("constructors cannot be declared `volatile'");
return void_type_node;
}
{
RID_BIT_TYPE tmp_bits;
bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE));
......@@ -8358,20 +8361,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (decl_context == FIELD)
staticp = 0;
}
else if (friendp && virtualp)
else if (friendp)
{
/* Cannot be both friend and virtual. */
error ("virtual functions cannot be friends");
RIDBIT_RESET (RID_FRIEND, specbits);
friendp = 0;
if (initialized)
error ("can't initialize friend function `%s'", name);
if (virtualp)
{
/* Cannot be both friend and virtual. */
error ("virtual functions cannot be friends");
RIDBIT_RESET (RID_FRIEND, specbits);
friendp = 0;
}
}
if (decl_context == NORMAL && friendp)
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. */
if (flag_traditional
......@@ -8836,13 +8841,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp)
{
/* 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;
if (volatilep)
{
cp_error ("`volatile' specified for friend class declaration");
volatilep = 0;
}
if (inlinep)
{
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)
{
......@@ -8878,7 +8898,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
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 0 /* How could this happen? */
......@@ -8921,6 +8943,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_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);
......@@ -9030,7 +9057,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
else if (TYPE_SIZE (type) == NULL_TREE && !staticp
&& (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
instantiation made the field's type be incomplete. */
......@@ -9302,6 +9332,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
staticp = 0;
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))
{
cp_error ("cannot explicitly declare member `%#D' to have extern linkage",
......@@ -9583,7 +9618,8 @@ grokparms (first_parm, funcdef_flag)
any_init++;
if (TREE_CODE (init) == SAVE_EXPR)
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)))
{
......@@ -10656,6 +10692,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
original_result_rtx = NULL_RTX;
current_function_obstack_index = 0;
current_function_obstack_usage = 0;
base_init_insns = NULL_RTX;
protect_list = NULL_TREE;
clear_temp_name ();
......@@ -10751,7 +10789,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{
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;
}
warn_about_return_type = 0;
......@@ -10795,6 +10833,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
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)
warning ("return-type defaults to `int'");
......@@ -10824,14 +10866,19 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
DECL_EXTERNAL (decl1) = current_extern_inline;
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
{
/* This is a definition, not a reference.
So normally clear DECL_EXTERNAL.
However, `extern inline' acts like a declaration except for
defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
So clear DECL_EXTERNAL. */
DECL_EXTERNAL (decl1) = 0;
if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)))
/* We know nothing yet */;
......@@ -11423,6 +11470,7 @@ finish_function (lineno, call_poplevel, nested)
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
end_protect_partials ();
expand_label (ctor_label);
ctor_label = NULL_TREE;
......@@ -11503,6 +11551,8 @@ finish_function (lineno, call_poplevel, nested)
if (mark != get_last_insn ())
reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
end_protect_partials ();
/* This is where the body of the constructor ends. */
expand_label (ctor_label);
ctor_label = NULL_TREE;
......@@ -11643,8 +11693,14 @@ finish_function (lineno, call_poplevel, nested)
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
if (DECL_DEFER_OUTPUT (fndecl))
mark_inline_for_output (fndecl);
if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (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))
note_debug_info_needed (ctype);
......@@ -12121,7 +12177,9 @@ struct cp_function
tree shadowed_labels;
tree ctor_label;
tree dtor_label;
tree protect_list;
rtx result_rtx;
rtx base_init_insns;
struct cp_function *next;
struct binding_level *binding_level;
};
......@@ -12156,6 +12214,8 @@ push_cp_function_context (toplev)
p->just_assigned_this = current_function_just_assigned_this;
p->parms_stored = current_function_parms_stored;
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. */
......@@ -12197,10 +12257,12 @@ pop_cp_function_context (toplev)
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;
protect_list = p->protect_list;
current_function_assigns_this = p->assigns_this;
current_function_just_assigned_this = p->just_assigned_this;
current_function_parms_stored = p->parms_stored;
original_result_rtx = p->result_rtx;
base_init_insns = p->base_init_insns;
free (p);
}
......@@ -1027,6 +1027,7 @@ grok_array_decl (array_expr, index_exp)
tree array_expr, index_exp;
{
tree type = TREE_TYPE (array_expr);
tree p1, p2, i1, i2;
if (type == error_mark_node || index_exp == error_mark_node)
return error_mark_node;
......@@ -1049,28 +1050,38 @@ grok_array_decl (array_expr, index_exp)
array_expr, index_exp, NULL_TREE);
/* 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]'.
We don't emit a warning or error for this, since it's allowed
by ARM $8.2.4. */
if (TREE_CODE (type) == ARRAY_TYPE)
p1 = array_expr;
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
|| TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0);
i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0);
if (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == ARRAY_TYPE)
return build_array_ref (index_exp, array_expr);
if ((p1 && i2) && (i1 && p2))
error ("ambiguous conversion for array subscript");
/* The expression E1[E2] is identical (by definition) to *((E1)+(E2)). */
return build_indirect_ref (build_binary_op (PLUS_EXPR, array_expr,
index_exp, 1),
"array indexing");
if (p1 && i2)
array_expr = p1, index_exp = i2;
else if (i1 && p2)
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
......@@ -2487,8 +2498,8 @@ import_export_vtable (decl, type, final)
}
else
{
/* We can only do this optimization if we have real non-inline
virtual functions in our class, or if we come from a template. */
/* We can only wait to decide if we have real non-inline virtual
functions in our class, or if we come from a template. */
int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
......@@ -2543,7 +2554,8 @@ finish_prevtable_vardecl (prev, vars)
tree ctype = DECL_CONTEXT (vars);
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;
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
......@@ -2562,19 +2574,11 @@ finish_prevtable_vardecl (prev, vars)
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)))
{
extern tree the_null_vtable_entry;
/* Kick out the type descriptor before writing out the vtable. */
if (flag_rtti)
{
build_t_desc (ctype, 1);
}
/* Write it out. */
mark_vtable_entries (vars);
build_t_desc (ctype, 1);
}
}
......@@ -2582,39 +2586,13 @@ static void
finish_vtable_vardecl (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
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
{
extern tree the_null_vtable_entry;
/* Write it out. */
mark_vtable_entries (vars);
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
if (write_symbols == DWARF_DEBUG)
......@@ -2646,8 +2624,18 @@ finish_vtable_vardecl (prev, vars)
rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
}
else if (TREE_USED (vars))
assemble_external (vars);
else if (! TREE_USED (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. */
TREE_CHAIN (prev) = TREE_CHAIN (vars);
}
......@@ -2731,6 +2719,8 @@ import_export_inline (decl)
if (DECL_INTERFACE_KNOWN (decl))
return;
DECL_EXTERNAL (decl) = 0;
if (DECL_TEMPLATE_INSTANTIATION (decl))
{
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
......@@ -2773,7 +2763,6 @@ finish_file ()
tree fnname;
tree vars = static_aggregates;
int needs_cleaning = 0, needs_messing_up = 0;
int have_exception_handlers = build_exception_table ();
if (flag_detailed_statistics)
dump_tree_statistics ();
......@@ -2788,7 +2777,7 @@ finish_file ()
we'll need here. */
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;
if (static_dtors)
needs_cleaning = 1;
......@@ -2900,7 +2889,7 @@ finish_file ()
push_momentary ();
expand_start_bindings (0);
if (have_exception_handlers)
if (might_have_exceptions_p ())
register_exception_table ();
while (vars)
......@@ -2931,6 +2920,7 @@ finish_file ()
/* 9.5p5: The initializer of a static member of a class has
the same acess rights as a member function. */
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
#if 0
if (init)
......@@ -3061,30 +3051,9 @@ finish_file ()
pushdecl (vars);
#endif
walk_vtables ((void (*)())0, finish_vtable_vardecl);
if (flag_handle_signatures)
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
which were not declared virtual and which were not declared `extern
inline'. */
......@@ -3098,10 +3067,23 @@ finish_file ()
tree place = TREE_CHAIN (saved_inlines);
reconsider = 0;
walk_vtables ((void (*)())0, finish_vtable_vardecl);
for (; place; place = TREE_CHAIN (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)
{
TREE_CHAIN (last) = TREE_CHAIN (place);
......@@ -3114,9 +3096,7 @@ finish_file ()
{
TREE_CHAIN (last) = TREE_CHAIN (place);
if (DECL_EXTERNAL (decl))
assemble_external (decl);
else
if (! DECL_EXTERNAL (decl))
{
reconsider = 1;
temporary_allocation ();
......@@ -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)
{
/* Now complain about an virtual function tables promised
......
......@@ -585,7 +585,7 @@ dump_decl (t, v)
break;
case VAR_DECL:
if (VTABLE_NAME_P (DECL_NAME (t)))
if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
{
OB_PUTS ("vtable for ");
dump_type (DECL_CONTEXT (t), v);
......@@ -933,9 +933,16 @@ dump_expr (t, nop)
char *p = enum_name_string (t, type);
OB_PUTCP (p);
}
else if (type == char_type_node
|| type == signed_char_type_node
|| type == unsigned_char_type_node)
else if (type == boolean_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 ('\'');
dump_char (TREE_INT_CST_LOW (t));
......
......@@ -31,6 +31,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "obstack.h"
#include "expr.h"
tree protect_list;
extern void (*interim_eh_hook) PROTO((tree));
/* holds the fndecl for __builtin_return_address () */
......@@ -53,6 +55,11 @@ tree builtin_return_address_fndecl;
#define __mips
#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)
#define TRY_NEW_EH
#endif
......@@ -872,11 +879,13 @@ void
end_protect (finalization)
tree finalization;
{
struct ehEntry *entry = pop_eh_entry (&ehstack);
struct ehEntry *entry;
if (! doing_eh (0))
return;
entry = pop_eh_entry (&ehstack);
emit_label (entry->end_label);
entry->finalization = finalization;
......@@ -1574,11 +1583,29 @@ expand_throw (exp)
/* end of: my-cp-except.c */
#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.
Return the number of handlers. */
int
build_exception_table ()
void
emit_exception_table ()
{
int count = 0;
#ifdef TRY_NEW_EH
......@@ -1587,7 +1614,15 @@ build_exception_table ()
tree eh_node_decl;
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))
{
......@@ -1596,32 +1631,18 @@ build_exception_table ()
if (context && ! TREE_ASM_WRITTEN (context))
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++;
output_exception_table_entry (asm_out_file,
entry->start_label, entry->end_label,
entry->exception_handler_label);
}
if (count)
{
/* Ending marker for table. */
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
output_exception_table_entry (asm_out_file,
constm1_rtx, constm1_rtx, constm1_rtx);
}
/* Ending marker for table. */
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
output_exception_table_entry (asm_out_file,
constm1_rtx, constm1_rtx, constm1_rtx);
#endif /* TRY_NEW_EH */
return count;
}
void
......
......@@ -157,8 +157,8 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
/* 348 - 351 */
/* Subroutine of emit_base_init. */
static void
perform_member_init (member, name, init, explicit)
tree member, name, init;
perform_member_init (member, name, init, explicit, protect_list)
tree member, name, init, *protect_list;
int explicit;
{
tree decl;
......@@ -223,27 +223,44 @@ perform_member_init (member, name, init, explicit)
}
}
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. */
static tree
sort_member_init (t)
tree t;
{
extern int warn_reorder;
tree x, member, name, field, init;
tree init_list = NULL_TREE;
tree fields_to_unmark = NULL_TREE;
int found;
int last_pos = 0;
tree last_field;
for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))
{
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)
{
/* If we cleared this out, then pay no attention to it. */
......@@ -266,17 +283,9 @@ sort_member_init (t)
if (field == member)
{
/* See if we already found an initializer for this field. */
if (found)
{
if (DECL_NAME (field))
cp_error ("multiple initializations given for member `%D'",
field);
continue;
}
else
if (warn_reorder)
{
if (pos < last_pos && warn_reorder)
if (pos < last_pos)
{
cp_warning_at ("member initializers for `%#D'", last_field);
cp_warning_at (" and `%#D'", field);
......@@ -286,78 +295,193 @@ sort_member_init (t)
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. */
TREE_PURPOSE (x) = NULL_TREE;
found = 1;
break;
x = build_tree_list (name, TREE_VALUE (x));
goto got_it;
}
}
/* 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
symmetrical. */
if (! found)
init_list = chainon (init_list, build_tree_list (NULL_TREE, NULL_TREE));
x = 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))
{
if (TREE_PURPOSE (x))
name = TREE_PURPOSE (x);
if (name)
{
name = TREE_PURPOSE (x);
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)
if (purpose_member (name, init_list))
{
field = TREE_VALUE (field);
if (decl_type_context (field) != current_class_type)
cp_error ("field `%D' not in immediate context", field);
cp_error ("multiple initializations given for member `%D'",
IDENTIFIER_CLASS_VALUE (name));
continue;
}
init_list = chainon (init_list,
build_tree_list (name, TREE_VALUE (x)));
TREE_PURPOSE (x) = NULL_TREE;
}
}
#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. */
return init_list;
}
/* 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
static void
sort_base_init (t, rbase_ptr, vbase_ptr)
tree t, *rbase_ptr, *vbase_ptr;
{
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
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))
error ("multiple initializations given for member `%s'",
IDENTIFIER_POINTER (DECL_NAME (field)));
continue;
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;
TREE_HAS_CONSTRUCTOR (field) = 1;
fields_to_unmark = tree_cons (NULL_TREE, field, fields_to_unmark);
/* 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))
{
tree v = CLASSTYPE_VBASECLASSES (t);
while (BINFO_TYPE (v) != BINFO_TYPE (binfo))
v = TREE_CHAIN (v);
perform_member_init (field, name, init, 1);
TREE_PURPOSE (x) = NULL_TREE;
vbases = tree_cons (v, TREE_VALUE (x), vbases);
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. */
while (fields_to_unmark)
/* Now walk through our regular bases and make sure they're initialized. */
for (i = 0; i < n_baseclasses; ++i)
{
TREE_HAS_CONSTRUCTOR (TREE_VALUE (fields_to_unmark)) = 0;
/* XXX is this a memory leak? */
fields_to_unmark = TREE_CHAIN (fields_to_unmark);
tree base_binfo = TREE_VEC_ELT (binfos, i);
int pos;
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
......@@ -385,13 +509,14 @@ emit_base_init (t, immediately)
{
extern tree in_charge_identifier;
tree member, vbases;
tree init_list;
int pass, start;
tree member, x;
tree mem_init_list;
tree rbase_init_list, vbase_init_list;
tree t_binfo = TYPE_BINFO (t);
tree binfos = BINFO_BASETYPES (t_binfo);
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)
{
......@@ -407,172 +532,31 @@ emit_base_init (t, immediately)
emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),
DECL_SOURCE_LINE (current_function_decl));
start = ! TYPE_USES_VIRTUAL_BASECLASSES (t);
for (pass = start; pass < 2; pass++)
{
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;
mem_init_list = sort_member_init (t);
current_member_init_list = NULL_TREE;
member = convert_pointer_to (binfo, current_class_decl);
expand_aggr_init_1 (binfo, 0,
build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (binfo), LOOKUP_NORMAL);
expand_cleanups_to (NULL_TREE);
}
sort_base_init (t, &rbase_init_list, &vbase_init_list);
current_base_init_list = NULL_TREE;
if (pass == 0)
{
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
tree vbases;
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
if (DECL_NAME (current_function_decl) == NULL_TREE
&& TREE_CHAIN (first_arg) != NULL_TREE)
{
/* If there are virtual baseclasses without initialization
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 ();
}
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
have not yet been initialized, and unmark baseclasses which
have been initialized. */
/* Now, perform initialization of non-virtual base classes. */
for (i = 0; i < n_baseclasses; i++)
{
tree base = current_class_decl;
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. */
my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo);
......@@ -580,109 +564,113 @@ emit_base_init (t, immediately)
BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
#endif
if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
{
if (! TREE_VIA_VIRTUAL (base_binfo)
&& ! BINFO_BASEINIT_MARKED (base_binfo))
{
tree ref;
if (TREE_PURPOSE (rbase_init_list))
init = TREE_VALUE (rbase_init_list);
else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
init = NULL_TREE;
if (BINFO_OFFSET_ZEROP (base_binfo))
base = build1 (NOP_EXPR,
TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
current_class_decl);
else
base = build (PLUS_EXPR,
TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
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);
}
if (init != void_list_node)
{
member = convert_pointer_to (base_binfo, current_class_decl);
expand_aggr_init_1 (base_binfo, 0,
build_indirect_ref (member, NULL_PTR), init,
BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
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))
&& BINFO_BASETYPES (base_binfo) != NULL_TREE
&& TREE_VEC_LENGTH (BINFO_BASETYPES (base_binfo)) == 1)
{
/* ?? 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);
}
start_protect ();
protect_list = tree_cons (NULL_TREE,
build_partial_cleanup_for (base_binfo),
protect_list);
}
rbase_init_list = TREE_CHAIN (rbase_init_list);
}
/* Initialize all the virtual function table fields that
do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
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
do not come from virtual base classes. */
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))
{
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. */
if (have_init_list)
if (TREE_PURPOSE (mem_init_list))
{
if (TREE_PURPOSE (init_list))
{
name = TREE_PURPOSE (init_list);
init = TREE_VALUE (init_list);
from_init_list = 1;
name = TREE_PURPOSE (mem_init_list);
init = TREE_VALUE (mem_init_list);
from_init_list = 1;
if (TREE_STATIC (member))
{
cp_error ("field `%#D' is static; only point of initialization is its declaration",
member);
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);
/* 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);
}
if (! from_init_list)
else
{
/* 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);
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)
{
......@@ -750,14 +738,13 @@ static void
expand_aggr_vbase_init_1 (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);
if (init)
init = TREE_PURPOSE (init);
init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
expand_cleanups_to (NULL_TREE);
CLEAR_BINFO_VBASE_INIT_MARKED (binfo);
}
/* Initialize this object's virtual base class pointers. This must be
......@@ -781,38 +768,14 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list)
if (result)
expand_expr_stmt (build_compound_expr (result));
/* Mark everything as having an initializer
(either explicit or default). */
for (vbases = CLASSTYPE_VBASECLASSES (type);
vbases; vbases = TREE_CHAIN (vbases))
SET_BINFO_VBASE_INIT_MARKED (vbases);
/* First, initialize baseclasses which could be baseclasses
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);
}
for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
vbases = TREE_CHAIN (vbases))
{
tree tmp = purpose_member (vbases, result);
expand_aggr_vbase_init_1 (vbases, exp,
TREE_OPERAND (TREE_VALUE (tmp), 0),
init_list);
}
}
}
......@@ -862,7 +825,7 @@ member_init_ok_or_else (field, type, member_name)
if (field == NULL_TREE)
{
cp_error ("class `%T' does not have any field named `%s'", type,
member_name);
member_name);
return 0;
}
if (DECL_CONTEXT (field) != type
......@@ -872,6 +835,13 @@ member_init_ok_or_else (field, type, member_name)
field);
return 0;
}
if (TREE_STATIC (field))
{
cp_error ("field `%#D' is static; only point of initialization is its declaration",
field);
return 0;
}
return 1;
}
......@@ -1209,7 +1179,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
tree rval;
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;
if (parms)
......@@ -2044,6 +2015,12 @@ build_offset_ref (cname, name)
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. */
if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
my_friendly_abort (53);
......@@ -2085,7 +2062,7 @@ get_member_function (exp_addr_ptr, exp, member)
if (UNITS_PER_WORD <= 1)
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,
build_tree_list (NULL_TREE, e1)));
e1 = save_expr (e1);
......@@ -2240,7 +2217,7 @@ resolve_offset_ref (exp)
}
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);
/* NOTREACHED */
......@@ -2322,7 +2299,13 @@ is_friend (type, supplicant)
{
tree list = DECL_FRIENDLIST (TYPE_NAME (type));
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))
{
if (name == TREE_PURPOSE (list))
......@@ -2353,8 +2336,14 @@ is_friend (type, supplicant)
}
{
tree context = declp ? DECL_CLASS_CONTEXT (supplicant)
: DECL_CONTEXT (TYPE_NAME (supplicant));
tree context;
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)
return is_friend (type, context);
......@@ -2508,7 +2497,7 @@ make_friend_class (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));
return;
}
......@@ -2803,7 +2792,7 @@ build_new (placement, decl, init, use_global_new)
{
tree type, true_type, size, rval;
tree nelts;
tree alloc_expr;
tree alloc_expr, alloc_temp;
int has_array = 0;
enum tree_code code = NEW_EXPR;
......@@ -2927,6 +2916,12 @@ build_new (placement, decl, init, use_global_new)
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
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. */
......@@ -2956,7 +2951,7 @@ build_new (placement, decl, init, use_global_new)
if (true_type == void_type_node)
{
error ("invalid type for new: `void'");
error ("invalid type `void' for new");
return error_mark_node;
}
......@@ -3032,12 +3027,19 @@ build_new (placement, decl, init, use_global_new)
TREE_CALLS_NEW (rval) = 1;
}
if (flag_check_new)
if (flag_check_new && rval)
{
if (rval)
rval = save_expr (rval);
alloc_expr = rval;
/* For array new, we need to make sure that the call to new is
not expanded as part of the RTL_EXPR for the initialization,
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
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)
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);
rval = build_conditional_expr (ifexp, rval, alloc_expr);
/* Did we modify the storage? */
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))
......@@ -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);
expand_start_loop_continue_elsewhere (1);
......@@ -3394,7 +3403,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
expand_assignment (base2,
build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0);
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));
if (obey_regdecls)
......@@ -3975,7 +3984,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
body = tree_cons (NULL_TREE,
build (EXIT_EXPR, void_type_node,
build (EQ_EXPR, integer_type_node, base, tbase)),
build (EQ_EXPR, boolean_type_node, base, tbase)),
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,
/* Outermost wrapper: If pointer is null, punt. */
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 = build1 (NOP_EXPR, void_type_node, body);
......
......@@ -4541,8 +4541,6 @@ real_yylex ()
{ value = '}'; goto done; }
else if (c == '%' && c1 == ':')
{ value = '#'; goto done; }
else if (c == ':' && c1 == '>')
{ value = ']'; goto done; }
nextchar = c1;
token_buffer[1] = 0;
......@@ -4560,6 +4558,11 @@ real_yylex ()
value = SCOPE;
yylval.itype = 1;
}
else if (c == '>')
{
value = ']';
goto done;
}
else
{
nextchar = c;
......
......@@ -2211,12 +2211,14 @@ synthesize_method (fndecl)
int nested = (current_function_decl != NULL_TREE);
int toplev = (decl_function_context (fndecl) == NULL_TREE);
char *f = input_filename;
tree base = DECL_CLASS_CONTEXT (fndecl);
if (nested)
push_cp_function_context (toplev);
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);
store_parm_decls ();
......
......@@ -1074,8 +1074,10 @@ unary_expr:
{
tree t = TREE_VALUE ($2);
if (t != NULL_TREE
&& TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids using sizeof() on a function");
&& ((TREE_TYPE (t)
&& 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)); }
| SIZEOF '(' type_id ')' %prec HYPERUNARY
......@@ -1142,7 +1144,7 @@ new_initializer:
syntactically valid but semantically invalid. */
| '=' init
{
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ forbids initialization of new expression with `='");
$$ = $2;
}
......@@ -1169,7 +1171,7 @@ cast_expr:
{
tree init = build_nt (CONSTRUCTOR, NULL_TREE,
nreverse ($3));
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ forbids constructor-expressions");
/* Indicate that this was a GNU C constructor expression. */
TREE_HAS_CONSTRUCTOR (init) = 1;
......@@ -1289,7 +1291,6 @@ unqualified_id:
expr_or_declarator:
notype_unqualified_id
| notype_qualified_id
| '*' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); }
| '&' expr_or_declarator %prec UNARY
......@@ -1301,9 +1302,6 @@ expr_or_declarator:
direct_notype_declarator:
complex_direct_notype_declarator
| notype_unqualified_id
| notype_qualified_id
{ push_nested_class (TREE_TYPE (OP0 ($$)), 3);
TREE_COMPLEXITY ($$) = current_class_depth; }
| '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); }
;
......@@ -1360,7 +1358,7 @@ primary:
$<ttype>$ = expand_start_stmt_expr (); }
compstmt ')'
{ tree rtl_exp;
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ forbids braced-groups within expressions");
rtl_exp = expand_end_stmt_expr ($<ttype>2);
/* The statements have side effects, so the group does. */
......@@ -1554,7 +1552,7 @@ primary:
| object unqualified_id %prec UNARY
{ got_object = NULL_TREE;
$$ = build_component_ref ($$, $2, NULL_TREE, 1); }
| object qualified_id %prec UNARY
| object overqualified_id %prec UNARY
{ got_object = NULL_TREE;
$$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
| object unqualified_id '(' nonnull_exprlist ')'
......@@ -1589,7 +1587,7 @@ primary:
(LOOKUP_NORMAL|LOOKUP_AGGR));
#endif
}
| object qualified_id '(' nonnull_exprlist ')'
| object overqualified_id '(' nonnull_exprlist ')'
{
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
......@@ -1601,7 +1599,7 @@ primary:
else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
}
| object qualified_id LEFT_RIGHT
| object overqualified_id LEFT_RIGHT
{
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
......@@ -1617,8 +1615,9 @@ primary:
| object '~' TYPESPEC LEFT_RIGHT
{
got_object = NULL_TREE;
if (TREE_CODE (TREE_TYPE ($1))
!= TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))
if (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);
$$ = convert (void_type_node, $1);
}
......@@ -1654,7 +1653,7 @@ primary_no_id:
}
$<ttype>$ = expand_start_stmt_expr (); }
compstmt ')'
{ if (flag_ansi)
{ if (pedantic)
pedwarn ("ANSI C++ forbids braced-groups within expressions");
$$ = expand_end_stmt_expr ($<ttype>2); }
| primary_no_id '(' nonnull_exprlist ')'
......@@ -1816,6 +1815,8 @@ typed_declspecs1:
{ $$ = decl_tree_cons (NULL_TREE, $2, $$); }
| typespec reserved_declspecs %prec HYPERUNARY
{ $$ = decl_tree_cons (NULL_TREE, $$, $2); }
| typespec reserved_typespecquals reserved_declspecs
{ $$ = decl_tree_cons (NULL_TREE, $$, chainon ($2, $3)); }
| declmods typespec reserved_declspecs
{ $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
| declmods typespec reserved_typespecquals
......@@ -1902,11 +1903,11 @@ typespec: structsp
| complete_type_name
| TYPEOF '(' expr ')'
{ $$ = TREE_TYPE ($3);
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ forbids `typeof'"); }
| TYPEOF '(' type_id ')'
{ $$ = groktypename ($3);
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ forbids `typeof'"); }
| SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3);
......@@ -2763,7 +2764,7 @@ new_type_id:
non-constant dimension. */
| '(' type_id ')' '[' expr ']'
{
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
$$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5);
$$ = build_decl_list (TREE_PURPOSE ($2), $$);
......@@ -2905,6 +2906,9 @@ complex_direct_notype_declarator:
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| notype_qualified_id
{ push_nested_class (TREE_TYPE (OP0 ($$)), 3);
TREE_COMPLEXITY ($$) = current_class_depth; }
;
qualified_id:
......@@ -3107,7 +3111,7 @@ errstmt: error ';'
maybe_label_decls:
/* empty */
| label_decls
{ if (flag_ansi)
{ if (pedantic)
pedwarn ("ANSI C++ forbids label declarations"); }
;
......@@ -3323,7 +3327,7 @@ simple_stmt:
register tree label
= build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ forbids range expressions in switch statement");
if (value1 != error_mark_node
&& value2 != error_mark_node)
......
......@@ -755,6 +755,8 @@ uses_template_parms (t)
case REFERENCE_TYPE:
return uses_template_parms (TREE_TYPE (t));
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (t))
return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t));
case UNION_TYPE:
if (!TYPE_NAME (t))
return 0;
......@@ -1153,9 +1155,8 @@ tsubst (t, args, nargs, in_decl)
&& type != integer_type_node
&& type != void_type_node
&& type != char_type_node)
type = cp_build_type_variant (tsubst (type, args, nargs, in_decl),
TYPE_READONLY (type),
TYPE_VOLATILE (type));
type = tsubst (type, args, nargs, in_decl);
switch (TREE_CODE (t))
{
case RECORD_TYPE:
......@@ -1679,12 +1680,16 @@ instantiate_template (tmpl, targ_ptr)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
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);
fndecl; fndecl = TREE_CHAIN (fndecl))
{
tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);
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;
/* Here, we have a match. */
......@@ -2036,6 +2041,15 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
return 1;
if (arg == unknown_type_node)
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 (TREE_CODE (arg) == VAR_DECL)
arg = TREE_TYPE (arg);
......
......@@ -1740,6 +1740,9 @@ make_deep_copy (t)
case ARRAY_TYPE:
return build_array_type (make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TYPE_DOMAIN (t)));
case INTEGER_TYPE:
return build_index_type (make_deep_copy (TYPE_MAX_VALUE (t)));
case OFFSET_TYPE:
return build_offset_type (make_deep_copy (TYPE_OFFSET_BASETYPE (t)),
make_deep_copy (TREE_TYPE (t)));
......@@ -1749,6 +1752,7 @@ make_deep_copy (t)
build_function_type
(make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TREE_CHAIN (TYPE_ARG_TYPES (t)))));
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
......
......@@ -719,7 +719,28 @@ comptypes (type1, type2, strict)
return 1;
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;
}
......@@ -1834,26 +1855,6 @@ build_array_ref (array, idx)
return error_mark_node;
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
&& TREE_CODE (array) != INDIRECT_REF)
......@@ -1902,19 +1903,19 @@ build_array_ref (array, idx)
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))
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;
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
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)));
......@@ -2122,7 +2123,7 @@ build_x_function_call (function, params, decl)
decl = C_C_D;
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));
params = tree_cons (NULL_TREE, decl_addr, params);
return build_function_call (function, params);
......@@ -2184,9 +2185,8 @@ build_x_function_call (function, params, decl)
instance to use, if the member points to a virtual member. */
tree
get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
get_member_function_from_ptrfunc (instance_ptrptr, function)
tree *instance_ptrptr;
tree instance;
tree function;
{
if (TREE_CODE (function) == OFFSET_REF)
......@@ -2200,7 +2200,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
tree index = save_expr (build_component_ref (function,
index_identifier,
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));
tree delta = convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier, 0, 0));
......@@ -2209,9 +2209,16 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
tree e3;
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. */
instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
build_unary_op (ADDR_EXPR, instance, 0));
instance
= convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
instance_ptr);
if (instance == error_mark_node)
return instance;
......@@ -2238,9 +2245,8 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
delta, 1);
}
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (*instance_ptrptr),
*instance_ptrptr,
delta);
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
if (flag_vtable_thunks)
e2 = aref;
else
......@@ -2249,6 +2255,12 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (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;
}
......@@ -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);
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
......@@ -2715,7 +2727,6 @@ build_binary_op (code, arg1, arg2, convert_p)
tree arg1, arg2;
int convert_p;
{
tree type1, type2;
tree args[2];
args[0] = arg1;
......@@ -2724,64 +2735,39 @@ build_binary_op (code, arg1, arg2, convert_p)
if (convert_p)
{
tree args_save [2];
tree type0, type1;
args[0] = args_save [0] = default_conversion (args[0]);
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]))
{
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]);
}
else if (type_unknown_p (args[1]))
{
args[1] = require_instantiated_type (TREE_TYPE (args[0]),
args[1],
args[1] = require_instantiated_type (type0, args[1],
error_mark_node);
args[1] = default_conversion (args[1]);
}
type1 = TREE_TYPE (args[0]);
type2 = TREE_TYPE (args[1]);
if (IS_AGGR_TYPE_2 (type1, type2))
if (IS_AGGR_TYPE (type0) || IS_AGGR_TYPE (type1))
{
/* Try to convert this to something reasonable. */
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,
TREE_TYPE (arg1), TREE_TYPE (arg2));
return error_mark_node;
}
if (try == error_mark_node)
error ("ambiguous pointer conversion");
args[convert_index] = try;
}
if (args[0] == args_save[0])
args[0] = arg1;
if (args[1] == args_save[1])
......@@ -3094,7 +3080,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
{
tree base = common_base_type (tt0, tt1);
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)
{
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)
if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE
&& tree_int_cst_lt (TYPE_SIZE (type0), TYPE_SIZE (type1)))
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)
{
......@@ -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
&& integer_zerop (op1))
{
op1 = null_pointer_node;
if (pedantic)
pedwarn ("ordered comparison of pointer with integer zero");
}
op1 = null_pointer_node;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
{
op0 = null_pointer_node;
if (pedantic)
pedwarn ("ANSI C++ forbids ordered comparison of pointer with integer zero");
}
op0 = null_pointer_node;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
if (pedantic)
......@@ -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
casts will be considered, but default promotions won't be. */
if (TREE_UNSIGNED (comp_type)
&& ((op0_signed
&& (TREE_CODE (op0) != INTEGER_CST
|| (TREE_CODE (op0) == INTEGER_CST
&& INT_CST_LT (op0, integer_zero_node))))
|| (op1_signed
&& (TREE_CODE (op1) != INTEGER_CST
|| (TREE_CODE (op1) == INTEGER_CST
&& INT_CST_LT (op1, integer_zero_node))))))
&& ((op0_signed && (TREE_CODE (orig_op0) != INTEGER_CST
|| tree_int_cst_sgn (orig_op0) == -1))
|| (op1_signed && (TREE_CODE (orig_op1) != INTEGER_CST
|| tree_int_cst_sgn (orig_op1) == -1))))
warning ("comparison between signed and unsigned");
/* Warn if two unsigned values are being compared in a size
......@@ -3830,121 +3806,46 @@ build_unary_op (code, xarg, noconvert)
/* No default_conversion here. It causes trouble for ADDR_EXPR. */
register tree arg = xarg;
register tree argtype = 0;
register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
char *errstring = NULL;
tree val;
int isaggrtype;
if (typecode == ERROR_MARK)
if (arg == 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)
{
case CONVERT_EXPR:
/* This is used for unary plus, because a CONVERT_EXPR
is enough to prevent anybody from looking inside for
associativity, but won't generate any code. */
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
errstring = "wrong type argument to unary plus";
else if (!noconvert)
arg = default_conversion (arg);
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 (!(arg = build_expr_type_conversion
(WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, 1)))
errstring = "wrong type argument to unary plus";
else
{
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;
arg = default_conversion (arg);
arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
}
break;
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
errstring = "wrong type argument to unary minus";
case NEGATE_EXPR:
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
errstring = "wrong type argument to unary minus";
else if (!noconvert)
arg = default_conversion (arg);
break;
case BIT_NOT_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)
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";
if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, arg, 1)))
errstring = "wrong type argument to bit-complement";
else if (!noconvert)
arg = default_conversion (arg);
break;
case ABS_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)
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";
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
errstring = "wrong type argument to abs";
else if (!noconvert)
arg = default_conversion (arg);
break;
......@@ -3973,21 +3874,8 @@ build_unary_op (code, xarg, noconvert)
/* Report invalid types. */
if (typecode == OFFSET_TYPE)
{
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 (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER,
arg, 1)))
{
if (code == PREINCREMENT_EXPR)
errstring ="no pre-increment operator for type";
......@@ -4024,7 +3912,7 @@ build_unary_op (code, xarg, noconvert)
/* Compute the increment. */
if (typecode == POINTER_TYPE)
if (TREE_CODE (argtype) == POINTER_TYPE)
{
enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
if (TYPE_SIZE (TREE_TYPE (argtype)) == 0)
......@@ -4081,7 +3969,37 @@ build_unary_op (code, xarg, noconvert)
? "increment" : "decrement")))
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;
return convert (result_type, val);
}
......@@ -4090,7 +4008,8 @@ build_unary_op (code, xarg, noconvert)
/* Note that this operation never does default_conversion
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);
TREE_REFERENCE_EXPR (arg) = 1;
......@@ -4194,13 +4113,12 @@ build_unary_op (code, xarg, noconvert)
;
/* Anything not already handled and not a true memory reference
is an error. */
else if (typecode != FUNCTION_TYPE
&& typecode != METHOD_TYPE
else if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE
&& !lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
/* Ordinary case; arg is a COMPONENT_REF or a decl. */
argtype = TREE_TYPE (arg);
/* If the lvalue is const or volatile,
merge that into the type that the address will point to. */
if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
......@@ -4900,10 +4818,25 @@ build_compound_expr (list)
rest = build_compound_expr (TREE_CHAIN (list));
/* When pedantic, a compound expression can be neither an lvalue
nor an integer constant expression. */
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
return rest;
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
/* the left-hand operand of a comma expression is like an expression
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),
break_out_cleanups (TREE_VALUE (list)), rest);
......@@ -5629,8 +5562,6 @@ build_modify_expr (lhs, modifycode, rhs)
cp_error ("`%T' does not define operator=", lhstype);
else if (! TYPE_HAS_REAL_ASSIGNMENT (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)))
/* Do the default thing */;
else
......@@ -5697,7 +5628,11 @@ build_modify_expr (lhs, modifycode, rhs)
newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
}
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
{
......@@ -6008,18 +5943,32 @@ build_modify_expr (lhs, modifycode, rhs)
}
else
newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
NULL_TREE, 0);
if (flag_elide_constructors == 0
&& TREE_CODE (newrhs) == CALL_EXPR
&& TREE_ADDRESSABLE (lhstype))
NULL_TREE, 0);
if (TREE_CODE (newrhs) == CALL_EXPR
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
newrhs = build_cplus_new (lhstype, newrhs, 0);
if (TREE_CODE (newrhs) == TARGET_EXPR)
{
/* Can't initialized directly from a CALL_EXPR, since
we don't know about what doesn't alias what. */
/* Can't initialize directly from a TARGET_EXPR, since that would
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);
newrhs = build (COMPOUND_EXPR, lhstype,
build_modify_expr (temp, INIT_EXPR, newrhs),
temp);
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
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)
}
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,
integer_zero_node,
......@@ -6180,7 +6129,7 @@ get_delta_difference (from, to, force)
}
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);
}
......@@ -6241,7 +6190,7 @@ build_ptrmemfunc (type, pfn, force)
force);
delta = build_binary_op (PLUS_EXPR, delta, ndelta, 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 (NULL_TREE, delta,
......
......@@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
/* First used: 0 (reserved), Last used: 364. Free: */
/* First used: 0 (reserved), Last used: 366. Free: */
static int abortcount = 0;
......@@ -855,6 +855,14 @@ digest_init (type, init, tail)
}
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,
"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