From b7484fbe2bf67c98dbff6f270dbc41376c0fdbaf Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Wed, 15 Mar 1995 23:03:59 +0000 Subject: [PATCH] 58th Cygnus<->FSF merge From-SVN: r9186 --- gcc/cp/ChangeLog | 360 ++++++++++++++++++++++- gcc/cp/Makefile.in | 5 +- gcc/cp/call.c | 14 +- gcc/cp/class.c | 16 +- gcc/cp/cp-tree.h | 21 +- gcc/cp/cvt.c | 330 +++++++++++++-------- gcc/cp/decl.c | 214 +++++++++----- gcc/cp/decl2.c | 167 ++++++----- gcc/cp/error.c | 15 +- gcc/cp/except.c | 65 +++-- gcc/cp/init.c | 709 +++++++++++++++++++++++---------------------- gcc/cp/lex.c | 7 +- gcc/cp/method.c | 4 +- gcc/cp/parse.y | 44 +-- gcc/cp/pt.c | 22 +- gcc/cp/tree.c | 4 + gcc/cp/typeck.c | 395 +++++++++++-------------- gcc/cp/typeck2.c | 10 +- 18 files changed, 1459 insertions(+), 943 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0cbb5de18211..aa13e96d2062 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,80 @@ +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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * decl.c (finish_function): Change test for calling + mark_inline_for_output. + +Wed Mar 1 11:23:46 1995 Jason Merrill + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * cvt.c (convert_to_aggr): Lose misleading shortcut. + +Sun Feb 26 17:27:32 1995 Doug Evans + + * 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 + + * 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 + + * except.c (end_protect_partials): Do it the right way. + +Wed Feb 22 15:42:56 1995 Jason Merrill + + * 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 + + * 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 +Tue Feb 21 18:36:55 1995 Mike Stump + + * 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 + + * 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 - * 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 @@ -518,6 +852,11 @@ Tue Jan 24 16:36:31 1995 Jason Merrill * 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 * 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 diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index f94d82424b02..dd267f378414 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -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) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index be7cf3c64fad..3079d147734c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.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 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b0332e9af767..f296dc9b421b 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 766e308e3707..528c23a03d6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index ce01c662ccfa..e87b168a2332 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -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. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index aad3dfb04b0a..1ef0ebd8f19a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index b0e5c00c5694..6cc04204cd9a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 2be11e0d90da..215dd1792403 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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)); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 6fc23ec85cdf..607d5034f2a5 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -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 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 63a909cb4578..01c5bcb896a3 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 89a90ded3fac..6cbc00671b29 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index f185ebe17695..29b64e69e3dd 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.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 (); diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index c51c756700a3..d9430eca6cb1 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -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: $$ = 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 ($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: } $$ = expand_start_stmt_expr (); } compstmt ')' - { if (flag_ansi) + { if (pedantic) pedwarn ("ANSI C++ forbids braced-groups within expressions"); $$ = expand_end_stmt_expr ($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) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5804bb6b87c7..5ac3b633b3f1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 4424423b07be..763d768148ca 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b21bbe94567f..b7f51d2a3fd9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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, diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 8a446c18f370..38015215f91e 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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); -- 2.43.5